多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內(nèi)最全IT社區(qū)平臺 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁 > php開源 > php教程 > FFmpeg源代碼簡單分析:avio_open2()

FFmpeg源代碼簡單分析:avio_open2()

來源:程序員人生   發(fā)布時間:2015-03-13 07:59:22 閱讀次數(shù):11194次
本文簡單分析FFmpeg中1個經(jīng)常使用的函數(shù)avio_open2()。該函數(shù)用于打開FFmpeg的輸入輸出文件。avio_open2()的聲明位于libavformatavio.h文件中,以下所示。
/** * Create and initialize a AVIOContext for accessing the * resource indicated by url. * @note When the resource indicated by url has been opened in * read+write mode, the AVIOContext can be used only for writing. * * @param s Used to return the pointer to the created AVIOContext. * In case of failure the pointed to value is set to NULL. * @param url resource to access * @param flags flags which control how the resource indicated by url * is to be opened * @param int_cb an interrupt callback to be used at the protocols level * @param options A dictionary filled with protocol-private options. On return * this parameter will be destroyed and replaced with a dict containing options * that were not found. May be NULL. * @return >= 0 in case of success, a negative value corresponding to an * AVERROR code in case of failure */ int avio_open2(AVIOContext **s, const char *url, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options);

avio_open2()函數(shù)參數(shù)的含義以下:
s:函數(shù)調(diào)用成功以后創(chuàng)建的AVIOContext結(jié)構(gòu)體。
url:輸入輸出協(xié)議的地址(文件也是1種“廣義”的協(xié)議,對文件來講就是文件的路徑)。
flags:打開地址的方式。可以選擇只讀,只寫,或讀寫。取值以下。
AVIO_FLAG_READ:只讀。
AVIO_FLAG_WRITE:只寫。
AVIO_FLAG_READ_WRITE:讀寫。
int_cb:目前還沒有用過。

options:目前還沒有用過。

該函數(shù)最典型的例子可以參考:最簡單的基于FFMPEG的視頻編碼器(YUV編碼為H.264)


函數(shù)調(diào)用結(jié)構(gòu)圖

首先貼出來終究分析得出的函數(shù)調(diào)用結(jié)構(gòu)圖,以下所示。

 

單擊查看更清晰的圖片


avio_open()

有1個和avio_open2()“長得很像”的函數(shù)avio_open(),應(yīng)當(dāng)是avio_open2()的初期版本。avio_open()比avio_open2()少了最后2個參數(shù)。而它前面幾個參數(shù)的含義和avio_open2()是1樣的。從源代碼中可以看出,avio_open()內(nèi)部調(diào)用了avio_open2(),并且把avio_open2()的后2個參數(shù)設(shè)置成了NULL,因此它的功能實際上和avio_open2()是1樣的。avio_open()源代碼以下所示。
int avio_open(AVIOContext **s, const char *filename, int flags) { return avio_open2(s, filename, flags, NULL, NULL); }

avio_open2()

下面看1下avio_open2()的源代碼,位于libavformataviobuf.c文件中。
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); if (err < 0) return err; err = ffio_fdopen(s, h); if (err < 0) { ffurl_close(h); return err; } return 0; }

從avio_open2()的源代碼可以看出,它主要調(diào)用了2個函數(shù):ffurl_open()和ffio_fdopen()。其中ffurl_open()用于初始化URLContext,ffio_fdopen()用于根據(jù)URLContext初始化AVIOContext。URLContext中包括的URLProtocol完成了具體的協(xié)議讀寫等工作。AVIOContext則是在URLContext的讀寫函數(shù)外面加上了1層“包裝”(通過retry_transfer_wrapper()函數(shù))。


URLProtocol和URLContext

在查看ffurl_open()和ffio_fdopen()函數(shù)之前,首先查看1下URLContext和URLProtocol的定義。這兩個結(jié)構(gòu)體在FFmpeg的初期版本的SDK中是定義在頭文件中可以直接使用的。但是近期的FFmpeg的SDK中已找不到這兩個結(jié)構(gòu)體的定義了。FFmpeg把這兩個結(jié)構(gòu)體移動到了源代碼的內(nèi)部,變成了內(nèi)部結(jié)構(gòu)體。
URLProtocol的定義位于libavformaturl.h,以下所示。
typedef struct URLProtocol { const char *name; int (*url_open)( URLContext *h, const char *url, int flags); /** * This callback is to be used by protocols which open further nested * protocols. options are then to be passed to ffurl_open()/ffurl_connect() * for those nested protocols. */ int (*url_open2)(URLContext *h, const char *url, int flags, AVDictionary **options); /** * Read data from the protocol. * If data is immediately available (even less than size), EOF is * reached or an error occurs (including EINTR), return immediately. * Otherwise: * In non-blocking mode, return AVERROR(EAGAIN) immediately. * In blocking mode, wait for data/EOF/error with a short timeout (0.1s), * and return AVERROR(EAGAIN) on timeout. * Checking interrupt_callback, looping on EINTR and EAGAIN and until * enough data has been read is left to the calling function; see * retry_transfer_wrapper in avio.c. */ 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;

從URLProtocol的定義可以看出,其中包括了用于協(xié)議讀寫的函數(shù)指針。例如:
url_open():打開協(xié)議。
url_read():讀數(shù)據(jù)。
url_write():寫數(shù)據(jù)。
url_close():關(guān)閉協(xié)議。
每種具體的協(xié)議都包括了1個URLProtocol結(jié)構(gòu)體,例如:
FILE協(xié)議(“文件”在FFmpeg中也被當(dāng)作1種協(xié)議)的結(jié)構(gòu)體ff_file_protocol的定義以下所示(位于libavformatfile.c)。
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, };

在使用FILE協(xié)議進行讀寫的時候,調(diào)用url_open()實際上就是調(diào)用了file_open()函數(shù),這里限于篇幅不再對file_open()的源代碼進行分析。file_open()函數(shù)實際上調(diào)用了系統(tǒng)的打開文件函數(shù)open()。同理,調(diào)用url_read()實際上就是調(diào)用了file_read()函數(shù);file_read()函數(shù)實際上調(diào)用了系統(tǒng)的讀取文件函數(shù)read()。url_write(),url_seek()等函數(shù)的道理都是1樣的。

LibRTMP協(xié)議的結(jié)構(gòu)體ff_librtmp_protocol的定義以下所示(位于libavformatlibrtmp.c)。
URLProtocol ff_librtmp_protocol = { .name = "rtmp", .url_open = rtmp_open, .url_read = rtmp_read, .url_write = rtmp_write, .url_close = rtmp_close, .url_read_pause = rtmp_read_pause, .url_read_seek = rtmp_read_seek, .url_get_file_handle = rtmp_get_file_handle, .priv_data_size = sizeof(LibRTMPContext), .priv_data_class = &librtmp_class, .flags = URL_PROTOCOL_FLAG_NETWORK, };

UDP協(xié)議的結(jié)構(gòu)體ff_udp_protocol的定義以下所示(位于libavformatudp.c)。
URLProtocol ff_udp_protocol = { .name = "udp", .url_open = udp_open, .url_read = udp_read, .url_write = udp_write, .url_close = udp_close, .url_get_file_handle = udp_get_file_handle, .priv_data_size = sizeof(UDPContext), .priv_data_class = &udp_context_class, .flags = URL_PROTOCOL_FLAG_NETWORK, };

上文中簡單介紹了URLProtocol結(jié)構(gòu)體。下面看1下URLContext結(jié)構(gòu)體。URLContext的定義也位于libavformaturl.h,以下所示。
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;

從代碼中可以看出,URLProtocol結(jié)構(gòu)體是URLContext結(jié)構(gòu)體的1個成員。由于還沒有對URLContext結(jié)構(gòu)體進行詳細(xì)研究,有關(guān)該結(jié)構(gòu)體的代碼不再做過量分析。

ffurl_open()

前文提到AVIOContext中主要調(diào)用了2個函數(shù):ffurl_open()和ffio_fdopen()。其中ffurl_open()用于初始化URLContext,ffio_fdopen()用于根據(jù)URLContext初始化AVIOContext。下面首先看1下初始化URLContext的函數(shù)ffurl_open()。
ffurl_open()的函數(shù)定義位于libavformatavio.c中,以下所示。
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); 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; }

從代碼中可以看出,ffurl_open()主要調(diào)用了2個函數(shù):ffurl_alloc()和ffurl_connect()。ffurl_alloc()用于查找適合的URLProtocol,并創(chuàng)建1個URLContext;ffurl_connect()用于打開取得的URLProtocol。


ffurl_alloc()

ffurl_alloc()的定義位于libavformatavio.c中,以下所示。
int ffurl_alloc(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb) { URLProtocol *p = NULL; if (!first_protocol) { av_log(NULL, AV_LOG_WARNING, "No URL Protocols are registered. " "Missing call to av_register_all()? "); } p = url_find_protocol(filename); if (p) return url_alloc_for_protocol(puc, p, filename, flags, int_cb); *puc = NULL; if (av_strstart(filename, "https:", NULL)) av_log(NULL, AV_LOG_WARNING, "https protocol not found, recompile with openssl or gnutls enabled. "); return AVERROR_PROTOCOL_NOT_FOUND; }

從代碼中可以看出,ffurl_alloc()主要調(diào)用了2個函數(shù):url_find_protocol()根據(jù)文件路徑查找適合的URLProtocol,url_alloc_for_protocol()為查找到的URLProtocol創(chuàng)建URLContext。


url_find_protocol()

先來看1下url_find_protocol()函數(shù),定義以下所示。
#define URL_SCHEME_CHARS "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789+-." static struct URLProtocol *url_find_protocol(const char *filename) { URLProtocol *up = NULL; char proto_str[128], proto_nested[128], *ptr; size_t proto_len = strspn(filename, URL_SCHEME_CHARS); if (filename[proto_len] != ':' && (filename[proto_len] != ',' || !strchr(filename + proto_len + 1, ':')) || is_dos_path(filename)) strcpy(proto_str, "file"); else av_strlcpy(proto_str, filename, FFMIN(proto_len + 1, sizeof(proto_str))); if ((ptr = strchr(proto_str, ','))) *ptr = ' 主站蜘蛛池模板: 亚洲爱爱图片 | www.欧美com| 精品福利一区二区三区 | free性欧美hd另类精品 | 国产亚洲精品一区二区 | 国产欧美亚洲专区第一页 | 欧美精品一区午夜小说 | 欧美一卡二卡3卡4卡无卡免费 | 精品国产看高清国产毛片 | 亚洲欧美成人永久第一网站 | 欧美国产成人一区二区三区 | 最近中文字幕大全高清视频 | 久久国产精品网 | 日韩福利网站 | 69av视频 | 精品久久久一二三区 | 亚洲资源最新版在线观看 | 天堂mv亚洲mv在线播放9蜜 | 国产免费久久精品99久久 | 波多野结衣在线一区二区 | 免费观看欧美一级牲片一 | h视频免费高清在线观看 | 国产精品v欧美精品v日韩 | 日本一二线不卡在线观看 | 最近中文字幕高清字幕在线视频 | 亚洲免费视频观看 | 国产亚洲精品线观看77 | 色淫影院| 久久一区二区三区四区 | 一级在线观看视频 | 亚洲精品久久久久久下一站 | 午夜影院网站 | 在线观看视频免费播放 | 久久在线免费观看视频 | 欧美日韩性生活视频 | 久久久久久久久久久观看 | 91久久综合九色综合欧美98 | poronovideos德国极品 | 国产成人久久精品推最新 | 秋霞日韩理论高清在线观看 | 高清欧美不卡一区二区三区 |