An ffmpeg and SDL Tutorial
在
ffmpeg-1.0.1
上的更新
Tutorial02
http://cutebunny.blog.51cto.com/301216/1150226
本篇和
Tutorial01
的主流程差别不大,只是将
’DO SOMETHING WITH frame’
从将前
5
帧保存为
PPM
文件改为以最快的解码速度将得到的帧播放出来。代码也相当简单,我们直接进入更新。
更新
Line19, 20
#include <ffmpeg/avcodec.h>
#include <ffmpeg/avformat.h>
改为
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
详见
Tutorial01
。
Line32
AVFormatContext *pFormatCtx;
改为
AVFormatContext *pFormatCtx = NULL;
详见
Tutorial01
。
Line59
if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0)
return -1; // Couldn't open file
改为
if(avformat_open_input(&pFormatCtx, argv[1], NULL, NULL)!=0)
return -1; // Couldn't open file
详见
Tutorial01
。
Line67
dump_format(pFormatCtx, 0, argv[1], 0);
改为
av_dump_format(pFormatCtx, 0, argv[1], 0);
详见
Tutorial01
。
Line72
if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) {
改为
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) {
详见
Tutorial01
。
Line120
avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,
packet.data, packet.size);
改为
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished,
&packet);
详见
Tutorial01
。
Line137
img_convert(&pict, PIX_FMT_YUV420P,
(AVPicture *)pFrame, pCodecCtx->pix_fmt,
pCodecCtx->width, pCodecCtx->height);
改为
static struct SwsContext *img_convert_ctx;
img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pict.data, pict.linesize);
详见
Tutorial01
。
好了,更新到此为止了。可以看到
Tutorial02
所作的修改和
Tutorial01
一模一样
(
当然除了行号
)
,这是因为
SDL
库的
API
是那么的一如既往,没什么太大差异。不知道
Dranger
大神
SDL
用的什么版本,我调试用的
1.2.15
,目前应该还是最新版,而且
Sample
代码不需要针对
SDL
做任何更新。我就喜欢这种专一。
开始编译吧,以下是我的编译脚本,加入了
SDL
库,还是注意一下修改路径。同样,源代码可以从附件中下载。
#!/bin/sh
FFMPEG_ROOT="ffmpeg-1.0.1"
SDL_ROOT="SDL-1.2.15"
gcc $1 -g -o sample -I../$FFMPEG_ROOT \
-L../$FFMPEG_ROOT/libavformat -L../$FFMPEG_ROOT/libavcodec -L../$FFMPEG_ROOT/libavutil -L../$FFMPEG_ROOT/libswscale \
-lavformat -lavcodec -lswscale -lavutil -lz -lbz2 -lm -lpthread \
-I../$SDL_ROOT/include -D_GNU_SOURCE=1 -D_REENTRANT \
-L../$SDL_ROOT/build/.libs -Wl,-rpath,../$SDL_ROOT/build/.libs -lSDL –lpthread
这里我没有使用原文中采用的
sdl-config --cflags –libs,
而是手动指定路径和编译选项,确保使用的是我最新的
SDL
库。
解释
Q:
Line127 AVPicture pict;
为什么这里的
pict
没有像
Tutorial01
中的
pFrameRGB
去手动分配空间?
A:
因为
pict
的
data
和
linesize
已经指向了
SDL_Overlay *bmp
的空间,随后在
sws_scale()
中对
pict
的操作实际上是对
bmp
在进行操作。
Q:
SDL_PollEvent(&event);
switch(event.type) {
case SDL_QUIT:
SDL_Quit();
……
这个事件系统是做什么的?有什么作用?
A:
本篇中作用不大,但千万别小看了它。后面的多线程以及音视频同步都是以它为基础。
疑问
Q:
Line108
// Allocate a place to put our YUV image on that screen
bmp = SDL_CreateYUVOverlay(pCodecCtx->width,
pCodecCtx->height,
SDL_YV12_OVERLAY,
screen);
创建了
YV12
类型的
overlay
,可是在最后的
Line147
img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
却创建了
PIX_FMT_YUV420P
类型的
img_convert_ctx
。
是否前后不匹配呢?还望知情者解答。
最后还是根据
Tutorial02
给出一个
ffmpeg+SDL
视频解码播放的简单流程。
本文出自 “bunny技术坊” 博客,转载请与作者联系!