ffmpeg-URL(转)
生活随笔
收集整理的這篇文章主要介紹了
ffmpeg-URL(转)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
ffmpeg中為方便對資源進行訪問,定義了兩個結構體,URLContext中是對具體資源文件進行操作的上下文,URLProtocol則是在將資源進行分類的基礎上,對某一類資源操作的函數集,熟悉Linux設備驅動程序的話,很容易聯想到file_operations結構體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;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;在代碼中搜索url_open,很容易能夠找到ffmpeg中支持的幾個協議:URLProtocol ff_bluray_protocol = {.name = "bluray",.url_close = bluray_close,.url_open = bluray_open,.url_read = bluray_read,.url_seek = bluray_seek,.priv_data_size = sizeof(BlurayContext),.priv_data_class = &bluray_context_class,};URLProtocol ff_data_protocol = {.name = "data",.url_open = data_open,.url_close = data_close,.url_read = data_read,.priv_data_size = sizeof(DataContext),};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,};URLProtocol ff_pipe_protocol = {.name = "pipe",.url_open = pipe_open,.url_read = file_read,.url_write = file_write,.url_get_file_handle = file_get_handle,.url_check = file_check,.priv_data_size = sizeof(FileContext),.priv_data_class = &pipe_class,};URLProtocol ff_ftp_protocol = {.name = "ftp",.url_open = ftp_open,.url_read = ftp_read,.url_write = ftp_write,.url_seek = ftp_seek,.url_close = ftp_close,.url_get_file_handle = ftp_get_file_handle,.url_shutdown = ftp_shutdown,.priv_data_size = sizeof(FTPContext),.priv_data_class = &ftp_context_class,.flags = URL_PROTOCOL_FLAG_NETWORK,};URLProtocol ff_hls_protocol = {.name = "hls",.url_open = hls_open,.url_read = hls_read,.url_close = hls_close,.flags = URL_PROTOCOL_FLAG_NESTED_SCHEME,.priv_data_size = sizeof(HLSContext),};URLProtocol ff_httpproxy_protocol = {.name = "httpproxy",.url_open = http_proxy_open,.url_read = http_buf_read,.url_write = http_proxy_write,.url_close = http_proxy_close,.url_get_file_handle = http_get_file_handle,.priv_data_size = sizeof(HTTPContext),.flags = URL_PROTOCOL_FLAG_NETWORK,};... 還有很多協議,不全部列出了,例如tcp, udp, ...支持這些協議而定義的結構體在av_register_all()函數被調用時而注冊,例如:REGISTER_PROTOCOL(FILE, file);#define REGISTER_PROTOCOL(X, x) \{ \extern URLProtocol ff_##x##_protocol; \if (CONFIG_##X##_PROTOCOL) \ffurl_register_protocol(&ff_##x##_protocol); \}ffurl_register_protocol(&ff_file_protocol);int ffurl_register_protocol(URLProtocol *protocol){URLProtocol **p;p = &first_protocol;while (*p != NULL)p = &(*p)->next;*p = protocol;protocol->next = NULL;return 0;}注冊到以static URLProtocol *first_protocol = NULL;為頭的一個鏈表中,每一個協議結構體是鏈表中的一項;以avio_open2為例: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;}ffurl_open--->ffurl_alloc--->static struct URLProtocol *url_find_protocol(const char *filename)url_find_protocol函數會根據filename判斷協議,這個函數的定義沒太看懂,但是其作用,無非是先判斷具體的協議,然后根據判讀出來的協議,調用URLProtocol *ffurl_protocol_next(URLProtocol *prev){return prev ? prev->next : first_protocol;}函數,在之前注冊的first_protocol鏈表上找到相應的協議結構體,然后返回給函數url_alloc_for_protocol,在這個函數中,則是根據判斷的協議,生成URLContext結構體,uc = av_mallocz(sizeof(URLContext) + strlen(filename) + 1);*puc = uc;在ffurl_open函數中,ffurl_alloc函數返回之后,URLContext **puc結構體就已經被設置完畢,然后在ffurl_open函數中,再調用ret = ffurl_connect(*puc, options);int ffurl_connect(URLContext *uc, AVDictionary **options){int err =uc->prot->url_open2 ? uc->prot->url_open2(uc,uc->filename,uc->flags,options) :uc->prot->url_open(uc, uc->filename, uc->flags);if (err)return err;uc->is_connected = 1;/* We must be careful here as ffurl_seek() could be slow,* for example for http */if ((uc->flags & AVIO_FLAG_WRITE) || !strcmp(uc->prot->name, "file"))if (!uc->is_streamed && ffurl_seek(uc, 0, SEEK_SET) < 0)uc->is_streamed = 1;return 0;}prot是協議,在url_alloc_for_protocol函數中設置的:uc->prot = up;然后url_open2, url_open都是在協議結構體中定義的函數指針,以"file"協議為例: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,
};url_open2是NULL,則調用url_open函數指針指向的函數file_open:static int file_open(URLContext *h, const char *filename, int flags){FileContext *c = h->priv_data;int access;int fd;struct stat st;av_strstart(filename, "file:", &filename);if (flags & AVIO_FLAG_WRITE && flags & AVIO_FLAG_READ) {access = O_CREAT | O_RDWR;if (c->trunc)access |= O_TRUNC;} else if (flags & AVIO_FLAG_WRITE) {access = O_CREAT | O_WRONLY;if (c->trunc)access |= O_TRUNC;} else {access = O_RDONLY;}#ifdef O_BINARYaccess |= O_BINARY;#endiffd = avpriv_open(filename, access, 0666);if (fd == -1)return AVERROR(errno);c->fd = fd;h->is_streamed = !fstat(fd, &st) && S_ISFIFO(st.st_mode);return 0;}
http://blog.csdn.net/xiruanliuwei/article/details/24928237
總結
以上是生活随笔為你收集整理的ffmpeg-URL(转)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2022年股灾真的来了吗,要从三个方面判
- 下一篇: 微信企业号开发之正式版的本地调试