ffmpeg的IO操作
ffmpeg的IO操作主要在libavformat庫(kù)中實(shí)現(xiàn),部分實(shí)現(xiàn)用到了libavutl中的工具。網(wǎng)上有一些介紹ffmpeg的IO的文章,但是有些比較老了,并且一些現(xiàn)在ffmpeg結(jié)構(gòu)已經(jīng)一些變化,比如ByteIOContext已經(jīng)改名為AVIOContext,本文章主要介紹IO基礎(chǔ),以及一些ffmpeg對(duì)于一些內(nèi)存操作的方法。
所謂IO就是數(shù)據(jù)的存取,主要的途徑也就是文件或者網(wǎng)絡(luò)。數(shù)據(jù)IO是基于文件格式的,與具體的編碼標(biāo)準(zhǔn)無(wú)關(guān)。
ffmpeg對(duì)各種協(xié)議實(shí)現(xiàn)了封裝,使用同樣的接口,完成對(duì)不同數(shù)據(jù)的讀取。比較屌。
ffmpeg所有的協(xié)議的注冊(cè)是在av_register_all中完成的。協(xié)議保存在鏈表first_protocol中。
ffmpeg的IO層次,不同的封裝層次:
URLContext層次的操作主要有:url_open,url_read,url_write,url_seek,url_close等
AVIOContext層次的操作主要有:avio_open,avio_clse,avio_rxxx,avio_wxxx。事實(shí)上這是對(duì)URLContext層次的上層操作。或者更高層次的抽象封裝。
avio_rxxx和avio_wxxx簡(jiǎn)介的調(diào)用ffurl_read,ffurl_write,實(shí)現(xiàn)讀寫操作,而avio_open根據(jù)文件名來(lái)實(shí)現(xiàn)avio_rxxx和avio_wxxx和不用媒介的操作函數(shù)ffurl_read,ffurl_write的綁定。
avio_rxxx和avio_wxxx實(shí)現(xiàn)的是對(duì)內(nèi)存緩沖區(qū)中數(shù)據(jù)的操作,當(dāng)緩沖區(qū)中數(shù)據(jù)不足或者緩沖區(qū)將要溢出時(shí),調(diào)用flush_buffer和fill_buffer將數(shù)據(jù)把數(shù)據(jù)讀到媒介中。
實(shí)現(xiàn)IO的重要的結(jié)構(gòu):
ffmpeg的針對(duì)不同的媒介的數(shù)據(jù)操作方法稱為url_xxx并記錄在URLProtocol中URLProtocol:用于各種數(shù)據(jù)傳輸協(xié)議,結(jié)構(gòu)中定義了一系列的接口(回調(diào)函數(shù)),包括協(xié)議的打開,讀,寫,定位等。
typedef struct URLProtocol {const char *name;//協(xié)議名稱int (*url_open)( URLContext *h, const char *url, int flags);//打開協(xié)議的函數(shù)int (*url_open2)(URLContext *h, const char *url, int flags, AVDictionary **options);//int (*url_read)( URLContext *h, unsigned char *buf, int size);//讀int (*url_write)(URLContext *h, const unsigned char *buf, int size);//int64_t (*url_seek)( URLContext *h, int64_t pos, int whence);int (*url_close)(URLContext *h);struct URLProtocol *next;int (*url_read_pause)(URLContext *h, int pause);int64_t (*url_read_seek)(URLContext *h, int stream_index, int64_t timestamp, int flags);int (*url_get_file_handle)(URLContext *h);int (*url_get_multi_file_handle)(URLContext *h, int **handles, int *numhandles);int (*url_shutdown)(URLContext *h, int flags);int priv_data_size;const AVClass *priv_data_class;int flags;int (*url_check)(URLContext *h, int mask); } URLProtocol; URLContext 協(xié)議的上下文:可以看成某種協(xié)議的載體,在打開一個(gè)協(xié)議的時(shí)候,全局函數(shù)url_open會(huì)根據(jù)文件的前綴來(lái)判斷使用的協(xié)議,并為該協(xié)議分配好資源,在調(diào)用url_connect來(lái)打開具體的協(xié)議,即調(diào)用prot->url_open
typedef struct URLContext {const AVClass *av_class; /**< information for av_log(). Set by url_open(). */struct URLProtocol *prot;void *priv_data;char *filename; /**< specified URL */int flags;int max_packet_size; /**< if non zero, the stream is packetized with this max packet size */int is_streamed; /**< true if streamed (no seek possible), default = false */int is_connected;AVIOInterruptCB interrupt_callback;int64_t rw_timeout; /**< maximum time to wait for (network) read/write operation completion, in mcs */ } URLContext;
比如file協(xié)議:
URLProtocol ff_file_protocol = {.name = "file",.url_open = file_open,.url_read = file_read,.url_write = file_write,.url_seek = file_seek,.url_close = file_close,.url_get_file_handle = file_get_handle,.url_check = file_check,.priv_data_size = sizeof(FileContext),.priv_data_class = &file_class, };
AVIOContext:
typedef struct AVIOContext {const AVClass *av_class;unsigned char *buffer; int buffer_size; unsigned char *buf_ptr; unsigned char *buf_end;void *opaque; int (*read_packet)(void *opaque, uint8_t *buf, int buf_size);int (*write_packet)(void *opaque, uint8_t *buf, int buf_size);int64_t (*seek)(void *opaque, int64_t offset, int whence);int64_t pos; int must_flush; int eof_reached; int write_flag; int max_packet_size;unsigned long checksum;unsigned char *checksum_ptr;unsigned long (*update_checksum)(unsigned long checksum, const uint8_t *buf, unsigned int size);int error; int (*read_pause)(void *opaque, int pause);int64_t (*read_seek)(void *opaque, int stream_index, int64_t timestamp, int flags);int seekable;int64_t maxsize;int direct;int64_t bytes_read;int seek_count;int writeout_count;int orig_buffer_size; } AVIOContext; AVIOContext和URLContext的關(guān)系:
我們知道數(shù)據(jù)源頭肯定是URLProtocol,而URLContext是對(duì)URLProtocol的封裝,所以AVIOContext肯定和URLContext有某種關(guān)系。在url_fopen中,調(diào)用了url_fdopen對(duì)AVIOContext進(jìn)行初始化。將read_packet,write_packet,seek_packet分別設(shè)置為ffurl_read, ffurl_write,ffurl_seek。
*s = avio_alloc_context(buffer, buffer_size, h->flags & AVIO_FLAG_WRITE, h,(void*)ffurl_read, (void*)ffurl_write, (void*)ffurl_seek);
avio_open/avio_open2函數(shù)的作用
int avio_open2(AVIOContext **s, const char *filename, int flags,const AVIOInterruptCB *int_cb, AVDictionary **options) {URLContext *h;int err;err = ffurl_open(&h, filename, flags, int_cb, options);//通過(guò)解析文件名,找到對(duì)應(yīng)的操作集URLProtocolif (err < 0)return err;/**調(diào)用ffio_init_context把URLProtocol中的ffurl_read, ffurl_write, ffurl_seek,注冊(cè)到AVIOContext結(jié)構(gòu)體中,成為read_packet, write_packet的回調(diào)函數(shù)*/err = ffio_fdopen(s, h);if (err < 0) {ffurl_close(h);return err;}return 0; }解析文件名,找到對(duì)應(yīng)的操作集URLProtocol
int ffurl_open(URLContext **puc, const char *filename, int flags,const AVIOInterruptCB *int_cb, AVDictionary **options) {int ret = ffurl_alloc(puc, filename, flags, int_cb);//文件名的解析在該函數(shù)中實(shí)現(xiàn)的if (ret < 0)return ret;if (options && (*puc)->prot->priv_data_class &&(ret = av_opt_set_dict((*puc)->priv_data, options)) < 0)goto fail;if ((ret = av_opt_set_dict(*puc, options)) < 0)goto fail;ret = ffurl_connect(*puc, options);if (!ret)return 0; fail:ffurl_close(*puc);*puc = NULL;return ret; }
未完待續(xù)。。。。
總結(jié)
以上是生活随笔為你收集整理的ffmpeg的IO操作的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【目标检测】(13) 先验框解码,调整预
- 下一篇: 如何使用网易邮箱大师登录网易企业邮箱?