mirror of https://git.ffmpeg.org/ffmpeg.git
lavf/mux: add avformat_init_output
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.
This commit is contained in:
parent
8a24e03684
commit
a246fef163
|
@ -15,6 +15,9 @@ libavutil: 2015-08-28
|
||||||
|
|
||||||
API changes, most recent first:
|
API changes, most recent first:
|
||||||
|
|
||||||
|
2016-10-24 - xxxxxxx - lavf 57.54.100 - avformat.h
|
||||||
|
Add avformat_init_output() and AVSTREAM_INIT_IN_ macros
|
||||||
|
|
||||||
2016-10-22 - xxxxxxx - lavu 55.33.100 - avassert.h
|
2016-10-22 - xxxxxxx - lavu 55.33.100 - avassert.h
|
||||||
Add av_assert0_fpu() / av_assert2_fpu()
|
Add av_assert0_fpu() / av_assert2_fpu()
|
||||||
|
|
||||||
|
|
|
@ -618,6 +618,8 @@ typedef struct AVOutputFormat {
|
||||||
* AVStream parameters that need to be set before packets are sent.
|
* AVStream parameters that need to be set before packets are sent.
|
||||||
* This method must not write output.
|
* 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().
|
* Any allocations made here must be freed in deinit().
|
||||||
*/
|
*/
|
||||||
int (*init)(struct AVFormatContext *);
|
int (*init)(struct AVFormatContext *);
|
||||||
|
@ -2374,6 +2376,10 @@ void avformat_close_input(AVFormatContext **s);
|
||||||
* @addtogroup lavf_encoding
|
* @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
|
* Allocate the stream private data and write the stream header to
|
||||||
* an output media file.
|
* an output media file.
|
||||||
|
@ -2385,13 +2391,37 @@ void avformat_close_input(AVFormatContext **s);
|
||||||
* On return this parameter will be destroyed and replaced with a dict containing
|
* On return this parameter will be destroyed and replaced with a dict containing
|
||||||
* options that were not found. May be NULL.
|
* 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
|
av_warn_unused_result
|
||||||
int avformat_write_header(AVFormatContext *s, AVDictionary **options);
|
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.
|
* Write a packet to an output media file.
|
||||||
*
|
*
|
||||||
|
|
|
@ -130,6 +130,16 @@ struct AVFormatInternal {
|
||||||
* Timestamp of the end of the shortest stream.
|
* Timestamp of the end of the shortest stream.
|
||||||
*/
|
*/
|
||||||
int64_t shortest_end;
|
int64_t shortest_end;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 {
|
struct AVStreamInternal {
|
||||||
|
|
|
@ -423,10 +423,13 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||||
*options = tmp;
|
*options = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->oformat->init && (ret = s->oformat->init(s)) < 0) {
|
if (s->oformat->init) {
|
||||||
if (s->oformat->deinit)
|
if ((ret = s->oformat->init(s)) < 0) {
|
||||||
s->oformat->deinit(s);
|
if (s->oformat->deinit)
|
||||||
goto fail;
|
s->oformat->deinit(s);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return ret == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -493,31 +496,64 @@ static int write_header_internal(AVFormatContext *s)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int avformat_write_header(AVFormatContext *s, AVDictionary **options)
|
int avformat_init_output(AVFormatContext *s, AVDictionary **options)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if ((ret = init_muxer(s, options)) < 0)
|
if ((ret = init_muxer(s, options)) < 0)
|
||||||
return ret;
|
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)) {
|
if (!(s->oformat->check_bitstream && s->flags & AVFMT_FLAG_AUTO_BSF)) {
|
||||||
ret = write_header_internal(s);
|
ret = write_header_internal(s);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = init_pts(s)) < 0)
|
if (!s->internal->streams_initialized) {
|
||||||
goto fail;
|
if ((ret = init_pts(s)) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
if (s->avoid_negative_ts < 0) {
|
if (s->avoid_negative_ts < 0) {
|
||||||
av_assert2(s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO);
|
av_assert2(s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO);
|
||||||
if (s->oformat->flags & (AVFMT_TS_NEGATIVE | AVFMT_NOTIMESTAMPS)) {
|
if (s->oformat->flags & (AVFMT_TS_NEGATIVE | AVFMT_NOTIMESTAMPS)) {
|
||||||
s->avoid_negative_ts = 0;
|
s->avoid_negative_ts = 0;
|
||||||
} else
|
} else
|
||||||
s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE;
|
s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return streams_already_initialized;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
if (s->oformat->deinit)
|
if (s->oformat->deinit)
|
||||||
|
@ -1292,6 +1328,10 @@ fail:
|
||||||
if (s->oformat->deinit)
|
if (s->oformat->deinit)
|
||||||
s->oformat->deinit(s);
|
s->oformat->deinit(s);
|
||||||
|
|
||||||
|
s->internal->header_written =
|
||||||
|
s->internal->initialized =
|
||||||
|
s->internal->streams_initialized = 0;
|
||||||
|
|
||||||
if (s->pb)
|
if (s->pb)
|
||||||
avio_flush(s->pb);
|
avio_flush(s->pb);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
// Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium)
|
// Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium)
|
||||||
// Also please add any ticket numbers that you believe might be affected here
|
// Also please add any ticket numbers that you believe might be affected here
|
||||||
#define LIBAVFORMAT_VERSION_MAJOR 57
|
#define LIBAVFORMAT_VERSION_MAJOR 57
|
||||||
#define LIBAVFORMAT_VERSION_MINOR 53
|
#define LIBAVFORMAT_VERSION_MINOR 54
|
||||||
#define LIBAVFORMAT_VERSION_MICRO 100
|
#define LIBAVFORMAT_VERSION_MICRO 100
|
||||||
|
|
||||||
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
|
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
|
||||||
|
|
Loading…
Reference in New Issue