windows和Linux上利用vlc插件获取rtsp视频流解码数据

本文介绍了如何在Linux和Windows系统上利用VLC插件获取并解码RTSP视频流。在Linux环境下,需要确保安装了VLC和SDL,并遇到无法打开RTSP流的问题。而在Windows环境中,通过编译Linux版本的VLC得到适用于Windows的版本,并解决stdint.h头文件兼容性问题,确保工程引用了必要的库和DLL。
摘要由CSDN通过智能技术生成
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" ,
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值