windows和Linux上利用vlc外掛獲取rtsp視訊流解碼資料
Linux上實現:
執行下面程式碼前確保Linux上已經安裝好vlc以及相應外掛,我編譯並安裝了vlc-2.0.1版本,但最終仍然不能開啟rtsp視訊流,不清楚原因,但是本地視訊還是可以獲取到原始視訊流的。
程式碼裡面用到了SDL來顯示視訊,我下載並編譯安裝了SDL-1.2.15的原始碼。
/* libSDL and libVLC sample code * Copyright ? 2008 Sam Hocevar <sam@zoy.org> * license: [http://en.wikipedia.org/wiki/WTFPL WTFPL] */ #include <stdio.h> #include <stdint.h> #include <math.h> #include <stdlib.h> #include <assert.h> #include <SDL/SDL.h> #include <SDL/SDL_mutex.h> #include <vlc/vlc.h> #define WIDTH 640 #define HEIGHT 480 #define VIDEOWIDTH 320 #define VIDEOHEIGHT 240 struct ctx { SDL_Surface *surf; SDL_mutex *mutex; }; static void *lock(void *data, void **p_pixels) { #if 1 struct ctx *ctx = data; SDL_LockMutex(ctx->mutex); SDL_LockSurface(ctx->surf); *p_pixels = ctx->surf->pixels; #endif return NULL; /* picture identifier, not needed here */ } static void unlock(void *data, void *id, void *const *p_pixels) { #if 1 struct ctx *ctx = data; /* VLC just rendered the video, but we can also render stuff */ uint16_t *pixels = *p_pixels; int x, y; //memset(pixels, 0x00, 320*240); for(y = 10; y < 40; y++) for(x = 10; x < 40; x++) if(x < 13 || y < 13 || x > 36 || y > 36) pixels[y * VIDEOWIDTH + x] = 0xffff; else pixels[y * VIDEOWIDTH + x] = 0x0; #if 0 FILE *fp = NULL; fp = fopen("data.yuv", "ab+"); if(fp != NULL) { fwrite(pixels, 320*240*3, 1, fp); fclose(fp); printf("write a frame.\r\n"); } #endif SDL_UnlockSurface(ctx->surf); SDL_UnlockMutex(ctx->mutex); assert(id == NULL); /* picture identifier, not needed here */ #endif } static void display(void *data, void *id) { /* VLC wants to display the video */ (void) data; printf("display a frame.\r\n"); assert(id == NULL); } int main(int argc, char *argv[]) { libvlc_instance_t *libvlc; libvlc_media_t *m; libvlc_media_player_t *mp; char const *vlc_argv[] = { "--no-audio", /* skip any audio track */ "--no-xlib", /* tell VLC to not use Xlib */ }; int vlc_argc = sizeof(vlc_argv) / sizeof(*vlc_argv); SDL_Surface *screen, *empty; SDL_Event event; SDL_Rect rect; int done = 0, action = 0, pause = 0, n = 0; struct ctx ctx; if(argc < 2) { printf("Usage: %s <filename>\n", argv[0]); return EXIT_FAILURE; } /* * Initialise libSDL */ if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_EVENTTHREAD) == -1) { printf("cannot initialize SDL\n"); return EXIT_FAILURE; } empty = SDL_CreateRGBSurface(SDL_SWSURFACE, VIDEOWIDTH, VIDEOHEIGHT, 16, 0, 0, 0, 0); #if 1 ctx.surf = SDL_CreateRGBSurface(SDL_SWSURFACE, VIDEOWIDTH, VIDEOHEIGHT, 16, 0x001f, 0x07e0, 0xf800, 0); #else ctx.surf = SDL_CreateRGBSurface(SDL_SWSURFACE, VIDEOWIDTH, VIDEOHEIGHT, 16, 0xff000000, 0x00ff0000, 0x0000ff00, 0); #endif ctx.mutex = SDL_CreateMutex(); int options = SDL_ANYFORMAT | SDL_HWSURFACE | SDL_DOUBLEBUF; screen = SDL_SetVideoMode(WIDTH, HEIGHT, 0, options); if(!screen) { printf("cannot set video mode\n"); return EXIT_FAILURE; } /* * Initialise libVLC */ libvlc = libvlc_new(vlc_argc, vlc_argv); m = libvlc_media_new_path(libvlc, argv[1]); mp = libvlc_media_player_new_from_media(m); libvlc_media_release(m); libvlc_video_set_callbacks(mp, lock, unlock, display, &ctx); libvlc_video_set_format(mp, "RV16", VIDEOWIDTH, VIDEOHEIGHT, VIDEOWIDTH*2); libvlc_media_player_play(mp); /* * Main loop */ rect.w = 0; rect.h = 0; while(!done) { action = 0; /* Keys: enter (fullscreen), space (pause), escape (quit) */ while( SDL_PollEvent( &event ) ) { switch(event.type) { case SDL_QUIT: done = 1; break; case SDL_KEYDOWN: action = event.key.keysym.sym; break; } } switch(action) { case SDLK_ESCAPE: done = 1; break; case SDLK_RETURN: options ^= SDL_FULLSCREEN; screen = SDL_SetVideoMode(WIDTH, HEIGHT, 0, options); break; case ' ': pause = !pause; break; } rect.x = (int)((1. + .5 * sin(0.03 * n)) * (WIDTH - VIDEOWIDTH) / 2); rect.y = (int)((1. + .5 * cos(0.03 * n)) * (HEIGHT - VIDEOHEIGHT) / 2); if(!pause) n++; /* Blitting the surface does not prevent it from being locked and * written to by another thread, so we use this additional mutex. */ SDL_LockMutex(ctx.mutex); SDL_BlitSurface(ctx.surf, NULL, screen, &rect); SDL_UnlockMutex(ctx.mutex); SDL_Flip(screen); SDL_Delay(10); SDL_BlitSurface(empty, NULL, screen, &rect); } /* * Stop stream and clean up libVLC */ libvlc_media_player_stop(mp); libvlc_media_player_release(mp); libvlc_release(libvlc); /* * Close window and clean up libSDL */ SDL_DestroyMutex(ctx.mutex); SDL_FreeSurface(ctx.surf); SDL_FreeSurface(empty); SDL_Quit(); return 0; } |
Windows上的實現:
上面提到的VLC的外掛和SDL,在Windows上同樣需要,我用vlc2.0.1在Linux上編譯了windows版本的vlc,這樣相應的庫和外掛就都有了,SDL可以到官網下載。
由於vlc的哪個標頭檔案中包含了stdint.h這個標頭檔案,這個標頭檔案說是C99標準標頭檔案,vc裡面沒有,vs2010裡面有,所以用vs2010建立的工程,在工程中新增好vlc和SDL的include、lib。並且將vlc和SDL相應用到的DLL檔案複製到工程的Debug或Release目錄,還要將vlc的plugins目錄複製到Debug或Release目錄,要不然找不到vlc外掛。
#include "stdafx.h"
#include <stdio.h>
#include <tchar.h>
#include <time.h>
#include <windows.h>
#include <stdlib.h>
#include <assert.h>
#include <SDL.h>
#include <vlc/vlc.h>
#pragma comment (lib, "libvlc.lib")
#pragma comment (lib, "libvlccore.lib")
#pragma comment (lib, "SDL.lib")
using namespace std;
#if 0
//這部分程式碼是讀取本地檔案然後顯示,並沒有用到SDL
int _tmain(int argc,
_TCHAR* argv[])
{
libvlc_instance_t * vlc_ins = NULL;
libvlc_media_player_t * vlc_player = NULL;
libvlc_media_t * vlc_media = NULL;
const char *
vlc_args[] =
{
"-I",
"dummy",
"--ignore-config",
"--extraintf=logger",
"--verbose=2",
};
vlc_ins = libvlc_new( sizeof(vlc_args)/sizeof (vlc_args[0]),
vlc_args);
if(vlc_ins
!= NULL)
{
vlc_player = libvlc_media_player_new(vlc_ins);
if(vlc_player
!= NULL)
{
vlc_media = libvlc_media_new_path(vlc_ins, "rtsp://192.0.0.64/av0_0" );
if(vlc_media
!= NULL)
{
libvlc_media_parse(vlc_media);
libvlc_time_t duration = libvlc_media_get_duration(vlc_media);
libvlc_media_track_info_t *media_tracks = NULL;
int trackCount
= libvlc_media_get_tracks_info(vlc_media, &media_tracks);
//
free(media_tracks); // crash?
libvlc_media_player_set_media(vlc_player, vlc_media);
libvlc_media_player_set_hwnd(vlc_player, ::GetDesktopWindow());
libvlc_media_player_play(vlc_player);
time_t last_time = time(NULL);
while((time(NULL)
< (last_time + 20)))
{
Sleep(10);
libvlc_time_t play_time = libvlc_media_player_get_time(vlc_player);
printf( "playing
time : %lld ms\r" , (__int64)(play_time));
//
libvlc_state_t media_state = libvlc_media_get_state(vlc_media);
//
printf("\nmedia state : %d\n", (int)(media_state));
}
//
停止1
libvlc_media_player_stop(vlc_player);
//
釋放?
libvlc_media_release(vlc_media);
}
//
釋放?
libvlc_media_player_release(vlc_player);
}
//
釋放?
libvlc_release(vlc_ins);
}
return 0;
}
#endif
/* libSDL and libVLC sample code
* Copyright ? 2008 Sam Hocevar <sam@zoy.org>
* license: [http://en.wikipedia.org/wiki/WTFPL WTFPL] */
//下面這部分程式碼獲取rtsp視訊流並用SDL進行顯示
#include <stdio.h>
#include <stdint.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include <SDL.h>
#include <SDL_mutex.h>
#include <vlc/vlc.h>
#define WIDTH
1280
#define HEIGHT
720
#define VIDEOWIDTH
640
#define VIDEOHEIGHT
480
struct ctx
{
SDL_Surface *surf;
SDL_mutex *mutex;
};
static void *lock(void *data, void **p_pixels)
{
#if 1
struct ctx
*ctx = (struct ctx*)data;
SDL_LockMutex(ctx->mutex);
SDL_LockSurface(ctx->surf);
*p_pixels = ctx->surf->pixels;
#endif
return NULL; /*
picture identifier, not needed here */
}
static void unlock(void *data, void *id, void *const *p_pixels)
{
#if 1
struct ctx
*ctx = (struct ctx*)data;
/* VLC
just rendered the video, but we can also render stuff */
uint16_t *pixels = (uint16_t*)*p_pixels;
int x,
y;
//memset(pixels,
0x00, 640*480);
for(y
= 10; y < 40; y++)
for(x
= 10; x < 40; x++)
if(x
< 13 || y < 13 || x > 36 || y > 36)
pixels[y * VIDEOWIDTH + x] = 0xffff;
else
pixels[y * VIDEOWIDTH + x] = 0x0;
#if 0
FILE *fp = NULL;
fp = fopen( "data.rgb", "ab+" );
if(fp
!= NULL)
{
fwrite(pixels, 640*480*2, 1, fp);
fclose(fp);
printf( "write
a frame.\r\n");
}
#endif
SDL_UnlockSurface(ctx->surf);
SDL_UnlockMutex(ctx->mutex);
assert(id == NULL); /*
picture identifier, not needed here */
#endif
}
static void display(void *data, void *id)
{
/* VLC
wants to display the video */
( void)
data;
printf( "display
a frame.\r\n");
assert(id == NULL);
}
int _tmain(int argc,
_TCHAR* argv[])
{
libvlc_instance_t *libvlc;
libvlc_media_t *m;
libvlc_media_player_t *mp;
char const *vlc_argv[]
=
{
"--no-audio", /*
skip any audio track */
"--no-xlib", /*
tell VLC to not use Xlib */
};
int vlc_argc
= sizeof (vlc_argv)
/ sizeof(*vlc_argv);
SDL_Surface *screen, *empty;
SDL_Event event;
SDL_Rect rect;
int done
= 0, action = 0, pause = 0, n = 0;
struct ctx
ctx;
//if(argc
< 2)
{
printf( "Usage:
%s <filename>\n" , argv[0]);
//
return EXIT_FAILURE;
}
/*
* Initialise libSDL
*/
//if(SDL_Init(SDL_INIT_VIDEO
| SDL_INIT_AUDIO | SDL_INIT_EVENTTHREAD) == -1)
if(SDL_Init(0)
== -1)
{
printf( "cannot
initialize SDL\n" );
return EXIT_FAILURE;
}
empty = SDL_CreateRGBSurface(SDL_SWSURFACE, VIDEOWIDTH, VIDEOHEIGHT,
16, 0, 0, 0, 0);
#if 1
ctx.surf = SDL_CreateRGBSurface(SDL_SWSURFACE, VIDEOWIDTH, VIDEOHEIGHT,
16, 0x001f, 0x07e0, 0xf800, 0);
#else
ctx.surf = SDL_CreateRGBSurface(SDL_SWSURFACE, VIDEOWIDTH, VIDEOHEIGHT,
16, 0xff000000, 0x00ff0000, 0x0000ff00, 0);
#endif
ctx.mutex = SDL_CreateMutex();
int options
= SDL_ANYFORMAT | SDL_HWSURFACE | SDL_DOUBLEBUF;
screen = SDL_SetVideoMode(WIDTH, HEIGHT, 0, options);
if(!screen)
{
printf( "cannot
set video mode\n" );
return EXIT_FAILURE;
}
/*
* Initialise libVLC
*/
libvlc = libvlc_new(vlc_argc, vlc_argv);
//m =
libvlc_media_new_path(libvlc, (const char*)argv[1]);
//m
= libvlc_media_new_path(libvlc, "F:\\123.mp4");
m = libvlc_media_new_path(libvlc, "rtsp://192.0.0.64/av0_0" );
mp = libvlc_media_player_new_from_media(m);
libvlc_media_release(m);
libvlc_video_set_callbacks(mp, lock, unlock, display, &ctx);
libvlc_video_set_format(mp, "RV16",
VIDEOWIDTH, VIDEOHEIGHT, VIDEOWIDTH*2);
libvlc_media_player_play(mp);
/*
* Main loop
*/
rect.w = 0;
rect.h = 0;
while(!done)
{
action = 0;
/*
Keys: enter (fullscreen), space (pause), escape (quit) */
while(
SDL_PollEvent( &event )
)
{
switch(event .type)
{
case SDL_QUIT:
done = 1;
break;
case SDL_KEYDOWN:
action = event.key.keysym.sym;
break;
}
}
switch(action)
{
case SDLK_ESCAPE:
done = 1;
break;
case SDLK_RETURN:
options ^= SDL_FULLSCREEN;
screen = SDL_SetVideoMode(WIDTH, HEIGHT, 0, options);
break;
case '
' :
pause = !pause;
break;
}
rect.x = ( int)((1.
+ .5 * sin(0.03 * n)) * (WIDTH - VIDEOWIDTH) / 2);
rect.y = ( int)((1.
+ .5 * cos(0.03 * n)) * (HEIGHT - VIDEOHEIGHT) / 2);
if(!pause)
n++;
/*
Blitting the surface does not prevent it from being locked and
* written to by another thread, so we use this additional mutex. */
SDL_LockMutex(ctx.mutex);
SDL_BlitSurface(ctx.surf, NULL, screen, &rect);
SDL_UnlockMutex(ctx.mutex);
SDL_Flip(screen);
SDL_Delay(10);
SDL_BlitSurface(empty, NULL, screen, &rect);
}
/*
* Stop stream and clean up libVLC
*/
libvlc_media_player_stop(mp);
libvlc_media_player_release(mp);
libvlc_release(libvlc);
/*
* Close window and clean up libSDL
*/
SDL_DestroyMutex(ctx.mutex);
SDL_FreeSurface(ctx.surf);
SDL_FreeSurface(empty);
SDL_Quit();
return 0;
}
|
相關文章
- Qt+FFmpeg仿VLC接收RTSP流並播放QT
- 使用VideoView播放rtsp視訊流IDEView
- 獲取Wireshark資料流
- 前端獲取視訊編碼格式前端
- 20款jQuery 的音訊和視訊外掛jQuery音訊
- 利用insert,update和delete注入獲取資料delete
- 通過gitHub獲取vlc-Android原始碼GithubAndroid原始碼
- iOS視訊邊下邊播–快取播放資料流iOS快取
- 視訊彈幕外掛
- Discuz 外掛開發視訊
- RTSP網路攝像頭網頁無外掛直播視訊平臺EasyNVR自定義標題和CopyRight步驟網頁VR
- Jenkins解決無法獲取外掛的辦法Jenkins
- 微信小程式 – 解決騰訊視訊外掛—視訊只能播放廣告問題微信小程式
- chrome 外掛實現mac地址獲取ChromeMac
- opencv python 從攝像頭獲取視訊/從檔案獲取視訊 /儲存視訊OpenCVPython
- PHP外掛系統的實現(二):獲取全部外掛資訊PHP
- 視訊怎麼使用外掛字幕
- 電視機頂盒視訊播放外掛
- 【原始碼解讀】js原生訊息提示外掛原始碼JS
- 獲取本地圖片/視訊地圖
- iOS 獲取視訊圖片iOS
- javascript獲取視訊播放時間程式碼例項JavaScript
- 自己做一個table外掛 (一)Ajax獲取資料後動態生成table
- linux掛載windows共享資料夾LinuxWindows
- c#利用WebClient和WebRequest獲取網頁原始碼C#Webclient網頁原始碼
- Android視訊編碼和直播推流教程Android
- 如何利用電商API介面來獲取商品資料API
- 如何利用API介面獲取電商平臺資料?API
- 利用XMLHTTP 從其他頁面獲取資料 (轉)XMLHTTP
- 如何在Java中獲取Windows和Linux/Mac系統上的桌面路徑JavaWindowsLinuxMac
- 如何利用資料視覺化和分析來獲得實時洞察?視覺化
- 10個最好的 jQuery 視訊外掛jQuery
- 基於canvas的視訊遮罩外掛Canvas遮罩
- FFmpeg 播放 RTSP/Webcam 流Web
- Golang 爬蟲快速入門 | 獲取 B 站全站的視訊資料Golang爬蟲
- datatables 獲取 pageLength 和 pageStart,重新獲取table資料
- 音視訊通訊——直播協議和視訊推流協議
- windows的盤掛到linux上WindowsLinux