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;
1. The context environment in which context is currently running is actually the global variable of C, which is used to save the common variables that need to be used by multiple functions when the current module is running. Each module has a context to indicate the running context. The specific implementation in the module must use the corresponding context. The file protocol is implemented in file. C. It contains a filecontext and an avclass file_class.
2. av_class in urlcontext is its own avclass ffurl_context_class
3. The prot in urlcontext points to the specific Protocol. urlprotocol abstracts some interfaces. The upper layer uses these interfaces to operate data, and implements these interfaces in different protocols. If a file protocol is opened, the prot points to urlprotocol ff_file_protocol.
4. priv_data in urlcontext is a bit difficult to understand. It is easier to understand urlprotocol first.
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;
5. priv_data_size in urlprotocol indicates the size of the currently implemented context, which is the size of the filecontext structure in the file protocol.
6. priv_data_class in urlprotocol refers to the specific avclass of the current implementation. In the file protocol, it refers to avclass file_class.
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,};
7. the specific implementation of the file protocol implements the interface in urlprotocol, and the two priv variables in it refer to the size of its own filecontext structure and avclass file_class.
8. priv_data in urlcontext actually points to the context of the specific Protocol. In the file protocol, it is a filecontext allocated, and the class in filecontext points to its own avclass, that is, priv_data_class in ff_file_protocol points to the same avclass.
typedef struct FileContext { const AVClass *class; int fd; int trunc; int blocksize;} FileContext;
9. At present, avclass has not found the application. In the file protocol, it seems to be related to some set parameters. You can change the value of the members in filecontext through parameters.
static const AVClass file_class = { .class_name = "file", .item_name = av_default_item_name, .option = file_options, .version = LIBAVUTIL_VERSION_INT,};
10. Find the specific protocol in the url_find_protocol function. The search is based on the protocol name and urlprotocol. if the given filename is a path without a write protocol, it is directly used as the file protocol. After finding the relevant protocol, you need to allocate context (for example, filecontext) and set members in urlcontext. The implementation is in the url_alloc_for_protocol function.
11. avio. c maintains a urlprotocol list and registers the Protocol through the ffurl_register_protocol function. This function is triggered in av_register_all. All codecs, muxers, protocol, and libraries are registered here.
FFmpeg protocol preliminary study