mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-08 13:22:53 +02:00
avformat/mux: stop delaying writing the header
Every bitstream filter behaves as intended now, so there's no need to wait for the first packet of every stream. Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
parent
5a412a5c3c
commit
d6d605eb05
@ -1449,7 +1449,7 @@ typedef struct AVFormatContext {
|
|||||||
#endif
|
#endif
|
||||||
#define AVFMT_FLAG_FAST_SEEK 0x80000 ///< Enable fast, but inaccurate seeks for some formats
|
#define AVFMT_FLAG_FAST_SEEK 0x80000 ///< Enable fast, but inaccurate seeks for some formats
|
||||||
#define AVFMT_FLAG_SHORTEST 0x100000 ///< Stop muxing when the shortest stream stops.
|
#define AVFMT_FLAG_SHORTEST 0x100000 ///< Stop muxing when the shortest stream stops.
|
||||||
#define AVFMT_FLAG_AUTO_BSF 0x200000 ///< Wait for packet data before writing a header, and add bitstream filters as requested by the muxer
|
#define AVFMT_FLAG_AUTO_BSF 0x200000 ///< Add bitstream filters as requested by the muxer
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum size of the data read from input for determining
|
* Maximum size of the data read from input for determining
|
||||||
|
@ -120,12 +120,6 @@ struct AVFormatInternal {
|
|||||||
|
|
||||||
int avoid_negative_ts_use_pts;
|
int avoid_negative_ts_use_pts;
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether or not a header has already been written
|
|
||||||
*/
|
|
||||||
int header_written;
|
|
||||||
int write_header_ret;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timestamp of the end of the shortest stream.
|
* Timestamp of the end of the shortest stream.
|
||||||
*/
|
*/
|
||||||
|
@ -458,25 +458,6 @@ static void flush_if_needed(AVFormatContext *s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int write_header_internal(AVFormatContext *s)
|
|
||||||
{
|
|
||||||
if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
|
|
||||||
avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_HEADER);
|
|
||||||
if (s->oformat->write_header) {
|
|
||||||
int ret = s->oformat->write_header(s);
|
|
||||||
if (ret >= 0 && s->pb && s->pb->error < 0)
|
|
||||||
ret = s->pb->error;
|
|
||||||
s->internal->write_header_ret = ret;
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
flush_if_needed(s);
|
|
||||||
}
|
|
||||||
s->internal->header_written = 1;
|
|
||||||
if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
|
|
||||||
avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_UNKNOWN);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int avformat_init_output(AVFormatContext *s, AVDictionary **options)
|
int avformat_init_output(AVFormatContext *s, AVDictionary **options)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -515,11 +496,18 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options)
|
|||||||
if ((ret = avformat_init_output(s, options)) < 0)
|
if ((ret = avformat_init_output(s, options)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (!(s->oformat->check_bitstream && s->flags & AVFMT_FLAG_AUTO_BSF)) {
|
if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
|
||||||
ret = write_header_internal(s);
|
avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_HEADER);
|
||||||
|
if (s->oformat->write_header) {
|
||||||
|
ret = s->oformat->write_header(s);
|
||||||
|
if (ret >= 0 && s->pb && s->pb->error < 0)
|
||||||
|
ret = s->pb->error;
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
flush_if_needed(s);
|
||||||
}
|
}
|
||||||
|
if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
|
||||||
|
avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_UNKNOWN);
|
||||||
|
|
||||||
if (!s->internal->streams_initialized) {
|
if (!s->internal->streams_initialized) {
|
||||||
if ((ret = init_pts(s)) < 0)
|
if ((ret = init_pts(s)) < 0)
|
||||||
@ -739,12 +727,6 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!s->internal->header_written) {
|
|
||||||
ret = s->internal->write_header_ret ? s->internal->write_header_ret : write_header_internal(s);
|
|
||||||
if (ret < 0)
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((pkt->flags & AV_PKT_FLAG_UNCODED_FRAME)) {
|
if ((pkt->flags & AV_PKT_FLAG_UNCODED_FRAME)) {
|
||||||
AVFrame *frame = (AVFrame *)pkt->data;
|
AVFrame *frame = (AVFrame *)pkt->data;
|
||||||
av_assert0(pkt->size == UNCODED_FRAME_PACKET_SIZE);
|
av_assert0(pkt->size == UNCODED_FRAME_PACKET_SIZE);
|
||||||
@ -760,8 +742,6 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt)
|
|||||||
ret = s->pb->error;
|
ret = s->pb->error;
|
||||||
}
|
}
|
||||||
|
|
||||||
fail:
|
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
pkt->pts = pts_backup;
|
pkt->pts = pts_backup;
|
||||||
pkt->dts = dts_backup;
|
pkt->dts = dts_backup;
|
||||||
@ -894,11 +874,6 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt)
|
|||||||
|
|
||||||
if (!pkt) {
|
if (!pkt) {
|
||||||
if (s->oformat->flags & AVFMT_ALLOW_FLUSH) {
|
if (s->oformat->flags & AVFMT_ALLOW_FLUSH) {
|
||||||
if (!s->internal->header_written) {
|
|
||||||
ret = s->internal->write_header_ret ? s->internal->write_header_ret : write_header_internal(s);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
ret = s->oformat->write_packet(s, NULL);
|
ret = s->oformat->write_packet(s, NULL);
|
||||||
flush_if_needed(s);
|
flush_if_needed(s);
|
||||||
if (ret >= 0 && s->pb && s->pb->error < 0)
|
if (ret >= 0 && s->pb && s->pb->error < 0)
|
||||||
@ -1282,14 +1257,8 @@ int av_write_trailer(AVFormatContext *s)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!s->internal->header_written) {
|
|
||||||
ret = s->internal->write_header_ret ? s->internal->write_header_ret : write_header_internal(s);
|
|
||||||
if (ret < 0)
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
if (s->internal->header_written && s->oformat->write_trailer) {
|
if (s->oformat->write_trailer) {
|
||||||
if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
|
if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb)
|
||||||
avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER);
|
avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_TRAILER);
|
||||||
if (ret >= 0) {
|
if (ret >= 0) {
|
||||||
@ -1302,7 +1271,6 @@ 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->initialized =
|
||||||
s->internal->streams_initialized = 0;
|
s->internal->streams_initialized = 0;
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ static const AVOption avformat_options[] = {
|
|||||||
{"seek2any", "allow seeking to non-keyframes on demuxer level when supported", OFFSET(seek2any), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, D},
|
{"seek2any", "allow seeking to non-keyframes on demuxer level when supported", OFFSET(seek2any), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, D},
|
||||||
{"bitexact", "do not write random/volatile data", 0, AV_OPT_TYPE_CONST, { .i64 = AVFMT_FLAG_BITEXACT }, 0, 0, E, "fflags" },
|
{"bitexact", "do not write random/volatile data", 0, AV_OPT_TYPE_CONST, { .i64 = AVFMT_FLAG_BITEXACT }, 0, 0, E, "fflags" },
|
||||||
{"shortest", "stop muxing with the shortest stream", 0, AV_OPT_TYPE_CONST, { .i64 = AVFMT_FLAG_SHORTEST }, 0, 0, E, "fflags" },
|
{"shortest", "stop muxing with the shortest stream", 0, AV_OPT_TYPE_CONST, { .i64 = AVFMT_FLAG_SHORTEST }, 0, 0, E, "fflags" },
|
||||||
{"autobsf", "add needed bsfs automatically (delays header until each stream's first packet is written)", 0, AV_OPT_TYPE_CONST, { .i64 = AVFMT_FLAG_AUTO_BSF }, 0, 0, E, "fflags" },
|
{"autobsf", "add needed bsfs automatically", 0, AV_OPT_TYPE_CONST, { .i64 = AVFMT_FLAG_AUTO_BSF }, 0, 0, E, "fflags" },
|
||||||
{"analyzeduration", "specify how many microseconds are analyzed to probe the input", OFFSET(max_analyze_duration), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, D},
|
{"analyzeduration", "specify how many microseconds are analyzed to probe the input", OFFSET(max_analyze_duration), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, D},
|
||||||
{"cryptokey", "decryption key", OFFSET(key), AV_OPT_TYPE_BINARY, {.dbl = 0}, 0, 0, D},
|
{"cryptokey", "decryption key", OFFSET(key), AV_OPT_TYPE_BINARY, {.dbl = 0}, 0, 0, D},
|
||||||
{"indexmem", "max memory used for timestamp index (per stream)", OFFSET(max_index_size), AV_OPT_TYPE_INT, {.i64 = 1<<20 }, 0, INT_MAX, D},
|
{"indexmem", "max memory used for timestamp index (per stream)", OFFSET(max_index_size), AV_OPT_TYPE_INT, {.i64 = 1<<20 }, 0, INT_MAX, D},
|
||||||
|
@ -238,54 +238,6 @@ fail:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fifo_write_header_err_tst(AVFormatContext *oc, AVDictionary **opts,
|
|
||||||
const FailingMuxerPacketData *pkt_data)
|
|
||||||
{
|
|
||||||
int ret = 0, i;
|
|
||||||
AVPacket pkt;
|
|
||||||
|
|
||||||
av_init_packet(&pkt);
|
|
||||||
|
|
||||||
ret = avformat_write_header(oc, opts);
|
|
||||||
if (ret) {
|
|
||||||
fprintf(stderr, "Unexpected write_header failure: %s\n",
|
|
||||||
av_err2str(ret));
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < MAX_TST_PACKETS; i++ ) {
|
|
||||||
ret = prepare_packet(&pkt, pkt_data, i);
|
|
||||||
if (ret < 0) {
|
|
||||||
fprintf(stderr, "Failed to prepare test packet: %s\n",
|
|
||||||
av_err2str(ret));
|
|
||||||
goto write_trailer_and_fail;
|
|
||||||
}
|
|
||||||
ret = av_write_frame(oc, &pkt);
|
|
||||||
av_packet_unref(&pkt);
|
|
||||||
if (ret < 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ret) {
|
|
||||||
fprintf(stderr, "write_packet not failed when supposed to.\n");
|
|
||||||
goto fail;
|
|
||||||
} else if (ret != -1) {
|
|
||||||
fprintf(stderr, "Unexpected write_packet error: %s\n", av_err2str(ret));
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = av_write_trailer(oc);
|
|
||||||
if (ret < 0)
|
|
||||||
fprintf(stderr, "Unexpected write_trailer error: %s\n", av_err2str(ret));
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
write_trailer_and_fail:
|
|
||||||
av_write_trailer(oc);
|
|
||||||
fail:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int fifo_overflow_drop_test(AVFormatContext *oc, AVDictionary **opts,
|
static int fifo_overflow_drop_test(AVFormatContext *oc, AVDictionary **opts,
|
||||||
const FailingMuxerPacketData *data)
|
const FailingMuxerPacketData *data)
|
||||||
{
|
{
|
||||||
@ -403,10 +355,6 @@ const TestCase tests[] = {
|
|||||||
* exactly what was on input */
|
* exactly what was on input */
|
||||||
{fifo_basic_test, "nonfail test", NULL,1, 0, 0, {0, 0, 0}},
|
{fifo_basic_test, "nonfail test", NULL,1, 0, 0, {0, 0, 0}},
|
||||||
|
|
||||||
/* Test that we receive delayed write_header error from one of the write_packet
|
|
||||||
* calls. */
|
|
||||||
{fifo_write_header_err_tst, "write header error test", NULL, 0, -1, 0, {0, 0, 0}},
|
|
||||||
|
|
||||||
/* Each write_packet will fail 3 times before operation is successful. If recovery
|
/* Each write_packet will fail 3 times before operation is successful. If recovery
|
||||||
* Since recovery is on, fifo muxer should not return any errors. */
|
* Since recovery is on, fifo muxer should not return any errors. */
|
||||||
{fifo_basic_test, "recovery test", "attempt_recovery=1:recovery_wait_time=0",
|
{fifo_basic_test, "recovery test", "attempt_recovery=1:recovery_wait_time=0",
|
||||||
|
@ -2,7 +2,6 @@ flush count: 1
|
|||||||
pts seen nr: 15
|
pts seen nr: 15
|
||||||
pts seen: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14
|
pts seen: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14
|
||||||
nonfail test: ok
|
nonfail test: ok
|
||||||
write header error test: ok
|
|
||||||
recovery test: ok
|
recovery test: ok
|
||||||
flush count: 1
|
flush count: 1
|
||||||
pts seen nr: 15
|
pts seen nr: 15
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
55270be3b5d393d770a1dfcb19b68271 *tests/data/fate/rgb24-mkv.matroska
|
09ee413b2d92a6be5e3b18e9e20a1f74 *tests/data/fate/rgb24-mkv.matroska
|
||||||
58345 tests/data/fate/rgb24-mkv.matroska
|
58342 tests/data/fate/rgb24-mkv.matroska
|
||||||
#tb 0: 1/10
|
#tb 0: 1/10
|
||||||
#media_type 0: video
|
#media_type 0: video
|
||||||
#codec_id 0: rawvideo
|
#codec_id 0: rawvideo
|
||||||
|
Loading…
Reference in New Issue
Block a user