您的位置:首页 > 其它

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

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

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

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

        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;
}


 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息