转自:http://blog.csdn.net/gavinr/article/details/6973704
安装好ffmpeg后,就开始学习如何应用了,主要也就是熟悉一些常用API。
同事推荐了一个ffmpeg的自学教程--An ffmpeg and SDL Tutorial,觉得不错,就开始照敲代码了。这个教程的网址为:http://dranger.com/ffmpeg/tutorial01.html
学习过程中敲的代码及编译makefile文件 ,已上传至http://download.csdn.net/detail/gavinr/3798699
教程中提供8个例程:
Tutorial 01: Making Screencaps 读取一个文件解码,并保存成*.ppm格式的图片,*.ppm其实就是RGB数据添加一个简单的文件头(一个魔数、宽、高等)组成。
Tutorial 02: Outputting to the Screen 主要是在Tutorial 01基础上,将解码后的图像通过SDL输出到屏幕,
Tutorial 03: Playing Sound 增加了SDL播放声音
Tutorial 04: Spawning Threads 调整程序结构,使用了多线程机制,方便后续扩展
Tutorial 05: Synching Video 音频同步
Tutorial 06: Synching Audio 视频同步
Tutorial 07: Seeking 定位
Tutorial 08: Software Scaling 使用libswscale库进行,图像的格式转换及缩放操作
每个例程都是在前一个的基础上完成的,所以需要从第一个看起。不过有一个例外,Tutorial 08最好提前看。前面的例子中图像格式转换时,均使用了img_convert函数,但是在新版本的ffmpeg中已经不再支持,必需使用例程8讲述的方式。
2.SDL的作用
SDL是一个跨平台媒体库,似乎在游戏编程中有大量应用,例中大量使用了SDL中的函数,主要用到其以下功能:
1)视频渲染
2)音频播放
3)事件机制,可以响应键盘及自定义事件
4)线程机制,SDL提供了线程创建函数,及线程同步机制
3.编译例程遇到的问题
前5个例程,偶都敲进去编译运行了一下,遇到的问题不算太多,主要修改几个已经不再支持的宏及函数调用,主要有以下几个地方
1).宏CODEC_TYPE_VIDEO需要改为AVMEDIA_TYPE_VIDEO
2).音频解码函数
/*
len1 = avcodec_decode_audio2(aCodecCtx, (int16_t *) audio_buf, &data_size, audio_pkt_data,
audio_pkt_size);
*/
len1 = avcodec_decode_audio3(aCodecCtx, (int16_t *) audio_buf,
&data_size, &pkt);
3).视频解码函数
/*
avcodec_decode_video(pCodecCtx, pFrame, &frameFinished, packet.data, packet.size);
*/
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
4).图像格式转换,就是Tutorial 08中提到的
/*
*此函数已经不用
img_convert((AVPicture *)pFrameRGB, PIX_FMT_RGB24, (AVPicture*)pFrame, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
*/
static struct SwsContext *img_convert_ctx;
...
// Convert the image into YUV format that SDL uses
if(img_convert_ctx == NULL) {
int w = is->video_st->codec->width;
int h = is->video_st->codec->height;
img_convert_ctx = sws_getContext(w, h,
is->video_st->codec->pix_fmt,
w, h, dst_pix_fmt, SWS_BICUBIC,
NULL, NULL, NULL);
if(img_convert_ctx == NULL) {
fprintf(stderr, "Cannot initialize the conversion context!\n");
exit(1);
}
}
sws_scale(img_convert_ctx, pFrame->data,
pFrame->linesize, 0,
is->video_st->codec->height,
pict.data, pict.linesize);