An ffmpeg and SDL Tutorial在ffmpeg-1.0.1上的更新,tutorial02
阿新 • • 發佈:2020-10-09
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 p_w_picpath 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視訊解碼播放的簡單流程。
轉載於:https://blog.51cto.com/cutebunny/1150226