[FFmpeg-devel] [PATCH 02/11] lavf/mux: add avformat_init_output
Rodger Combs
rodger.combs at gmail.com
Sat Sep 10 07:37:16 EEST 2016
This allows a consumer to run the muxer's init function without actually
writing the header, which is useful in chained muxers that support
automatic bitstream filtering.
---
libavformat/avformat.h | 34 +++++++++++++++++++++++--
libavformat/internal.h | 10 ++++++++
libavformat/mux.c | 68 +++++++++++++++++++++++++++++++++++++++-----------
libavformat/version.h | 4 +--
4 files changed, 98 insertions(+), 18 deletions(-)
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 585f00b..7ac9127 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -618,6 +618,8 @@ typedef struct AVOutputFormat {
* AVStream parameters that need to be set before packets are sent.
* This method must not write output.
*
+ * Return 0 if streams were fully configured, 1 if not, negative AVERROR on failure
+ *
* Any allocations made here must be freed in deinit().
*/
int (*init)(struct AVFormatContext *);
@@ -2370,6 +2372,10 @@ void avformat_close_input(AVFormatContext **s);
* @addtogroup lavf_encoding
* @{
*/
+
+#define AVSTREAM_INIT_IN_WRITE_HEADER 0 ///< stream parameters initialized in avformat_write_header
+#define AVSTREAM_INIT_IN_INIT_OUTPUT 1 ///< stream parameters initialized in avformat_init_output
+
/**
* Allocate the stream private data and write the stream header to
* an output media file.
@@ -2381,14 +2387,38 @@ void avformat_close_input(AVFormatContext **s);
* On return this parameter will be destroyed and replaced with a dict containing
* options that were not found. May be NULL.
*
- * @return 0 on success, negative AVERROR on failure.
+ * @return AVSTREAM_INIT_IN_WRITE_HEADER on success if the codec had not already been fully initialized in avformat_init,
+ * AVSTREAM_INIT_IN_INIT_OUTPUT on success if the codec had already been fully initialized in avformat_init,
+ * negative AVERROR on failure.
*
- * @see av_opt_find, av_dict_set, avio_open, av_oformat_next.
+ * @see av_opt_find, av_dict_set, avio_open, av_oformat_next, avformat_init_output.
*/
av_warn_unused_result
int avformat_write_header(AVFormatContext *s, AVDictionary **options);
/**
+ * Allocate the stream private data and initialize the codec, but do not write the header.
+ * May optionally be used before avformat_write_header to initialize stream parameters
+ * before actually writing the header.
+ * If using this function, do not pass the same options to avformat_write_header.
+ *
+ * @param s Media file handle, must be allocated with avformat_alloc_context().
+ * Its oformat field must be set to the desired output format;
+ * Its pb field must be set to an already opened AVIOContext.
+ * @param options An AVDictionary filled with AVFormatContext and muxer-private options.
+ * On return this parameter will be destroyed and replaced with a dict containing
+ * options that were not found. May be NULL.
+ *
+ * @return AVSTREAM_INIT_IN_WRITE_HEADER on success if the codec requires avformat_write_header to fully initialize,
+ * AVSTREAM_INIT_IN_INIT_OUTPUT on success if the codec has been fully initialized,
+ * negative AVERROR on failure.
+ *
+ * @see av_opt_find, av_dict_set, avio_open, av_oformat_next, avformat_write_header.
+ */
+av_warn_unused_result
+int avformat_init_output(AVFormatContext *s, AVDictionary **options);
+
+/**
* Write a packet to an output media file.
*
* This function passes the packet directly to the muxer, without any buffering
diff --git a/libavformat/internal.h b/libavformat/internal.h
index f9278c5..71bcf22 100644
--- a/libavformat/internal.h
+++ b/libavformat/internal.h
@@ -125,6 +125,16 @@ struct AVFormatInternal {
*/
int header_written;
int write_header_ret;
+
+ /**
+ * Whether or not avformat_init_output has already been called
+ */
+ int initialized;
+
+ /**
+ * Whether or not avformat_init_output fully initialized streams
+ */
+ int streams_initialized;
};
struct AVStreamInternal {
diff --git a/libavformat/mux.c b/libavformat/mux.c
index 10d2ba3..a8baee4e 100644
--- a/libavformat/mux.c
+++ b/libavformat/mux.c
@@ -423,10 +423,13 @@ FF_ENABLE_DEPRECATION_WARNINGS
*options = tmp;
}
- if (s->oformat->init && (ret = s->oformat->init(s)) < 0) {
- if (s->oformat->deinit)
- s->oformat->deinit(s);
- goto fail;
+ if (s->oformat->init) {
+ if ((ret = s->oformat->init(s)) < 0) {
+ if (s->oformat->deinit)
+ s->oformat->deinit(s);
+ return ret;
+ }
+ return ret == 0;
}
return 0;
@@ -493,31 +496,64 @@ static int write_header_internal(AVFormatContext *s)
return 0;
}
-int avformat_write_header(AVFormatContext *s, AVDictionary **options)
+int avformat_init_output(AVFormatContext *s, AVDictionary **options)
{
int ret = 0;
if ((ret = init_muxer(s, options)) < 0)
return ret;
+ s->internal->initialized = 1;
+ s->internal->streams_initialized = ret;
+
+ if (s->oformat->init && ret) {
+ if ((ret = init_pts(s)) < 0)
+ return ret;
+
+ if (s->avoid_negative_ts < 0) {
+ av_assert2(s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO);
+ if (s->oformat->flags & (AVFMT_TS_NEGATIVE | AVFMT_NOTIMESTAMPS)) {
+ s->avoid_negative_ts = 0;
+ } else
+ s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE;
+ }
+
+ return AVSTREAM_INIT_IN_INIT_OUTPUT;
+ }
+
+ return AVSTREAM_INIT_IN_WRITE_HEADER;
+}
+
+int avformat_write_header(AVFormatContext *s, AVDictionary **options)
+{
+ int ret = 0;
+ int already_initialized = s->internal->initialized;
+ int streams_already_initialized = s->internal->streams_initialized;
+
+ if (!already_initialized)
+ if ((ret = avformat_init_output(s, options)) < 0)
+ return ret;
+
if (!(s->oformat->check_bitstream && s->flags & AVFMT_FLAG_AUTO_BSF)) {
ret = write_header_internal(s);
if (ret < 0)
goto fail;
}
- if ((ret = init_pts(s)) < 0)
- goto fail;
+ if (!s->internal->streams_initialized) {
+ if ((ret = init_pts(s)) < 0)
+ goto fail;
- if (s->avoid_negative_ts < 0) {
- av_assert2(s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO);
- if (s->oformat->flags & (AVFMT_TS_NEGATIVE | AVFMT_NOTIMESTAMPS)) {
- s->avoid_negative_ts = 0;
- } else
- s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE;
+ if (s->avoid_negative_ts < 0) {
+ av_assert2(s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO);
+ if (s->oformat->flags & (AVFMT_TS_NEGATIVE | AVFMT_NOTIMESTAMPS)) {
+ s->avoid_negative_ts = 0;
+ } else
+ s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE;
+ }
}
- return 0;
+ return streams_already_initialized;
fail:
if (s->oformat->deinit)
@@ -1253,6 +1289,10 @@ fail:
if (s->oformat->deinit)
s->oformat->deinit(s);
+ s->internal->header_written =
+ s->internal->initialized =
+ s->internal->streams_initialized = 0;
+
if (s->pb)
avio_flush(s->pb);
if (ret == 0)
diff --git a/libavformat/version.h b/libavformat/version.h
index 90ac534..34226ca 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -32,8 +32,8 @@
// Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium)
// Also please add any ticket numbers that you believe might be affected here
#define LIBAVFORMAT_VERSION_MAJOR 57
-#define LIBAVFORMAT_VERSION_MINOR 48
-#define LIBAVFORMAT_VERSION_MICRO 103
+#define LIBAVFORMAT_VERSION_MINOR 49
+#define LIBAVFORMAT_VERSION_MICRO 100
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
LIBAVFORMAT_VERSION_MINOR, \
--
2.10.0
More information about the ffmpeg-devel
mailing list