我們直接從 video_decode_example() 函數開始講,該函數實現瞭如何去解碼一個視頻文件,以 .mpeg 文 件爲例。
( 1 )將緩存的末尾清 0 ,從而確保讀操作不會越界導致破壞 mpeg 流。
uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE);
可見,我們所分配的緩存,除了存放數據外,最後部分還預留了一小段空間。
( 2 ) avcodec_find_decoder() 函數用於查找與 codec ID 相匹配的已註冊的解碼器。
( 3 ) avcodec_alloc_context() 函數用於分配一個 AVCodecContext 並設置默認值, 如果失敗返回 NULL ,並可用 av_free() 進行釋放。
( 4 ) avcodec_alloc_frame() 函數用於分配一個 AVFrame 並設置默認值,如果失敗返回 NULL , 並可用 av_free() 進行釋放。
( 5 ) avcodec_open() 函數用給定的 AVCodec 來初始化 AVCodecContext 。
對於一些編解碼器,像 msmpeg4 和 mpeg4 ,其寬度和高度必須要初始化,因爲這些信息在碼流( bitstream )中是沒有的。 avcodec_open() 會幫我們把寬度和高度設置好。
( 6 )打開文件 fopen 。
( 7 )循環解碼。
來源:(http://blog.sina.com.cn/s/blog_4e87ac6e0100a60g.html ) - FFMpeg中apiexample.c例子分析——解碼分析_eNsEmpire_新浪博客
( 7.1 )讀取文件 fread(inbuf, 1, INBUF_SIZE, f );
注意 1 :一些編解碼器是基於流的(像 mpegvideo , mpegaudio ),這是使用它們的唯一一種方法,因爲在解析它之前,你不知道壓縮數據的大小。
但是,一些其他編解碼器(像 msmpeg4 , mpeg4 )是基於幀的,所以對於某一幀,你必須調用這些編解碼器來處理所有數據。你也必須在初始化這些編解 碼器前,先把寬度和高度設置了。
注意 2 :一些編解碼器允許原始參數(像幀大小,採樣率)在任何一幀被改變。我們雖然已對此做了處理,但你也 要重視起來。
這兒,我們用一個基於流的解碼器( mpeg1video ),所以我們把數據輸到解碼器,看它是否可以解碼一幀。
( 7.2 ) avcodec_decode_video() 函數用於解碼一個視頻幀 , 從 inbuf_ptr 到 picture, 所採用的編解碼器是 c 。
( 7.3 )寫入文件。
( 8 )解碼延時的幀,再寫入文件。
一些解碼器,像 MPEG ,傳輸 I 幀和 P 幀時,都會有一幀的延時。所以我們必須要獲取視頻的最後一幀數據。
( 9 )釋放資源。
fclose(f);
avcodec_close(c);
av_free(c);
av_free(picture);