久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

FFMpeg分析詳細分析

 怎么了啊早上 2014-09-14

與其說是分析,,不如說是學(xué)習(xí),,只是看在自己第一次寫系列文章的份上,給足自己面子,取個有"深度"的題目,!如有人被題目所蒙騙進來,還望見諒!

URLProtocol,URLContext和ByteIOContext是FFMpeg操作文件(即I/O,,包括網(wǎng)絡(luò)數(shù)據(jù)流)的結(jié)構(gòu),這幾個結(jié)構(gòu)現(xiàn)實 的功能類似于C++的多態(tài)繼承吧,,C++的多態(tài)是通過子類繼承實現(xiàn),,而FFMpeg的“多態(tài)”是通過靜態(tài)對像現(xiàn)實。這部分的代碼非常值得C程序借鑒,,我是 說,,如果你要在C里實現(xiàn)類似C++多態(tài)性的功能;比如當(dāng)你要區(qū)分你老婆和情人之間的不同功能時,。

     好了,,先來看一下這三個struct的定義吧

  1. typedef struct URLProtocol { 
  2.  
  3.     const char *name;        //Rotocol名稱  
  4.     int (*url_open)(URLContext *h, const char *url, int flags); //open函數(shù)指針對象,以下類似 
  5.     int (*url_read)(URLContext *h, unsigned char *buf, int size);   
  6.     int (*url_write)(URLContext *h, unsigned char *buf, int size); 
  7.  
  8.     int64_t (*url_seek)(URLContext *h, int64_t pos, int whence); 
  9.  
  10.     int (*url_close)(URLContext *h); 
  11.  
  12.     struct URLProtocol *next; //指向下一個URLProtocol,具體說明見備注1 
  13.  
  14.     int (*url_read_pause)(URLContext *h, int pause); 
  15.  
  16.     int64_t (*url_read_seek)(URLContext *h, int stream_index,int64_t timestamp, int flags); 
  17.  
  18.     int (*url_get_file_handle)(URLContext *h); 
  19.  
  20. } URLProtocol; 

備注1:FFMpeg所有的Protol類型都用這個變量串成一個鏈表,,表頭為avio.c里的URLProtocol *first_protocol = NULL;

每個文件類似都有自己的一個URLProtocol靜態(tài)對象,,如libavformat/file.c里

  1. URLProtocol file_protocol = { 
  2.     "file", 
  3.     file_open, 
  4.     file_read, 
  5.     file_write, 
  6.     file_seek, 
  7.     file_close, 
  8.     .url_get_file_handle = file_get_handle, 
  9. }; 

再通過av_register_protocol()將他們鏈接成鏈表。在FFMpeg中所有的URLProtocol對像值都在編譯時確定,。

  1. typedef struct URLContext { 
  2. #if LIBAVFORMAT_VERSION_MAJOR >= 53 
  3.     const AVClass *av_class; ///< information for av_log(). Set by url_open(). 
  4. #endif 
  5.     struct URLProtocol *prot;
  6. //指向具體的I/0類型,,在運行時通過文件URL確定,如是file類型時就是file_protocol           
  7.     int flags; 
  8.     int is_streamed;
  9. /**< true if streamed (no seek possible), default = false */ 
  10.     int max_packet_size;
  11. /**< if non zero, the stream is packetized with this max packet size */ 
  12.     void *priv_data;//指向具體的I/O句柄 
  13.     char *filename; /**< specified URL */ 
  14. } URLContext; 

不同于URLProtocol對象值在編譯時確定,,URLContext對象值是在運行過程中根據(jù)輸入的I/O類型動態(tài)確定的,。這一動一靜組合起到了C++的多態(tài)繼承一樣的作用。URLContext像是基類,,為大家共同所有,,而URLProtocol像是子類部分。

  1. typedef struct { 
  2.     unsigned char *buffer; 
  3.     int buffer_size; 
  4.     unsigned char *buf_ptr, *buf_end; 
  5.     void *opaque; 
  6.     int (*read_packet)(void *opaque, uint8_t *buf, int buf_size); 
  7.     int (*write_packet)(void *opaque, uint8_t *buf, int buf_size); 
  8.     int64_t (*seek)(void *opaque, int64_t offset, int whence); 
  9.     int64_t pos; /**< position in the file of the current buffer */ 
  10.     int must_flush; /**< true if the next seek should flush */ 
  11.     int eof_reached; /**< true if eof reached */ 
  12.     int write_flag;  /**< true if open for writing */ 
  13.     int is_streamed; 
  14.     int max_packet_size; 
  15.     unsigned long checksum; 
  16.     unsigned char *checksum_ptr; 
  17.     unsigned long (*update_checksum)(unsigned long checksum
  18. , const uint8_t *buf, unsigned int size); 
  19.     int error;         ///< contains the error code or 0 if no error happened 
  20.     int (*read_pause)(void *opaque, int pause); 
  21.     int64_t (*read_seek)(void *opaque, int stream_index, 
  22.                          int64_t timestamp, int flags); 
  23. } ByteIOContext; 

ByteIOContext是URLContext和URLProtocol 一個擴展,,也是FFMpeg提供給用戶的接口,,URLContext 和URLProtocol對用戶是透明,我們所有的操作是通過ByteIOContext現(xiàn)實,。這幾個struct的相關(guān)的關(guān)鍵函數(shù)有:

  1. int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, 
  2.                        AVInputFormat *fmt, 
  3.                        int buf_size, 
  4.                        AVFormatParameters *ap) 
  5.     int url_fopen(ByteIOContext **s, const char *filename, int flags) 
  6.     { 
  7.          url_open(URLContext **puc, const char *filename, int flags) 
  8.          { 
  9.                URLProtocol *up; 
  10.                //根據(jù)filename確定up 
  11. url_open_protocol (URLContext **puc, struct URLProtocol *up, const char *filename, int flags) 
  12.                { 
  13. //初始化URLContext對像,,并通過 up->url_open()將I/O打開將I/O fd賦值給URLContext的priv_data對像 
  14.                } 
  15.          } 
  16.          url_fdopen(ByteIOContext **s, URLContext *h) 
  17.          { 
  18.                //初始化ByteIOContext 對像 
  19.          } 
  20.     } 

我們先看一下音視頻播放器的大概結(jié)構(gòu)(個人想法,不保證正確):1,、數(shù)據(jù)源輸入(Input)->2,、文件格式解析器(Demux)->3、 音視頻解碼(Decoder)->4、顏色空間轉(zhuǎn)換(僅視頻)->5,、渲染輸出(Render Output),。前一篇介紹的幾個struct是數(shù)據(jù)源輸入模塊里的內(nèi)容,哪么這一帖所講的就是第二個模塊即文件格式解析器里用到的內(nèi)容,。

      AVInputFormat,、AVOutputFormat與URLProtocol類似,每一種文件類型都有一個AVInputFormat和 AVOutputFormat靜態(tài)對像并通過av_register_input_format和av_register_output_format函 數(shù)鏈成一個表,,其表頭在utils.c:

 

/** head of registered input format linked list */

AVInputFormat *first_iformat = NULL;

/** head of registered output format linked list */

AVOutputFormat *first_oformat = NULL;

 

AVInputFormat和AVOutputFormat的定義分別在avformat.h,,代碼很長,不貼出來浪費空間了,。

當(dāng)程序運行時,,AVInputFormat對像的

  1. int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, 
  2.                        AVInputFormat *fmt, 
  3.                        int buf_size, 
  4.                        AVFormatParameters *ap) 
  5.      fmt = av_probe_input_format(pd, 0);//返回該文件的AVInputFormat類型 

至于AVOutputFormat嘛,下次再說吧,,晚安,!

   AVFormatContext在FFMpeg里是一個非常重要的的結(jié)構(gòu),是其它輸入,、輸出相關(guān)信息的一個容器,,需要注意的是其中兩個成員:

  struct AVInputFormat *iformat;//數(shù)據(jù)輸入格式
 struct AVOutputFormat *oformat;//數(shù)據(jù)輸出格式
這兩個成員不能同時賦值,即AVFormatContext不能同時做為輸入,、輸出格式的容器,。AVFormatContext和AVIContext、FLVContext等XXXContext之間像前面講的 URLContext和 URLProtocol的關(guān)系一樣,,是一種"多態(tài)"關(guān)系,,即AVFormatContext 對像記錄著運行時大家共有的信息,而各個XXXContext記錄自己文件格式的信息,,如AVIContext,、FLVContext等。 AVInputFormat->priv_data_size記錄相對應(yīng)的XXXContext的大小,,該值大小在編譯時靜態(tài)確定,。 AVFormatContext的void *priv_data記錄XXXContext指針。
AVFormatContext對像的初始化主要在 AVInputFormat的read_header函數(shù)中進行,,read_header是個函數(shù)指針,,指向
具體的文件類型的read_header,如flv_read_header(),,avi_read_header()等,AVFormatContext,、 AVInputFormat和XXXContext組成一起共同完成數(shù)據(jù)輸入模塊,,可以出來粗魯?shù)恼J為,AVFormatContext是一個類容 器,AVInputFormat是這個類的操作函數(shù)集合,,XXXContext代表該類的私有數(shù)據(jù)對像,。AVFormatContext還有個重要的成 員 AVStream *streams[MAX_STREAMS];也是在read_header里初始化,這個等會兒再講,。

 前幾篇說的都還是數(shù)據(jù)源文件格式解析部分,,哪么解析完后呢,讀出的數(shù)據(jù)流保存在哪呢,?正是現(xiàn)在講的AVStream對像,,在AVInputFormat 的read_header中初始化AVFormatContext對像時,他會解析出該輸入文件有哪些類型的數(shù)據(jù)流,,并初始化 AVFormatContext的AVStream *streams[MAX_STREAMS];一個AVStream代表一個流對像,,如音頻流、視頻流,,nb_streams記錄流對像個數(shù),。主版本號大 于53時MAX_STREAMS為100,小于53為20,。AVStream也是個容器,,其

void *priv_data;//

成員變量指向具體的Stream類型對像,如AVIStream,。其

AVCodecContext *actx;//記錄具體的編解容器,,這個下面會講

也在這讀頭文件信息里初始化。

主要相關(guān)的函數(shù)有

  1. int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, 
  2.                        AVInputFormat *fmt, 
  3.                       int buf_size, 
  4.                        AVFormatParameters *ap) 
  5.     av_open_input_stream(AVFormatContext **ic_ptr,ByteIOContext *pb
  6. , const char *filename,AVInputFormat *fmt, AVFormatParameters *ap) 
  7.     { 
  8.          fmt.read_header()//調(diào)用具體的AVInputFormat的read_header,,如avi_read_header 
  9.          { 
  10.                //根據(jù)文件頭信息初始化AVStream *streams及AVStream里的 
  11.                //void *priv_data和AVCodecContext *actx;成員對像 
  12.          }         
  13.     } 

他們之間的關(guān)系和URLProtocol,、URLContext之間是一樣的,AVCodecContext動態(tài)的記錄一個解碼器的上下文信息,,而 AVCodec是每個解碼器都會擁有一個自己的靜態(tài)對像,,并通過avcodec_register()函數(shù)注冊成一個鏈表,表頭在utils.c里定義

static AVCodec *first_avcodec = NULL;

AVCodecContext的enum CodecID codec_id成員記錄者當(dāng)前數(shù)據(jù)流的Codec,,void *priv_data記錄具體Codec所對應(yīng)的上下文信息對像的指針,,如MsrleContext。這三個結(jié)合起來現(xiàn)實數(shù)據(jù)解碼的作用,。我們可以傻逼的 認為AVCodecContext是這個解碼模塊的容器類,,Codec是操作函數(shù)集合,類似MsrleContext的就是操作數(shù)據(jù)對像,。

他們之間關(guān)系的確立:

每一個解碼類型都會有自己的Codec靜態(tài)對像,,Codec的int priv_data_size記錄該解碼器上下文的結(jié)構(gòu)大小,如MsrleContext,。這些都是編譯時確定的,,程序運行時通過 avcodec_register_all()將所有的解碼器注冊成一個鏈表,。在av_open_input_stream()函數(shù)中調(diào)用 AVInputFormat的read_header()中讀文件頭信息時,會讀出數(shù)據(jù)流的CodecID,,即確定了他的解碼器Codec,。

  1. typedef struct AVPicture { 
  2.     uint8_t *data[4]; 
  3.     int linesize[4];       ///< number of bytes per line 
  4. } AVPicture; 
  5.  
  6. typedef struct AVFrame 
  7.    uint8_t *data[4]; // 有多重意義,其一用NULL 來判斷是否被占用 
  8.    int linesize[4]; 
  9.    uint8_t *base[4]; // 有多重意義,,其一用NULL 來判斷是否分配內(nèi)存 
  10.    //......其他的數(shù)據(jù) 
  11. } AVFrame; 

從定義上可知,,AVPicture是AVFrame的一個子集,他們都是數(shù)據(jù)流在編解過程中用來保存數(shù)據(jù)緩存的對像,,從int av_read_frame(AVFormatContext *s, AVPacket *pkt)函數(shù)看,,從數(shù)據(jù)流讀出的數(shù)據(jù)首先是保存在AVPacket里,也可以理解為一個AVPacket最多只包含一個AVFrame,,而一個 AVFrame可能包含好幾個AVPacket,,AVPacket是種數(shù)據(jù)流分包的概念。記錄一些音視頻相關(guān)的屬性值,,如pts,dts等,,定義如下:

  1. typedef struct AVPacket {    
  2.     int64_t pts;    
  3.     int64_t dts; 
  4.     uint8_t *data; 
  5.     int   size; 
  6.     int   stream_index; 
  7.     int   flags;    
  8.     int   duration; 
  9.     void  (*destruct)(struct AVPacket *); 
  10.     void  *priv; 
  11.     int64_t pos; //< byte position in stream, -1 if unknown    
  12.     int64_t convergence_duration; 
  13. } AVPacket; 

 

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多