一、FFmpeg 播放視頻的基本流程整理
播放流程: video.avi(Container) -> 打開得到 Video_Stream -> 讀取Packet -> 解析到 Frame -> 顯示Frame。
- Container:在音視頻中的容器,一般指的是一種特定的文件格式(如 AVI/QT ),里面指明了所包含的音視頻,字幕等相關信息。
- Stream:媒體流,指時間軸上的一段連續數據,如一段聲音、視頻或字幕數據。
- Packet:Stream中的Raw數據,包含了可以被解碼成方便我們最后在應用程序中操作的幀的原始數據。
- Frame:Stream中的一個數據單元。
- Codec:編解碼器(Code 和 Decode),如 Divx和 MP3,以幀為單位實現壓縮數據和原始數據之間的相互轉換。
二、FFmpeg 各個結構體及相關方法流程整理
1. AVCodec
AVCodec -- 編解碼器,采用鏈表維護,每一個都有其對應的名字、類型、CodecID和對數據進行處理的編解碼函數指針。
- avcodec_find_decoder/avcodec_find_encoder :根據給定的codec id或解碼器名稱從系統中搜尋並返回一個AVCodec結構的指針
- avcodec_alloc_context3:根據 AVCodec 分配合適的 AVCodecContext
- avcodec_open/avcodec_open2/avcodec_close :根據給定的 AVCodec 打開對應的Codec,並初始化 AVCodecContext/ 關閉Codec
- avcodec_alloc_frame:分配編解碼需要的 AVFrame 結構
- avcodec_decode_video/avcodec_decode_video2 :解碼一個視頻幀,輸入數據在AVPacket結構中,輸出數據在AVFrame結構中
- avcodec_decode_audio4:解碼一個音頻幀。輸入數據在AVPacket結構中,輸出數據在AVFrame結構中
- avcodec_encode_video/avcodec_encode_video2 :編碼一個視頻幀,輸入數據在AVFrame結構中,輸出數據在AVPacket結構中
2. AVCodecContext
AVCodecContext -- 和具體媒體數據相關的編解碼器上下文,保存AVCodec指針和與codec相關的數據,包含了流中所使用的關於編解碼器的所有信息
- codec_name[32]、codec_type(AVMediaType)、codec_id(CodecID)、codec_tag:編解碼器的名字、類型(音頻/視頻/字幕等)、ID(H264/MPEG4等)、FOURC等信息
- hight/width,coded_width/coded_height: Video的高寬
- sample_fmt:音頻的原始采樣格式, 是 SampleFormat 枚舉
- time_base:采用分數(den/num)保存了幀率的信息
3. AVFrame
- data/linesize:FFMpeg內部以平面的方式存儲原始圖像數據,即將圖像像素分為多個平面(R/G/B或Y/U/V)數組
- data數組:其中的指針指向各個像素平面的起始位置,編碼時需要用戶設置數據
- linesize數組 :存放各個存貯各個平面的緩沖區的行寬,編碼時需要用戶設置數據
- key_frame:該圖像是否是關鍵幀,由 libavcodec 設置
- pict_type:該圖像的編碼類型:Intra(1)/Predicted(2)/Bi-dir(3) 等,默認值是 NONE(0),其值由libavcodec設置
- pts:呈現時間,編碼時由用戶設置
- quality:從1(最好)到FF_LAMBDA_MAX(256*128-1,最差),編碼時用戶設置,默認值是0
- nterlaced_frame:表明是否是隔行掃描的,編碼時用戶指定,默認0
4. AVFormatContext
AVFormatContext -- 格式轉換過程中實現輸入和輸出功能、保存相關數據的主要結構,描述了一個媒體文件或媒體流的構成和基本信息
- nb_streams/streams :AVStream結構指針數組, 包含了所有內嵌媒體流的描述,其內部有 AVInputFormat + AVOutputFormat 結構體,來表示輸入輸出的文件格式
- avformat_open_input:創建並初始化部分值,但其他一些值(如 mux_rate、key 等)需要手工設置初始值,否則可能出現異常
- avformat_alloc_output_context2:根據文件的輸出格式、擴展名或文件名等分配合適的 AVFormatContext 結構
5. AVPacket
AVPacket -- 暫存解碼之前的媒體數據(一個音/視頻幀、一個字幕包等)及附加信息(解碼時間戳、顯示時間戳、時長等),主要用於建立緩沖區並裝載數據。
- data/size/pos: 數據緩沖區指針、長度和媒體流中的字節偏移量
- flags:標志域的組合,1(AV_PKT_FLAG_KEY)表示該數據是一個關鍵幀, 2(AV_PKT_FLAG_CORRUPT)表示該數據已經損壞
- destruct:釋放數據緩沖區的函數指針,其值可為 [av_destruct_packet]/av_destruct_packet_nofree, 會被 av_free_packet 調用
6. AVStream
AVStream -- 描述一個媒體流,其大部分信息可通過 avformat_open_input 根據文件頭信息確定,其他信息可通過 avformat_find_stream_info 獲取,典型的有 視頻流、中英文音頻流、中英文字幕流(Subtitle),可通過 av_new_stream、avformat_new_stream 等創建。
- index:在AVFormatContext中流的索引,其值自動生成(AVFormatContext::streams[index])
- nb_frames:流內的幀數目
- time_base:流的時間基准,是一個實數,該流中媒體數據的pts和dts都將以這個時間基准為粒度。通常,使用av_rescale/av_rescale_q可以實現不同時間基准的轉換
- avformat_find_stream_info:獲取必要的編解碼器參數(如 AVMediaType、CodecID ),設置到 AVFormatContext::streams[i]::codec 中
- av_read_frame:從多媒體文件或多媒體流中讀取媒體數據,獲取的數據由 AVPacket 來存放
- av_seek_frame:改變媒體文件的讀寫指針來實現對媒體文件的隨機訪問,通常支持基於時間、文件偏移、幀號(AVSEEK_FLAG_FRAME)的隨機訪問方式
三、FFmpeg 學習教程及資源整理
1. 英文的入門教材(有些過時)
地址:http://dranger.com/ffmpeg/ffmpeg.html
2. 使用FFMpeg進行H264編碼
地址:https://www.cnblogs.com/billcoco/archive/2012/06/18/2553948.html
3. FFMpeg寫MP4文件例子分析
地址:http://www.cnblogs.com/billcoco/archive/2012/06/18/2553939.html
四、后續計划
目前針對FFmepg的最基本的知識已經了解,后續要結合相應的開發實戰來進行更深一步的學習。
