This solves the problem discussed in https://ffmpeg.org/pipermail/ffmpeg-devel/2015-September/179238.html
by allowing AVCodec::write_header to be delayed until after packets have been
run through required bitstream filters in order to generate global extradata.
It also provides a mechanism by which a muxer can add a bitstream filter to a
stream automatically, rather than prompting the user to do so.
... | ... |
@@ -15,6 +15,9 @@ libavutil: 2015-08-28 |
15 | 15 |
|
16 | 16 |
API changes, most recent first: |
17 | 17 |
|
18 |
+2015-12-28 - xxxxxxx - lavf 57.21.100 - avformat.h |
|
19 |
+ Add automatic bitstream filtering; add av_apply_bitstream_filters() |
|
20 |
+ |
|
18 | 21 |
2015-12-22 - xxxxxxx - lavfi 6.21.101 - avfilter.h |
19 | 22 |
Deprecate avfilter_link_set_closed(). |
20 | 23 |
Applications are not supposed to mess with links, |
... | ... |
@@ -600,6 +600,29 @@ typedef struct AVOutputFormat { |
600 | 600 |
*/ |
601 | 601 |
int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps); |
602 | 602 |
enum AVCodecID data_codec; /**< default data codec */ |
603 |
+ /** |
|
604 |
+ * Initialize format. May allocate data here, and set any AVFormatContext or |
|
605 |
+ * AVStream parameters that need to be set before packets are sent. |
|
606 |
+ * This method must not write output. |
|
607 |
+ * |
|
608 |
+ * Any allocations made here must be freed in deinit(). |
|
609 |
+ */ |
|
610 |
+ int (*init)(struct AVFormatContext *); |
|
611 |
+ /** |
|
612 |
+ * Deinitialize format. If present, this is called whenever the muxer is being |
|
613 |
+ * destroyed, regardless of whether or not the header has been written. |
|
614 |
+ * |
|
615 |
+ * If a trailer is being written, this is called after write_trailer(). |
|
616 |
+ * |
|
617 |
+ * This is called if init() fails as well. |
|
618 |
+ */ |
|
619 |
+ void (*deinit)(struct AVFormatContext *); |
|
620 |
+ /** |
|
621 |
+ * Set up any necessary bitstream filtering and extract any extra data needed |
|
622 |
+ * for the global header. |
|
623 |
+ * Return 0 if more packets from this stream must be checked; 1 if not. |
|
624 |
+ */ |
|
625 |
+ int (*check_bitstream)(struct AVFormatContext *, const AVPacket *pkt); |
|
603 | 626 |
} AVOutputFormat; |
604 | 627 |
/** |
605 | 628 |
* @} |
... | ... |
@@ -117,6 +117,11 @@ struct AVFormatInternal { |
117 | 117 |
int inject_global_side_data; |
118 | 118 |
|
119 | 119 |
int avoid_negative_ts_use_pts; |
120 |
+ |
|
121 |
+ /** |
|
122 |
+ * Whether or not a header has already been written |
|
123 |
+ */ |
|
124 |
+ int header_written; |
|
120 | 125 |
}; |
121 | 126 |
|
122 | 127 |
struct AVStreamInternal { |
... | ... |
@@ -125,6 +130,18 @@ struct AVStreamInternal { |
125 | 125 |
* from dts. |
126 | 126 |
*/ |
127 | 127 |
int reorder; |
128 |
+ |
|
129 |
+ /** |
|
130 |
+ * bitstream filter to run on stream |
|
131 |
+ * - encoding: Set by muxer using ff_stream_add_bitstream_filter |
|
132 |
+ * - decoding: unused |
|
133 |
+ */ |
|
134 |
+ AVBitStreamFilterContext *bsfc; |
|
135 |
+ |
|
136 |
+ /** |
|
137 |
+ * Whether or not check_bitstream should still be run on each packet |
|
138 |
+ */ |
|
139 |
+ int bitstream_checked; |
|
128 | 140 |
}; |
129 | 141 |
|
130 | 142 |
#ifdef __GNUC__ |
... | ... |
@@ -405,6 +405,11 @@ FF_ENABLE_DEPRECATION_WARNINGS |
405 | 405 |
*options = tmp; |
406 | 406 |
} |
407 | 407 |
|
408 |
+ if (s->oformat->init && (ret = s->oformat->init(s)) < 0) { |
|
409 |
+ s->oformat->deinit(s); |
|
410 |
+ goto fail; |
|
411 |
+ } |
|
412 |
+ |
|
408 | 413 |
return 0; |
409 | 414 |
|
410 | 415 |
fail: |
... | ... |
@@ -456,7 +461,7 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options) |
456 | 456 |
if ((ret = init_muxer(s, options)) < 0) |
457 | 457 |
return ret; |
458 | 458 |
|
459 |
- if (s->oformat->write_header) { |
|
459 |
+ if (s->oformat->write_header && !s->oformat->check_bitstream) { |
|
460 | 460 |
ret = s->oformat->write_header(s); |
461 | 461 |
if (ret >= 0 && s->pb && s->pb->error < 0) |
462 | 462 |
ret = s->pb->error; |
... | ... |
@@ -464,6 +469,7 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options) |
464 | 464 |
return ret; |
465 | 465 |
if (s->flush_packets && s->pb && s->pb->error >= 0 && s->flags & AVFMT_FLAG_FLUSH_PACKETS) |
466 | 466 |
avio_flush(s->pb); |
467 |
+ s->internal->header_written = 1; |
|
467 | 468 |
} |
468 | 469 |
|
469 | 470 |
if ((ret = init_pts(s)) < 0) |
... | ... |
@@ -668,6 +674,18 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) |
668 | 668 |
} |
669 | 669 |
|
670 | 670 |
did_split = av_packet_split_side_data(pkt); |
671 |
+ |
|
672 |
+ if (!s->internal->header_written && s->oformat->write_header) { |
|
673 |
+ ret = s->oformat->write_header(s); |
|
674 |
+ if (ret >= 0 && s->pb && s->pb->error < 0) |
|
675 |
+ ret = s->pb->error; |
|
676 |
+ if (ret < 0) |
|
677 |
+ goto fail; |
|
678 |
+ if (s->flush_packets && s->pb && s->pb->error >= 0 && s->flags & AVFMT_FLAG_FLUSH_PACKETS) |
|
679 |
+ avio_flush(s->pb); |
|
680 |
+ s->internal->header_written = 1; |
|
681 |
+ } |
|
682 |
+ |
|
671 | 683 |
if ((pkt->flags & AV_PKT_FLAG_UNCODED_FRAME)) { |
672 | 684 |
AVFrame *frame = (AVFrame *)pkt->data; |
673 | 685 |
av_assert0(pkt->size == UNCODED_FRAME_PACKET_SIZE); |
... | ... |
@@ -684,7 +702,7 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) |
684 | 684 |
ret = s->pb->error; |
685 | 685 |
} |
686 | 686 |
|
687 |
- |
|
687 |
+fail: |
|
688 | 688 |
if (did_split) |
689 | 689 |
av_packet_merge_side_data(pkt); |
690 | 690 |
|
... | ... |
@@ -1021,6 +1039,17 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt) |
1021 | 1021 |
ret = AVERROR(EINVAL); |
1022 | 1022 |
goto fail; |
1023 | 1023 |
} |
1024 |
+ |
|
1025 |
+ if (s->oformat->check_bitstream) { |
|
1026 |
+ if (!st->internal->bitstream_checked) { |
|
1027 |
+ if ((ret = s->oformat->check_bitstream(s, pkt)) < 0) |
|
1028 |
+ goto fail; |
|
1029 |
+ else if (ret == 1) |
|
1030 |
+ st->internal->bitstream_checked = 1; |
|
1031 |
+ } |
|
1032 |
+ } |
|
1033 |
+ |
|
1034 |
+ av_apply_bitstream_filters(st->codec, pkt, st->internal->bsfc); |
|
1024 | 1035 |
} else { |
1025 | 1036 |
av_log(s, AV_LOG_TRACE, "av_interleaved_write_frame FLUSH\n"); |
1026 | 1037 |
flush = 1; |
... | ... |
@@ -1077,14 +1106,28 @@ int av_write_trailer(AVFormatContext *s) |
1077 | 1077 |
goto fail; |
1078 | 1078 |
} |
1079 | 1079 |
|
1080 |
+ if (!s->internal->header_written && s->oformat->write_header) { |
|
1081 |
+ ret = s->oformat->write_header(s); |
|
1082 |
+ if (ret >= 0 && s->pb && s->pb->error < 0) |
|
1083 |
+ ret = s->pb->error; |
|
1084 |
+ if (ret < 0) |
|
1085 |
+ goto fail; |
|
1086 |
+ if (s->flush_packets && s->pb && s->pb->error >= 0 && s->flags & AVFMT_FLAG_FLUSH_PACKETS) |
|
1087 |
+ avio_flush(s->pb); |
|
1088 |
+ s->internal->header_written = 1; |
|
1089 |
+ } |
|
1090 |
+ |
|
1080 | 1091 |
fail: |
1081 |
- if (s->oformat->write_trailer) |
|
1092 |
+ if ((s->internal->header_written || !s->oformat->write_header) && s->oformat->write_trailer) |
|
1082 | 1093 |
if (ret >= 0) { |
1083 | 1094 |
ret = s->oformat->write_trailer(s); |
1084 | 1095 |
} else { |
1085 | 1096 |
s->oformat->write_trailer(s); |
1086 | 1097 |
} |
1087 | 1098 |
|
1099 |
+ if (s->oformat->deinit) |
|
1100 |
+ s->oformat->deinit(s); |
|
1101 |
+ |
|
1088 | 1102 |
if (s->pb) |
1089 | 1103 |
avio_flush(s->pb); |
1090 | 1104 |
if (ret == 0) |
... | ... |
@@ -30,7 +30,7 @@ |
30 | 30 |
#include "libavutil/version.h" |
31 | 31 |
|
32 | 32 |
#define LIBAVFORMAT_VERSION_MAJOR 57 |
33 |
-#define LIBAVFORMAT_VERSION_MINOR 20 |
|
33 |
+#define LIBAVFORMAT_VERSION_MINOR 21 |
|
34 | 34 |
#define LIBAVFORMAT_VERSION_MICRO 100 |
35 | 35 |
|
36 | 36 |
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ |