注:学习参考雷霄骅老师博客,博客地址:http://blog.csdn.net/leixiaohua1020
An ffmpeg and SDL Tutorial : http://dranger.com/ffmpeg/tutorial01.html
中文教程:http://blog.csdn.net/jinhaijian/article/details/5827116
(ps:YUV 压缩数据)
FFMPEG接口调用顺序:
1.av_register_all();
2.avformat_open_input()
3.avformat_find_stream_info();
4.av_dump_format()
5.avcodec_find_decoder()
6.avcodec_alloc_context3();
7.avcodec_open2();
8.av_read_frame();
9.avcodec_decode_video2();
10.av_free_packet()
11.avcodec_close();
12.avcodec_close_input();
关于SDL调用:
1. 头文件
#include <SDL.h>
#include <SDL_thread.h>
2. SDL初始化
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
exit(1);
}
SDL_Init 初始化确定使用哪些库,SDL_GetError()获取错误信息
3.创建一个显示窗口
SDL_Surface *screen;
screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0, 0);
我们需要在屏幕的一个地方显示图像,SDL中叫做SDL_Surface. 第三个参数是颜色深度
现在我们再屏幕上创建一个YUV覆盖以便于我们输入视频上去
SDL_Overlay *bmp;
bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height, SDL_YV12_OVERLAY, screen);
我们使用YV12 来显示图像。
4.显示图像
为了显示到屏幕上,我们要先建立一个AVPicture结构体,并且设置它数据指针和行尺寸来为我们的YUV覆盖服务。
if(frameFinished)
{
SDL_LockYUVOverlay(bmp);
AVPicture pict;
pict.data[0] = bmp->pixels[0];
pict.data[1] = bmp->pixels[2];
pict.data[2] = bmp->pixels[1];
pict.linesize[0] = bmp->pitches[0];
pict.linesize[1] = bmp->pitches[2];
pict.linesize[2] = bmp->pitches[1];
// Convert the image into YUV format that SDL uses
sws_scale(sws_ctx, (uint8_t const * const *)pFrame->data,
pFrame->linesize, 0, pCodecCtx->height,
pict.data, pict.linesize);
SDL_UnlockYUVOverlay(bmp); }
首先,我们锁定这个覆盖,因为我们将要去改写它。这是一个避免以后发生问题的好习惯。正如前面所示的,这个AVPicture结构体有一个数据指针指向一个有4个元素的指针数据。由于我们处理的是YUV420P,所以我们只需要3个通道即只要三组数据。其它的格式可能需要第四个指针来表示alpha通道或者其它参数。行尺寸正如它的名字表示的意义一样。在YUV覆盖中相同功能的结构体是像素pixel和程度pitch。(程度pitch是在SDL里用来表示指定行数据宽度的值)。所以我们现在做的是让我们的覆盖中的pict.data中的三个指针有一个指向必要的空间的地址。类似的,我们可以直接从覆盖中得到行尺寸信息。像前面一样我们使用img_convert来把格式转换成PIX_FMT_YUV420P。
让我们再花一点时间来看一下SDL的特性:它的事件驱动系统。SDL被设置成当你在SDL中点击或者移动鼠标或者向它发送一个信号它都将产生一个事件的驱动方式。如果你的程序想要处理用户输入的话,它就会检测这些事件。你的程序也可以产生事件并且传递给SDL事件系统。当使用SDL进行多线程编程的时候,这相当有用,这方面代码我们可以在指导4中看到。在这个程序中,我们将在处理完包以后就立即轮询事件。现在而言,我们将处理SDL_QUIT事件以便于我们退出:
av_free_packet(&packet);
SDL_PollEvent(&event);
switch(event.type)
{
case SDL_QUIT:
SDL_Quit();
exit(0);
break;
default:
break;
这个时候没有sleep,所以视频就按着解码的速度在播,会比较快