diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 479f1f51c1..21b0e3103b 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2369,6 +2369,61 @@ int av_read_play(AVFormatContext *s); */ int av_read_pause(AVFormatContext *s); +/** + * Command IDs that can be sent to the demuxer + * + * The following commands can be sent to a demuxer + * using ::avformat_send_command. + */ +enum AVFormatCommandID { + /** + * Send a RTSP `SET_PARAMETER` request to the server + * + * Sends an SET_PARAMETER RTSP command to the server, + * with a data payload of type ::AVRTSPCommandRequest, + * ownership of it and its data remains with the caller. + * + * A reply retrieved is of type ::AVRTSPResponse and it + * and its contents must be freed by the caller. + */ + AVFORMAT_COMMAND_RTSP_SET_PARAMETER, +}; + +/** + * Send a command to the demuxer + * + * Sends the specified command and (depending on the command) + * optionally a command-specific payload to the demuxer to handle. + * + * @param s Format context, must be allocated with + * ::avformat_alloc_context. + * @param id Identifier of type ::AVFormatCommandID, + * indicating the command to send. + * @param data Command-specific data, allocated by the caller + * and ownership remains with the caller. + * For details what is expected here, consult the + * documentation of the respective ::AVFormatCommandID. + */ +int avformat_send_command(AVFormatContext *s, enum AVFormatCommandID id, void *data); + +/** + * Receive a command reply from the demuxer + * + * Retrieves a reply for a previously sent command from the muxer. + * + * @param s Format context, must be allocated with + * ::avformat_alloc_context. + * @param id Identifier of type ::AVFormatCommandID, + * indicating the command for which to retrieve + * the reply. + * @param data_out Pointee is set to the command reply, the actual + * type depends on the command. This is allocated by + * the muxer and must be freed with ::av_free. + * For details on the actual data set here, consult the + * documentation of the respective ::AVFormatCommandID. + */ +int avformat_receive_command_reply(AVFormatContext *s, enum AVFormatCommandID id, void **data_out); + /** * Close an opened input AVFormatContext. Free it and all its contents * and set *s to NULL. diff --git a/libavformat/demux.h b/libavformat/demux.h index c0c2164e92..f09afc849f 100644 --- a/libavformat/demux.h +++ b/libavformat/demux.h @@ -53,6 +53,16 @@ enum FFInputFormatStreamState { FF_INFMT_STATE_PAUSE, }; +/** + * Command handling options + * Different options influencing the behaviour of + * the FFInputFormat::handle_command callback. + */ +enum FFInputFormatCommandOption { + FF_INFMT_COMMAND_SUBMIT, + FF_INFMT_COMMAND_GET_REPLY, +}; + typedef struct FFInputFormat { /** * The public AVInputFormat. See avformat.h for it. @@ -130,9 +140,33 @@ typedef struct FFInputFormat { enum FFInputFormatStreamState state); /** - * Currently unused. + * Handle demuxer commands + * This callback is used to either send a command to a demuxer + * (FF_INFMT_COMMAND_SUBMIT), or to retrieve the reply for + * a previously sent command (FF_INFMT_COMMAND_GET_REPLY). + * + * Demuxers implementing this must return AVERROR(ENOTSUP) + * if the provided \p id is not handled by the demuxer. + * Demuxers should return AVERROR(EAGAIN) if they can handle + * a specific command but are not able to at the moment. + * When a reply is requested that is not available yet, the + * demuxer should also return AVERROR(EAGAIN). + * + * Depending on \p opt, the \p data will be either a pointer + * to the command payload structure for the specified ID, or + * a pointer to the buffer for the command reply for the + * specified ID. + * + * When a command is submitted, before a previous reply + * was requested from the demuxer, the demuxer should discard + * the old reply. + * + * @see avformat_send_command() + * @see avformat_receive_command_reply() */ - int (*unused)(void); + int (*handle_command)(struct AVFormatContext *, + enum FFInputFormatCommandOption opt, + enum AVFormatCommandID id, void *data); /** * Seek to timestamp ts. diff --git a/libavformat/demux_utils.c b/libavformat/demux_utils.c index 34b6ba4ac7..639fed35fd 100644 --- a/libavformat/demux_utils.c +++ b/libavformat/demux_utils.c @@ -188,6 +188,20 @@ int av_read_pause(AVFormatContext *s) return AVERROR(ENOSYS); } +int avformat_send_command(AVFormatContext *s, enum AVFormatCommandID id, void *data) +{ + if (ffifmt(s->iformat)->handle_command) + return ffifmt(s->iformat)->handle_command(s, FF_INFMT_COMMAND_SUBMIT, id, data); + return AVERROR(ENOSYS); +} + +int avformat_receive_command_reply(AVFormatContext *s, enum AVFormatCommandID id, void **data_out) +{ + if (ffifmt(s->iformat)->handle_command) + return ffifmt(s->iformat)->handle_command(s, FF_INFMT_COMMAND_GET_REPLY, id, data_out); + return AVERROR(ENOSYS); +} + int ff_generate_avci_extradata(AVStream *st) { static const uint8_t avci100_1080p_extradata[] = {