FFmpeg總結

一、概述

本文會講到的內(nèi)容:
1、FFmpeg結構
2、FFmpeg解碼
3、FFmpeg的時間timebase
4、FFmpeg編碼
5、FFmpeg封裝mp4

二、FFmpeg結構

image.png

AVFormatContext:文件信息上下文,其中就包含了流信息結構AVStream

AVStream:流信息,其中就包含具體的音視頻格式信息AVCodecContext

AVCodecContext:具體的音視頻格式信息。要解碼音視頻,需要從這里拿到相關信息,比如AVCodecID

AVPacket:未解碼的音視頻內(nèi)容。比如視頻的每一幀數(shù)據(jù),就體現(xiàn)在一個packet中

AVFrame:解碼后的音視頻內(nèi)容。

通過FFmpeg解析mp4的過程來理解:

image.png

思考
1、如何得到音頻的編碼格式?
AVFormatContext->AVStream->AVCodecContext->AVCodecID

2、如何得到這個mp4的總時間?
AVFormatContext->duration

3、如何得到視頻的分辨率?
AVCodecContext->width、height

三、FFmpeg解碼

1、解碼H264(Annex-B)

Annex-B:H264其中一種表示格式。一般運用在網(wǎng)絡傳輸中。

一般是以0x00000001或者0x000001開頭,視頻幀分為I、P、B幀。
I幀還會帶上sps,pps信息,有這兩個信息才可以正常解碼。
0000000167+(SPS的內(nèi)容)+0000000168+(PPS的內(nèi)容)+0000000165+(IDR主幀的內(nèi)容):
標志位計算公式:code&0x1F,通過公式計算,得到:
SPS:0x07
PPS:0x08
IDR:0x05
0x67 & 0x1F = 0x07,所以0x67是sps的標志位。

哪天你看到0000000127,標志位為0x27,0x27&0x1F = 0x07,所以它也是sps的標志。
image.gif

解碼的部分代碼:

image.png

思考
這里的解碼器AVCodecContext不需要配置參數(shù)就可以解碼成功,為什么?
1、可以得到具體的NAL
2、可以得到解碼需要的信息
因為前面提到的sps,pps已經(jīng)攜帶了解碼的一些信息,比如分辨率,格式等等。FFmpeg會自動解析,然后進行解碼。
p2p流通過Annex-B這種格式傳H264。好處是每一個主幀都是獨立的,就算前面的主幀攜帶的sps、pps有錯,導致解碼失敗。后面的主幀也不受影響,還是可以解碼成功。這樣的容錯性就更好。

2、解碼H264(AVCC)

AVCC:H264其中一種表示格式。一般運用在mp4封裝格式中。
與Annex-B區(qū)別有兩點:一個是參數(shù)集(SPS, PPS)組織格式,一個是分隔。
Annex-B:使用start code分隔NAL(start code為三字節(jié)或四字節(jié),0x000001或0x00000001,一般是四字節(jié));SPS和PPS按流的方式寫在頭部。

AVCC:使用NALU長度(固定字節(jié),通常為4字節(jié))分隔NAL,在頭部包含extradata(或sequence header)的結構體。
image.png

組成:

extradata+NAL長度+NAL+NAL長度+NAL。。。
NAL長度所占字節(jié)、SPS與PPS等包含在extradata中

extradata格式:

image.jpeg

舉個例子:


image.png
image.png

思考
FFmpeg如何解碼AVCC格式的H264?
解碼的兩大條件:
1、可以得到具體的NAL
2、可以得到解碼需要的信息
前面提到了。必現(xiàn)要有extradata。才可以得到拆分出具體的NAL,并且extradata也包含了sps,pps等的解碼需要的信息。

解碼AVCC的H264:

image.png

3、如何得到extradata

a、從mp4文件中解析得到
AVFormatContext->AVStream->AVCodecContext->extradata

b、自己構造
(1)、直接構造extradata


image.png

(2)、先創(chuàng)建Annex-B格式的extradata,再通過ffmpeg自帶函數(shù)轉(zhuǎn)成AVCC的extradata
-先構造Annex-B方式的extradata:


image.png

-extradata(Annex-B) ----> extradata(AVCC)


image.png

四、timebase

timebase:視頻處理中的一種時間單位
基本的時間單位:時、分、秒、毫秒

視頻中最小單位為幀,幀都是毫秒級別
幀率為15,那么每幀時間為:1000/15=66.6666毫秒

1、不用浮點型
2、精度更高

只能擴大倍速了,比如擴大100倍,那么每一幀就是6666,這時候就得定義一種新的單位,可以轉(zhuǎn)換為我們認知的時間:秒。

最終的數(shù)值都可以轉(zhuǎn)化為秒。

比如,100毫秒,就是0.1秒
100*(1/1000) = 0.1秒

這里的timebase = 1/1000,表示 1秒=1000 毫秒。所以timebase包含了與秒的對應關系。

思考
1、剛才的6666,它的timebase是多少呢?
6666*timebase = 0.066秒
timebase = 1/100000

image.png

2、上面的pkt_pts_time是怎么得出來的?
timebase = 1/15360
pts = 1024
pts_time = 1024 * (1/15360) = 0.066667

五、FFmpeg編碼

YUV 編碼為 H264

編碼代碼:
image.png

解碼代碼:
image.png

是否這樣就可以編碼成功了呢?像解碼一樣,不需要參數(shù)?

引出的編碼相關的問題:
1、每一幀壓縮百分比多少,即編碼大小未知
2、每一幀的分辨率未知
3、每一幀的原圖片格式未知。YUV420? YUV422
所以這些東西都需要配置。

AVCodecContext的編碼參數(shù)配置:

image.png

思考
1、如果編碼的分辨率不按圖片的分辨率設置會怎樣?
設置多少,編碼多少。如果圖片分辨率1600X1200,我設置成800X600。結果如下:

image.png

2、如何控制編碼后幀的大???
a、通過修改碼流參數(shù),bit_rate
有時候你會發(fā)現(xiàn),碼流改小了很多,但編碼后的大小變化不大

b、設置正確的timebase值

只有設置了正確的timebase,在改變bit_rate后,編碼后的大小才能正確改變。
可以根據(jù)AVFrame中的timebase,具體你可以看它的pts值,推斷大概的timebase。
比如:
你以幀率為15來算,那么每一幀的時間為1/15秒
1、比如第二幀 pts為1,那么1xtimebase = 1/15,所以timebase為(AVRational){1, 15}
2、比如第二幀pts為1024,同理1024xtimebase = 1/15,所以timebase為1/15除以1024,所以為(AVRational){1, 15360}

六、FFmpeg封裝mp4

image.png

重點1:AVCodecContext的配置
需要配置正確的AVCodecContext->extradata
1、Annex-B的H264,配置對應的extradata(解碼時候有提到)
2、AVCC的H264,配置對應的extradata

重點2:配置正確的timebase
如果合成的mp4播放速度不對,很大概率都是timebase設置錯誤了。
控制倍速播放等等,也通過修改timebase值,達到修改了每一幀的展示時間。

思考
timebase由1/15 改成 1/30,會怎樣?

原本某幀的pts=30,30(1/15) = 2,就是這幀在第2秒才展示
30
(1/30) = 1,這幀變?yōu)榈?秒展示,所以播放速度快了一倍

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 結合前面的知識,這次把FFmpeg的解封裝、解碼、編碼和封裝整合到一塊。代碼倉庫:https://github.c...
    Johnny_Wu閱讀 2,364評論 4 5
  • 一、整體播放策略 (1)iOS自帶的播放控件- AVPlayer、AVQueuePlayer只能通過路徑播放,可以...
    Johnny_Wu閱讀 978評論 0 2
  • FFmpeg 介紹 FFmpeg是一套可以用來記錄、轉(zhuǎn)換數(shù)字音頻、視頻,并能將其轉(zhuǎn)化為流的開源計算機程序。采用LG...
    Y了個J閱讀 11,588評論 0 28
  • 視頻相關的問與答: 一、YUV的內(nèi)存存儲格式YUV格式有很多種,比如YUV420,YUV422,YUV444等。比...
    Johnny_Wu閱讀 414評論 0 0
  • 我是黑夜里大雨紛飛的人啊 1 “又到一年六月,有人笑有人哭,有人歡樂有人憂愁,有人驚喜有人失落,有的覺得收獲滿滿有...
    陌忘宇閱讀 8,876評論 28 54

友情鏈接更多精彩內(nèi)容