FFMpeg分析详细分析

 与其说是分析,不如说是学习,只是看在自己第一次写系列文章的份上,给足自己面子,取个有"深度"的题目!如有人被题目所蒙骗进来,还望见谅!

      URLProtocol,URLContext和ByteIOContext是FFMpeg操作文件(即I/O,包括网络数据流)的结构,这几个结构现实的功能类似于C++的多态继承吧,C++的多态是通过子类继承实现,而FFMpeg的“多态”是通过静态对像现实。这部分的代码非常值得C程序借鉴,我是说,如果你要在C里实现类似C++多态性的功能;比如当你要区分你老婆和情人之间的不同功能时。

     好了,先来看一下这三个struct的定义吧

01 typedef struct URLProtocol {
02  
03   
04  
05     const char*name;                                                                   //Rotocol名称
06  
07     int (*url_open)(URLContext *h, const char *url, int flags);      //open函数指针对象,以下类似
08  
09     int (*url_read)(URLContext *h, unsigned char *buf, int size);
10  
11     int (*url_write)(URLContext *h, unsigned char *buf, int size);
12  
13     int64_t (*url_seek)(URLContext *h, int64_t pos, int whence);
14  
15     int (*url_close)(URLContext *h);
16  
17     struct URLProtocol *next;                                                       //指向下一个URLProtocol,具体说明见备注1
18  
19     int (*url_read_pause)(URLContext *h, int pause);
20  
21     int64_t (*url_read_seek)(URLContext *h, int stream_index,int64_t timestamp, intflags);
22  
23     int (*url_get_file_handle)(URLContext *h);
24  
25 } URLProtocol;

 

备注1:FFMpeg所有的Protol类型都用这个变量串成一个链表,表头为avio.c里的URLProtocol *first_protocol = NULL;

每个文件类似都有自己的一个URLProtocol静态对象,如libavformat/file.c里

01 URLProtocol file_protocol = {
02  
03     "file",
04  
05     file_open,
06  
07     file_read,
08  
09     file_write,
10  
11     file_seek,
12  
13     file_close,
14  
15     .url_get_file_handle = file_get_handle,
16  
17 };

再通过av_register_protocol()将他们链接成链表。在FFMpeg中所有的URLProtocol对像值都在编译时确定。

 

01 typedef struct URLContext {
02  
03 #if LIBAVFORMAT_VERSION_MAJOR >= 53
04  
05     const AVClass *av_class; ///< information for av_log(). Set by url_open().
06  
07 #endif
08  
09     struct URLProtocol *prot;          //指向具体的I/0类型,在运行时通过文件URL确定,如是file类型时就是file_protocol         
10  
11     int flags;
12  
13     int is_streamed;  /**< true if streamed (no seek possible), default = false */
14  
15     int max_packet_size;  /**< if non zero, the stream is packetized with this max packet size */
16  
17     void *priv_data;                       //指向具体的I/O句柄
18  
19     char *filename; /**< specified URL */
20  
21 } URLContext;

不同于URLProtocol对象值在编译时确定,URLContext对象值是在运行过程中根据输入的I/O类型动态确定的。这一动一静组合起到了C++的多态继承一样的作用。URLContext像是基类,为大家共同所有,而URLProtocol像是子类部分。

 

01 typedef struct {
02  
03     unsigned char *buffer;
04  
05     int buffer_size;
06  
07     unsigned char *buf_ptr, *buf_end;
08  
09     void *opaque;
10  
11     int (*read_packet)(void *opaque, uint8_t *buf, int buf_size);
12  
13     int (*write_packet)(void *opaque, uint8_t *buf, int buf_size);
14  
15     int64_t (*seek)(void *opaque, int64_t offset, int whence);
16  
17     int64_t pos; /**< position in the file of the current buffer */
18  
19     int must_flush; /**< true if the next seek should flush */
20  
21     int eof_reached; /**< true if eof reached */
22  
23     int write_flag;  /**< true if open for writing */
24  
25     int is_streamed;
26  
27     int max_packet_size;
28  
29     unsigned long checksum;
30  
31     unsigned char *checksum_ptr;
32  
33     unsigned long (*update_checksum)(unsigned long checksum, const uint8_t *buf, unsigned int size);
34  
35     int error;         ///< contains the error code or 0 if no error happened
36  
37     int (*read_pause)(void *opaque, int pause);
38  
39     int64_t (*read_seek)(void *opaque, int stream_index,
40  
41                          int64_t timestamp, int flags);
42  
43 } ByteIOContext;

ByteIOContext是URLContext和URLProtocol 一个扩展,也是FFMpeg提供给用户的接口,URLContext 和URLProtocol对用户是透明,我们所有的操作是通过ByteIOContext现实。这几个struct的相关的关键函数有:

01 int av_open_input_file(AVFormatContext **ic_ptr, const char *filename,
02  
03                        AVInputFormat *fmt,
04  
05                        int buf_size,
06  
07                        AVFormatParameters *ap)
08  

你可能感兴趣的:(Stream,File,header,url,input,Codec)