ffmpeg開啟視訊檔案步驟
目的:解碼h264檔案,轉存avi格式或者yuv格式,方便opencv處理。
方法:使用ffmpeg庫來解碼檔案,轉存
1、理論探究
FFmpeg主要由一下幾個部分組成:
libavcodec:一個包含了所有FFmpeg音視訊編解碼器的庫。 為了保證最優效能和高可複用性,大多數編解碼器從頭開發的。
libavformat:一個包含了所有的普通音視格式的解析器和 產生器的庫。
三個例項程式,這三個例項較為複雜,基本可以作為API使用手冊:
ffmpeg:命令列的視訊格式轉換程式。
ffplay:視訊播放程式。(需要SDL支援)
ffserver:多媒體伺服器
使用ffmpeg SDK解碼流過程:
1、準備變數
定義AVCodec,AVCodec *變數為解碼器指標。
定義AVCodecContext,使用該變數可以將其定義為ffmpeg解碼類的類成員。
定義AVFrame,AVFrame描述一個多媒體幀。解碼後的資料將被放在其中。
定義AVFormatContext變數,AVFormatContext用於儲存視訊流的有效資訊。
AVCodec *pCodec;
AVCodecContext *pContext;
AVFrame *pAvFrame;
AVFormatContext *pFormatCtx;
2、初始化解碼器
第一件事情就是初始化libavformat/libavcodec:ffmpeg註冊複用器,編碼器等的函式av_register_all()。
av_register_all();
3、開啟視訊檔案、取出檔案頭的流資訊
// 開啟視訊檔案
if(av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL)!=0)
printf("Error!\n");
這個函式讀取檔案的頭部並且把資訊儲存到我們給的AVFormatContext結構體中。最後三個引數描述了檔案格式,緩衝區大小(size)和格式引數;我們通過簡單地指明NULL或0告訴 libavformat 去自動探測檔案格式並且使用預設的緩衝區大小。
// 取出流資訊
if(av_find_stream_info(pFormatCtx) <0)
handle_error(); // 不能夠找到流資訊
這一步會用有效的資訊把 AVFormatContext 的流域(streams field)填滿。
我們僅僅處理視訊流,而不是音訊流。為了讓這件事情更容易理解,我們只簡單使用我們發現的第一種視訊流。
//遍歷檔案的各個流,找到第一個視訊流,並記錄該流的編碼資訊
videoindex = -1;
for(i=0; i<pFormatCtx->nb_streams; i++)
{
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)
{
videoindex=i;
break;
}
}
if(videoindex==-1)
{
printf("Didn't find a video stream.\n");
return;
}
pCodecCtx=pFormatCtx->streams[videoindex]->codec;
我們已經得到了一個指向視訊流的稱之為上下文的指標。接下來,我們需要找到真正的編碼器開啟它。
4、尋找視訊流的解碼器
在庫裡面查詢支援該格式的解碼器
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if(pCodec == NULL)
handle_error(); // 找不到解碼器
5、開啟解碼器
if(avcodec_open(pCodecCtx, pCodec)<0)
handle_error();
6、給視訊幀分配空間,以便儲存解碼後的圖片資料
pAvFrame = avcodec_alloc_frame();
7、進行解碼
通過該api讀入一幀
result = av_read_frame(pFormatCtx, packet);
通過下面的api進行解碼一幀資料,將有效的影象資料儲存到pAvFrame成員變數中
ret = avcodec_decode_video2(pCodecCtx, pAvFrame, &got_picture, packet);