日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > php教程 > FFmpeg源代碼簡單分析:avio_open2()

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

來源:程序員人生   發布時間:2015-03-13 07:59:22 閱讀次數:11199次
本文簡單分析FFmpeg中1個經常使用的函數avio_open2()。該函數用于打開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()函數參數的含義以下:
s:函數調用成功以后創建的AVIOContext結構體。
url:輸入輸出協議的地址(文件也是1種“廣義”的協議,對文件來講就是文件的路徑)。
flags:打開地址的方式。可以選擇只讀,只寫,或讀寫。取值以下。
AVIO_FLAG_READ:只讀。
AVIO_FLAG_WRITE:只寫。
AVIO_FLAG_READ_WRITE:讀寫。
int_cb:目前還沒有用過。

options:目前還沒有用過。

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


函數調用結構圖

首先貼出來終究分析得出的函數調用結構圖,以下所示。

 

單擊查看更清晰的圖片


avio_open()

有1個和avio_open2()“長得很像”的函數avio_open(),應當是avio_open2()的初期版本。avio_open()比avio_open2()少了最后2個參數。而它前面幾個參數的含義和avio_open2()是1樣的。從源代碼中可以看出,avio_open()內部調用了avio_open2(),并且把avio_open2()的后2個參數設置成了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()的源代碼可以看出,它主要調用了2個函數:ffurl_open()和ffio_fdopen()。其中ffurl_open()用于初始化URLContext,ffio_fdopen()用于根據URLContext初始化AVIOContext。URLContext中包括的URLProtocol完成了具體的協議讀寫等工作。AVIOContext則是在URLContext的讀寫函數外面加上了1層“包裝”(通過retry_transfer_wrapper()函數)。


URLProtocol和URLContext

在查看ffurl_open()和ffio_fdopen()函數之前,首先查看1下URLContext和URLProtocol的定義。這兩個結構體在FFmpeg的初期版本的SDK中是定義在頭文件中可以直接使用的。但是近期的FFmpeg的SDK中已找不到這兩個結構體的定義了。FFmpeg把這兩個結構體移動到了源代碼的內部,變成了內部結構體。
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的定義可以看出,其中包括了用于協議讀寫的函數指針。例如:
url_open():打開協議。
url_read():讀數據。
url_write():寫數據。
url_close():關閉協議。
每種具體的協議都包括了1個URLProtocol結構體,例如:
FILE協議(“文件”在FFmpeg中也被當作1種協議)的結構體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協議進行讀寫的時候,調用url_open()實際上就是調用了file_open()函數,這里限于篇幅不再對file_open()的源代碼進行分析。file_open()函數實際上調用了系統的打開文件函數open()。同理,調用url_read()實際上就是調用了file_read()函數;file_read()函數實際上調用了系統的讀取文件函數read()。url_write(),url_seek()等函數的道理都是1樣的。

LibRTMP協議的結構體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協議的結構體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結構體。下面看1下URLContext結構體。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結構體是URLContext結構體的1個成員。由于還沒有對URLContext結構體進行詳細研究,有關該結構體的代碼不再做過量分析。

ffurl_open()

前文提到AVIOContext中主要調用了2個函數:ffurl_open()和ffio_fdopen()。其中ffurl_open()用于初始化URLContext,ffio_fdopen()用于根據URLContext初始化AVIOContext。下面首先看1下初始化URLContext的函數ffurl_open()。
ffurl_open()的函數定義位于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()主要調用了2個函數:ffurl_alloc()和ffurl_connect()。ffurl_alloc()用于查找適合的URLProtocol,并創建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()主要調用了2個函數:url_find_protocol()根據文件路徑查找適合的URLProtocol,url_alloc_for_protocol()為查找到的URLProtocol創建URLContext。


url_find_protocol()

先來看1下url_find_protocol()函數,定義以下所示。
#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 = ' 主站蜘蛛池模板: 超黄网站 | 美女一级黄色毛片 | 久久噜 | 成人一区二区三区四区 | 麻豆视频在线免费观看 | 国产不卡视频一区二区三区 | 日韩中文字幕视频 | 日韩一区二区三区四区五区 | 久久国产精品免费一区二区三区 | 免费a v在线 | 欧美精品导航 | 久久精品一 | 久久com | 亚洲一区视频 | 国产高清第一页 | 欧美二三四区 | 中文字幕国产一区 | 97午夜 | 久久婷婷国产麻豆91天堂徐州 | 国产伦精品一区二区三区视频黑人 | 亚洲午夜久久久久久久久久久 | 国产99区 | 天堂电影在线观看 | 夜夜久久久 | www久| 五月婷婷网 | 在线视频一区二区三区 | 欧美成人精品一区二区 | 久久久国产精品一区二区三区 | 最近最新2019免费中文视频 | 久久精品播放 | 国产三级欧美三级日产三级99 | 国产专区一区 | 日韩欧美中文字幕在线观看 | 九九视频在线 | 久久精品一区 | av看片| 国产精品国产a级 | 黄色网页在线看 | 免费a级毛片视频 | 国偷自产视频一区二区久 |