1. 程式人生 > >ffmpeg開啟視訊檔案步驟

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);