ffmpeg和SDL实现的视频播放程序

ffmpeg和SDL库实现视频解码、显示、按键控制,这里使用了较少的代码70多行,文中使用的视频文件是从优酷网下载的一段264视频“stealth.flv”,与代码放在同一文件夹下。

注:1. 文中没有考虑函数执行错误的情况和内存释放问题。

        2.代码只实现了基于ffmpegSDL库的视频解码、显示和按键控制,音频和同步待以后学习。

        3. ffmpeg版本为0.5.10,其它版本程序可能出错。

        4.程序功能在ubuntu上运行正常。

       5. 编译命令 gcc -o test test.c -I/INCLUDE_PATH -L/LIB_PATH -pthread -lavdevice -lavformat -lavcodec -ldl -lSDL -lz -lavutil -lm

以下是完整代码:

#include<unistd.h>
#include<libavformat/avformat.h>
#include<libavcodec/avcodec.h>
#include<SDL/SDL.h>
#include<SDL/SDL_thread.h>

int main(void)
{
    AVFormatContext *pFormatCtx;
    AVCodecContext *pCodecCtx;
    AVCodec *pCodec;
    AVFrame *pFrame;  
    AVPacket packet;
    AVPicture pic;
    SDL_Surface *screen;
    SDL_Overlay *bmp;
    SDL_Rect rect;
    SDL_Event event;   
    int i;
    int frameFinished;
    char *filename="stealth.flv";
    //初始化解码器和SDL
    av_register_all();
    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER);
    //打开文件,将文件信息保存到AVFormatContext结构中
    av_open_input_file(&pFormatCtx,filename,NULL,0,NULL);
    //找到文件中的视频流,stealth.flv中有两个流,即nb_streams=2,视频流为0,音频流为1
    av_find_stream_info(pFormatCtx);
    for(i=0;i<pFormatCtx->nb_streams;i++)
    {
        if(pFormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO)
        {
            break;
        }
    }
    //找到解码器的信息放到AVCodecContex结构中
    pCodecCtx=pFormatCtx->streams[i]->codec;
    //找到解码器放到AVCodec结构中,并打开它(也就是做一些初始化的工作)
    pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
    avcodec_open(pCodecCtx, pCodec);
    //pFrame用来保存一帧图像,这里为它申请空间
    pFrame=avcodec_alloc_frame();
    //设置视频显示区域
    screen=SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0,0);
    //创建一个YUV覆盖,显示格式SDL_YV12_OVERLAY
    bmp=SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height,SDL_YV12_OVERLAY, screen);
    rect.x=0;
    rect.y=0;
    rect.w=pCodecCtx->width;
    rect.h=pCodecCtx->height;
    //循环读取视频放到packet中
    while( av_read_frame(pFormatCtx, &packet)>=0)
    {   //如果是视频流
	 if(packet.stream_index==i)
       {  //解码视频流
          avcodec_decode_video(pCodecCtx, pFrame, &frameFinished, packet.data, packet.size);
          //是否解码完一帧? Stealth.flv在这里循环两到三次才解码完一帧
          if(frameFinished)
          {   // 上面定义了显示格式SDL_YV12_OVERLAY,与解码出来的YUV420格式U和V分量位置相反
               pic.data[0]=bmp->pixels[0];
               pic.data[1]=bmp->pixels[2];
               pic.data[2]=bmp->pixels[1];
               pic.linesize[0]=bmp->pitches[0];
               pic.linesize[1]=bmp->pitches[2];
               pic.linesize[2]=bmp->pitches[1];
               //将pFrame转换到pic中
               img_convert(&pic, PIX_FMT_YUV420P, (AVPicture *)pFrame, pCodecCtx->pix_fmt,
                            pCodecCtx->width, pCodecCtx->height);
               //显示视频
               SDL_DisplayYUVOverlay(bmp,&rect);
               //由于没有使用时间同步,这里等待30ms,视频传输大约30f/s。使用头文件unistd.h
               usleep(30000); 
          }     
       }
       //查询事件
       SDL_PollEvent(&event);
       switch(event.type)
       {    //如果有键盘按键按下
           case SDL_KEYDOWN:
               // 视频退出             
               SDL_Quit();
               exit(0);
               break;
           defualt:
               break;
       }
    }
    return 0;
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值