FFmpeg 简介
FFmpeg 簡介
FFmpeg 庫簡介
FFmpeg 一共包含 8 個庫:
- avcodec 編解碼(最重要的庫)
- avformat 封裝格式處理
- avfilter 濾鏡特效處理
- avdevice 各種設備的輸入輸出
- avutil 工具庫
- postproc 后加工
- swresample 音頻采樣數據格式轉換
- swscale 視頻像素數據格式轉換
FFmpeg 視頻解碼流程
更詳細的可以參照這里
解釋:
- av_register_all() 注冊所有組件
- avformat_open_input() 打開輸入視頻文件
- avformat_find_stream_info() 獲取視頻文件信息
- avcodec_find_decoder() 查找解碼器
- avcodec_open2() 打開解碼器
- av_read_frame() 從輸入文件讀取一幀壓縮數據,例如這里的 H.264
- avcodec_decode_video2() 解碼一幀壓縮數據
- avcodec_close() 關閉解碼器
- avformat_close_input() 關閉輸入視頻文件
FFmpeg 解碼的數據結構
](https://melodyofnight.github.io/im
FFMPEG中的結構體很多,最關鍵的結構體可以分為以下幾類:
a)解協議(http、rtsp、rtmp、mms)
AVIOContext、URLContext、URLProtocol主要存儲音視頻使用的協議類型以及狀態。URLProtocol存儲輸入音視頻使用的封裝格式。每種協議都對應一個URLProtocol結構。
b)解封裝(flv、avi、rmvb、mp4)
AVFormatContext主要存儲音視頻封裝格式中包含的信息;AVInputFormat存儲輸入音視頻使用的封裝格式,每種格式對應一個AVInputFormat結構。
c)解碼(h264、mpeg2、aac、mp3)
每個AVStream存儲一個音頻/視頻流的相關數據;每個AVStream對應一個AVCodecContext,存儲該音頻/視頻流使用解碼方式的相關數據;每個AVCodecContext中對應一個AVCodec,包含該音頻/視頻對應的解碼器。每種解碼器對應一個AVCodec結構。
d)存數據
就音頻而言,每個結構可能有好幾幀;視頻的話,每個結構一般是一幀。
AV - 指的是 Audio and Video
AVFormatContext
AVFormatContext 封裝格式的上下文結構體,也是統領全局的結構體,包含了視頻封裝格式最外層的信息。
- iformat: 輸入視頻的 AVInputFormat
- nb_stream: 輸入視頻的 AVStream 個數
- streams: 輸入視頻的 AVStream[] 數組
- duration: 輸入視頻的時長(以微妙為單位)
- bit_rate: 輸入視頻的碼率(碼率越高視頻越清晰)
- ……
AVInputFormat
AVInputFormat 指明了輸入文件的封裝格式,比如 flv、mkv、mp4、avi等;每種封裝格式對應一個該結構體。
- name: 封裝格式名稱
- long_name: 封裝格式的長名稱
- extensions: 封裝格式的拓展名
- id: 封裝格式 ID
- ……
AVStream
一般 AVStream[0] 代表的是視頻流;AVStream[1] 代表的是音頻流。
視頻文件中每個視頻(音頻)流對應一個該結構體。
- id: 序號
- codec: 該流對于的 AVCodecCoontext
- time_base: 該流的時基
- r_frame_rate: 該流的幀率
- ……
AVCodecContext
編碼器上下文結構體,保存了視頻(音頻)編解碼相關信息。
- codec: 編碼器的 AVCodec
- width,height: 圖像的寬高(只針對視頻)
- pix_fmt: 像素格式(只針對視頻)
- sample_rate: 采樣率(只針對音頻)
- channels: 聲道數(只針對音頻)
- sample_fmt: 采樣格式(只針對音頻)
- ……
AVCodec
每種視頻(音頻)編解碼器(例如 H.264 解碼器)對應一個該結構體。
- name: 編解碼器名稱
- long_name: 編解碼器長名稱
- type: 編解碼器類型
- id: 編解碼器 ID
- ….
AVPacket
存儲一幀壓縮編碼數據。
- pts: 顯示時間戳
- dts: 解碼時間戳
- data: 壓縮編碼數據
- size: 壓縮編碼數據大小
- stream_index: 所屬的 AVStream,可以用于區分到底是視頻流還是音頻流
AVFrame
存儲一幀解碼后像素(采樣)數據。
- data: 解碼后的圖像數據數據(音頻采樣數據)
- linesize: 對視頻來說是圖像中一行像素的大小;對音頻來說是整個音頻幀的大小
- width,height: 圖像的寬高(只針對視頻)
- key_frame: 是否為關鍵幀(只針對視頻)
- pict_type: 幀類型(只針對視頻),例如:I 幀、P 幀、B 幀
補充小知識點
1.解碼后的數據為什么要經過 sws_scale() 函數處理?
- 解碼后 YUV 格式的視頻像素數據保存在 AVFrame 的 data[0]、data[1]、data[2] 中(data[0]保存的是 Y 幀數據,data[1]保存的是 U 幀數據,data[2]保存的是 V 數據。)。但是這些像素值并不是連續存儲的。每行有效像素之后存儲了一些無效像素。以亮度 Y 數據為例 data[0] 中包含了 linesize[0] * height 個數據。但是出于優化等方面的考慮,linesize[0] 實際上并不等于寬度 width,而是一個比寬度大一些的值。因此需要使用 sws_scale() 進行轉換。轉換后去除了無效數據,width 和 linesize[0] 取值相等。
2.上面講到了碼率和幀率,那么碼率和幀率到底有什么區別呢?
碼率就是數據傳輸時單位時間傳送的數據位數,一般我們用的單位是kbps即千位每秒。通俗一點的理解就是取樣率,單位時間內取樣率越大,精度就越高,處理出來的文件就越接近原始文件,但是文件體積與取樣率是成正比的,所以幾乎所有的編碼格式重視的都是如何用最低的碼率達到最少的失真,圍繞這個核心衍生出來的cbr(固定碼率)與vbr(可變碼率),都是在這方面做的文章,不過事情總不是絕對的,從音頻方面來說,碼率越高,被壓縮的比例越小,音質損失越小,與音源的音質越接近。“碼率”就是失真度,碼率越高越清晰,反之則畫面粗糙而多馬賽克。計算機中的信息都是二進制的0和1來表示,其中每一個0或1被稱作一個位,用小寫b表示,即bit(位);大寫B表示byte,即字節,一個字節=八個位,即1B=8b;前面的大寫K表示千的意思,即千個位(Kb)或千個字節(KB)。表示文件的大小單位,一般都使用字節(KB)來表示文件的大小。
Kbps:首先要了解的是,ps指的是/s,即每秒。Kbps指的是網絡速度,也就是每秒鐘傳送多少個千位的信息(K表示千位,Kb表示的是多少千個位),為了在直觀上顯得網絡的傳輸速度較快,一般公司都使用kb(千位)來表示,如果是KBps,則表示每秒傳送多少千字節。1KBps=8Kbps。ADSL上網時的網速是512Kbps,如果轉換成字節,就是512/8=64KBps(即64千字節每秒)。
幀數簡單地說,幀數就是在1秒鐘時間里傳輸的圖片的幀數,也可以理解為圖形處理器每秒鐘能夠刷新幾次,通常用fps(Frames Per Second)表示。每一幀都是靜止的圖象,快速連續地顯示幀便形成了運動的假象。高的幀率可以得到更流暢、更逼真的動畫。每秒鐘幀數 (fps) 愈多,所顯示的動作就會愈流暢。一般來說30fps是可以接受的,所以要避免動作不流暢的最低fps是30。除了30fps外,有些計算機視頻格式,例如AVI,每秒只能提供15幀。我們之所以能夠利用攝像頭來看到連續不斷的影像,是因為影像傳感器不斷攝取畫面并傳輸到屏幕上來,當傳輸速度達到一定的水平時,人眼就無法辨別畫面之間的時間間隙,所以大家可以看到連續動態的畫面。
每秒的幀數(fps)或者說幀率表示圖形處理器場景時每秒鐘能夠更新幾次。高的幀率可以得到更流暢、更逼真的動畫。一般來說30fps就是可以接受的,但是將性能提升至60fps則可以明顯提升交互感和逼真感,但是一般來說超過75fps一般就不容易察覺到有明顯的流暢度提升了。如果幀率超過屏幕刷新率只會浪費圖形處理的能力,因為顯示器不能以這么快的速度更新,這樣超過刷新率的幀率就浪費掉了。
一般用“FPS(frame per second,每秒鐘畫面更新的數量)”來表示該項指標。在欣賞電視、電影畫面時,只要畫面的刷新率達到24幀/秒,就能滿足人們的需要。同樣的,在玩普通的游戲時,如果刷新率達到24幀/秒即可,但在一些高速游戲中(例如射擊游戲),如果畫面的刷新率還是只有24幀/秒,那么就會感覺到畫面比較遲鈍,不夠流暢。 雖然理論上畫面的刷新率越快越好,但過高的刷新率并沒有實際意義——當畫面的FPS達到60幀/秒時,已經能滿足絕大部分應用需求。一般情況下,如果能夠保證游戲畫面的平均FPS能夠達到30幀/秒,那么畫面已經基本流暢;能夠達到50幀/秒,就基本可以體會到行云流水的感覺了。一般人很難分辨出60幀/秒與100幀/秒有什么不同。
參考鏈接:
FFmpeg 官網
總結
- 上一篇: 视频流中的DTS、PTS到底是什么
- 下一篇: 二叉树的前、中、后、层序遍历整理(Jav