(轉載)FFMPEG源碼分析(二)

ffmpeg源碼分析之數據流

本文主要介紹ffmpeg的數據流,在ffmpeg中主要分有三個主要用途用於媒體流的解碼播放,媒體流的轉換(解碼之後再編碼)和媒體流錄製。

媒體流的解碼播放

在ffmpeg中媒體流的解碼播放流程如下圖:

decode其主要流程爲從媒體文件中讀取出媒體流,然後送入媒體格式解碼器(demuxer)中去除多餘的外衣--媒體格式。然後送入ffmpeg的codec的decode中進行解碼,最終生成顯示需要的YUV格式的圖片,然後再送入類似SDL中進行渲染。ffmpeg中媒體流的解碼播放流程相對比較來說其最大的難點在於pts的同步,在ffmpeg的ffplay中有很好的例子。例子中是啓動了多個線程來進行同步的。

媒體流的轉換

所謂媒體流的轉換分以下幾種情況:

一種是格式轉換,也相當於我們平時的換衣服一樣,只是換個樣式,換一種組織樣式以適應不同場合的需要。

一種是媒體編碼類型的轉換,例如將codec從mpeg4 to H264相當於不同的人來買同一個衣服,雖然外表(格式)看起來一樣但穿衣服的人已經發生了變化。

一種是媒體編碼類型和格式同時轉換,例如將格式爲flv的轉換爲mpeg4,同時將codec從mpeg4 to H264相當於不同的人穿了不同的衣服。

其流程如下圖:

data stream其數據流前半部分同解碼流程一樣,後半部分則和解碼的流程相反。當解析出YUV圖片之後,然後編碼成另外一種codec,之後再將codec的數據加上一個外殼形成一個媒體文件然後通過byteIocontext寫入目標文件。

媒體流錄製

媒體流的錄製過程相當於媒體流轉換的後半部分流程從YUV文件到media文件。其流程爲:

recode 

FFMPEG中的decoder的組織形式:

FFMPEG中codec的數據結構如下:

typedef struct AVCodec {
     const char *name;
    enum AVMediaType type;
    enum CodecID id;
    int priv_data_size;
    int (*init)(AVCodecContext *);
    int (*encode)(AVCodecContext *, uint8_t *buf, int buf_size, void *data);
    int (*close)(AVCodecContext *);
    int (*decode)(AVCodecContext *, void *outdata, int *outdata_size, AVPacket *avpkt);
    int capabilities;
    struct AVCodec *next;
    void (*flush)(AVCodecContext *);
    const AVRational *supported_framerates;
    const enum PixelFormat *pix_fmts;      
    const char *long_name;
    const int *supported_samplerates;      
    const enum SampleFormat *sample_fmts;  
    const int64_t *channel_layouts;        
} AVCodec;

這個數據結構分別用於decoder和encoder,當被decoder所用時函數指針encode爲NULL,而當用於encode時其decode爲NULL,在ffmpeg中通過向全局變量

static AVCodec *first_avcodec;

中添加新的codec變量。在查找的過程也是通過遍歷這個鏈表然後通過name來匹配相應的codec這個過程將會在以後的文章中詳細描述。在ffmpeg中formate的組織結構和codec類似。

發佈了28 篇原創文章 · 獲贊 6 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章