* [FFmpeg-devel] [PATCH] libavformat/dashenc: preserve metadata from container and streams (PR #20594)
@ 2025-09-24 10:35 damitha via ffmpeg-devel
0 siblings, 0 replies; only message in thread
From: damitha via ffmpeg-devel @ 2025-09-24 10:35 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: damitha
PR #20594 opened by damitha
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20594
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20594.patch
Currently metadata is dropped at the container and stream level when dash muxer is used. This is fixing that
>From 7b3b20a1e8719ff922e509623f3763af3574c9ff Mon Sep 17 00:00:00 2001
From: Damitha Gunawardena <damitha.guns@gmail.com>
Date: Wed, 24 Sep 2025 20:12:31 +1000
Subject: [PATCH 1/2] preserve metadata in dashenc
---
libavformat/dashenc.c | 621 ++++++++++++++++++++++++++----------------
1 file changed, 382 insertions(+), 239 deletions(-)
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index af92e38bbd..7ca46e201a 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -123,10 +123,10 @@ typedef struct OutputStream {
int last_flags;
int bit_rate;
int first_segment_bit_rate;
- SegmentType segment_type; /* segment type selected for this particular stream */
+ SegmentType segment_type; /* segment type selected for this particular stream */
const char *format_name;
const char *extension_name;
- const char *single_file_name; /* file names selected for this particular stream */
+ const char *single_file_name; /* file names selected for this particular stream */
const char *init_seg_name;
const char *media_seg_name;
@@ -148,7 +148,7 @@ typedef struct OutputStream {
} OutputStream;
typedef struct DASHContext {
- const AVClass *class; /* Class for private options. */
+ const AVClass *class; /* Class for private options. */
char *adaptation_sets;
AdaptationSet *as;
int nb_as;
@@ -168,7 +168,7 @@ typedef struct DASHContext {
time_t start_time_s;
int64_t presentation_time_offset;
char dirname[1024];
- const char *single_file_name; /* file names as specified in options */
+ const char *single_file_name; /* file names as specified in options */
const char *init_seg_name;
const char *media_seg_name;
const char *utc_timing_url;
@@ -187,7 +187,7 @@ typedef struct DASHContext {
int index_correction;
AVDictionary *format_options;
int global_sidx;
- SegmentType segment_type_option; /* segment type as specified in options */
+ SegmentType segment_type_option; /* segment type as specified in options */
int ignore_io_errors;
int lhls;
int ldash;
@@ -210,12 +210,12 @@ static const struct codec_string {
enum AVCodecID id;
const char str[8];
} codecs[] = {
- { AV_CODEC_ID_VP8, "vp8" },
- { AV_CODEC_ID_VP9, "vp9" },
- { AV_CODEC_ID_VORBIS, "vorbis" },
- { AV_CODEC_ID_OPUS, "opus" },
- { AV_CODEC_ID_FLAC, "flac" },
- { AV_CODEC_ID_NONE }
+ {AV_CODEC_ID_VP8, "vp8"},
+ {AV_CODEC_ID_VP9, "vp9"},
+ {AV_CODEC_ID_VORBIS, "vorbis"},
+ {AV_CODEC_ID_OPUS, "opus"},
+ {AV_CODEC_ID_FLAC, "flac"},
+ {AV_CODEC_ID_NONE}
};
static int dashenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename,
@@ -256,22 +256,19 @@ static void dashenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filenam
}
}
-static const char *get_format_str(SegmentType segment_type)
-{
+static const char *get_format_str(SegmentType segment_type) {
switch (segment_type) {
- case SEGMENT_TYPE_MP4: return "mp4";
- case SEGMENT_TYPE_WEBM: return "webm";
+ case SEGMENT_TYPE_MP4: return "mp4";
+ case SEGMENT_TYPE_WEBM: return "webm";
}
return NULL;
}
-static const char *get_extension_str(SegmentType type, int single_file)
-{
+static const char *get_extension_str(SegmentType type, int single_file) {
switch (type) {
-
- case SEGMENT_TYPE_MP4: return single_file ? "mp4" : "m4s";
- case SEGMENT_TYPE_WEBM: return "webm";
- default: return NULL;
+ case SEGMENT_TYPE_MP4: return single_file ? "mp4" : "m4s";
+ case SEGMENT_TYPE_WEBM: return "webm";
+ default: return NULL;
}
}
@@ -282,8 +279,7 @@ static int handle_io_open_error(AVFormatContext *s, int err, char *url) {
return c->ignore_io_errors ? 0 : err;
}
-static inline SegmentType select_segment_type(SegmentType segment_type, enum AVCodecID codec_id)
-{
+static inline SegmentType select_segment_type(SegmentType segment_type, enum AVCodecID codec_id) {
if (segment_type == SEGMENT_TYPE_AUTO) {
if (codec_id == AV_CODEC_ID_OPUS || codec_id == AV_CODEC_ID_VORBIS ||
codec_id == AV_CODEC_ID_VP8 || codec_id == AV_CODEC_ID_VP9) {
@@ -296,8 +292,7 @@ static inline SegmentType select_segment_type(SegmentType segment_type, enum AVC
return segment_type;
}
-static int init_segment_types(AVFormatContext *s)
-{
+static int init_segment_types(AVFormatContext *s) {
DASHContext *c = s->priv_data;
int has_mp4_streams = 0;
for (int i = 0; i < s->nb_streams; ++i) {
@@ -320,8 +315,8 @@ static int init_segment_types(AVFormatContext *s)
}
if (c->hls_playlist && !has_mp4_streams) {
- av_log(s, AV_LOG_WARNING, "No mp4 streams, disabling HLS manifest generation\n");
- c->hls_playlist = 0;
+ av_log(s, AV_LOG_WARNING, "No mp4 streams, disabling HLS manifest generation\n");
+ c->hls_playlist = 0;
}
return 0;
@@ -343,9 +338,8 @@ static void set_vp9_codec_str(AVFormatContext *s, AVCodecParameters *par,
}
static void set_codec_str(AVFormatContext *s, AVCodecParameters *par,
- AVRational *frame_rate, char *str, int size)
-{
- const AVCodecTag *tags[2] = { NULL, NULL };
+ AVRational *frame_rate, char *str, int size) {
+ const AVCodecTag *tags[2] = {NULL, NULL};
uint32_t tag;
int i;
@@ -438,8 +432,7 @@ static void set_codec_str(AVFormatContext *s, AVCodecParameters *par,
}
}
-static int flush_dynbuf(DASHContext *c, OutputStream *os, int *range_length)
-{
+static int flush_dynbuf(DASHContext *c, OutputStream *os, int *range_length) {
uint8_t *buffer;
if (!os->ctx->pb) {
@@ -467,8 +460,7 @@ static int flush_dynbuf(DASHContext *c, OutputStream *os, int *range_length)
}
}
-static void set_http_options(AVDictionary **options, DASHContext *c)
-{
+static void set_http_options(AVDictionary **options, DASHContext *c) {
if (c->method)
av_dict_set(options, "method", c->method, 0);
av_dict_copy(options, c->http_opts, 0);
@@ -493,7 +485,7 @@ static void get_start_index_number(OutputStream *os, DASHContext *c,
*start_index = 0;
*start_number = 1;
if (c->window_size) {
- *start_index = FFMAX(os->nb_segments - c->window_size, 0);
+ *start_index = FFMAX(os->nb_segments - c->window_size, 0);
*start_number = FFMAX(os->segment_index - c->window_size, 1);
}
}
@@ -556,10 +548,10 @@ static void write_hls_media_playlist(OutputStream *os, AVFormatContext *s,
seg->prog_date_time = prog_date_time;
ret = ff_hls_write_file_entry(c->m3u8_out, 0, c->single_file,
- (double) seg->duration / timescale, 0,
- seg->range_length, seg->start_pos, NULL,
- c->single_file ? os->initfile : seg->file,
- &prog_date_time, 0, 0, 0);
+ (double) seg->duration / timescale, 0,
+ seg->range_length, seg->start_pos, NULL,
+ c->single_file ? os->initfile : seg->file,
+ &prog_date_time, 0, 0, 0);
if (ret < 0) {
av_log(os->ctx, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n");
}
@@ -577,8 +569,7 @@ static void write_hls_media_playlist(OutputStream *os, AVFormatContext *s,
ff_rename(temp_filename_hls, filename_hls, os->ctx);
}
-static int flush_init_segment(AVFormatContext *s, OutputStream *os)
-{
+static int flush_init_segment(AVFormatContext *s, OutputStream *os) {
DASHContext *c = s->priv_data;
int ret, range_length;
@@ -595,8 +586,7 @@ static int flush_init_segment(AVFormatContext *s, OutputStream *os)
return 0;
}
-static void dash_free(AVFormatContext *s)
-{
+static void dash_free(AVFormatContext *s) {
DASHContext *c = s->priv_data;
int i, j;
@@ -638,8 +628,7 @@ static void dash_free(AVFormatContext *s)
}
static void output_segment_list(OutputStream *os, AVIOContext *out, AVFormatContext *s,
- int representation_id, int final)
-{
+ int representation_id, int final) {
DASHContext *c = s->priv_data;
int i, start_index, start_number;
get_start_index_number(os, c, &start_index, &start_number);
@@ -656,14 +645,15 @@ static void output_segment_list(OutputStream *os, AVIOContext *out, AVFormatCont
if (c->streaming && os->availability_time_offset && !final)
avio_printf(out, "availabilityTimeComplete=\"false\" ");
- avio_printf(out, "initialization=\"%s\" media=\"%s\" startNumber=\"%d\"", os->init_seg_name, os->media_seg_name, c->use_timeline ? start_number : 1);
+ avio_printf(out, "initialization=\"%s\" media=\"%s\" startNumber=\"%d\"", os->init_seg_name, os->media_seg_name,
+ c->use_timeline ? start_number : 1);
if (c->presentation_time_offset)
avio_printf(out, " presentationTimeOffset=\"%"PRId64"\"", c->presentation_time_offset);
avio_printf(out, ">\n");
if (c->use_timeline) {
int64_t cur_time = 0;
avio_printf(out, "\t\t\t\t\t<SegmentTimeline>\n");
- for (i = start_index; i < os->nb_segments; ) {
+ for (i = start_index; i < os->nb_segments;) {
Segment *seg = os->segments[i];
int repeat = 0;
avio_printf(out, "\t\t\t\t\t\t<S ");
@@ -674,7 +664,8 @@ static void output_segment_list(OutputStream *os, AVIOContext *out, AVFormatCont
avio_printf(out, "d=\"%"PRId64"\" ", seg->duration);
while (i + repeat + 1 < os->nb_segments &&
os->segments[i + repeat + 1]->duration == seg->duration &&
- os->segments[i + repeat + 1]->time == os->segments[i + repeat]->time + os->segments[i + repeat]->duration)
+ os->segments[i + repeat + 1]->time == os->segments[i + repeat]->time + os->segments[i + repeat]->
+ duration)
repeat++;
if (repeat > 0)
avio_printf(out, "r=\"%d\" ", repeat);
@@ -687,18 +678,23 @@ static void output_segment_list(OutputStream *os, AVIOContext *out, AVFormatCont
avio_printf(out, "\t\t\t\t</SegmentTemplate>\n");
} else if (c->single_file) {
avio_printf(out, "\t\t\t\t<BaseURL>%s</BaseURL>\n", os->initfile);
- avio_printf(out, "\t\t\t\t<SegmentList timescale=\"%d\" duration=\"%"PRId64"\" startNumber=\"%d\">\n", AV_TIME_BASE, FFMIN(os->seg_duration, os->last_duration), start_number);
- avio_printf(out, "\t\t\t\t\t<Initialization range=\"%"PRId64"-%"PRId64"\" />\n", os->init_start_pos, os->init_start_pos + os->init_range_length - 1);
+ avio_printf(out, "\t\t\t\t<SegmentList timescale=\"%d\" duration=\"%"PRId64"\" startNumber=\"%d\">\n",
+ AV_TIME_BASE, FFMIN(os->seg_duration, os->last_duration), start_number);
+ avio_printf(out, "\t\t\t\t\t<Initialization range=\"%"PRId64"-%"PRId64"\" />\n", os->init_start_pos,
+ os->init_start_pos + os->init_range_length - 1);
for (i = start_index; i < os->nb_segments; i++) {
Segment *seg = os->segments[i];
- avio_printf(out, "\t\t\t\t\t<SegmentURL mediaRange=\"%"PRId64"-%"PRId64"\" ", seg->start_pos, seg->start_pos + seg->range_length - 1);
+ avio_printf(out, "\t\t\t\t\t<SegmentURL mediaRange=\"%"PRId64"-%"PRId64"\" ", seg->start_pos,
+ seg->start_pos + seg->range_length - 1);
if (seg->index_length)
- avio_printf(out, "indexRange=\"%"PRId64"-%"PRId64"\" ", seg->start_pos, seg->start_pos + seg->index_length - 1);
+ avio_printf(out, "indexRange=\"%"PRId64"-%"PRId64"\" ", seg->start_pos,
+ seg->start_pos + seg->index_length - 1);
avio_printf(out, "/>\n");
}
avio_printf(out, "\t\t\t\t</SegmentList>\n");
} else {
- avio_printf(out, "\t\t\t\t<SegmentList timescale=\"%d\" duration=\"%"PRId64"\" startNumber=\"%d\">\n", AV_TIME_BASE, FFMIN(os->seg_duration, os->last_duration), start_number);
+ avio_printf(out, "\t\t\t\t<SegmentList timescale=\"%d\" duration=\"%"PRId64"\" startNumber=\"%d\">\n",
+ AV_TIME_BASE, FFMIN(os->seg_duration, os->last_duration), start_number);
avio_printf(out, "\t\t\t\t\t<Initialization sourceURL=\"%s\" />\n", os->initfile);
for (i = start_index; i < os->nb_segments; i++) {
Segment *seg = os->segments[i];
@@ -709,11 +705,10 @@ static void output_segment_list(OutputStream *os, AVIOContext *out, AVFormatCont
if (!c->lhls || final) {
write_hls_media_playlist(os, s, representation_id, final, NULL);
}
-
}
static char *xmlescape(const char *str) {
- int outlen = strlen(str)*3/2 + 6;
+ int outlen = strlen(str) * 3 / 2 + 6;
char *out = av_realloc(NULL, outlen + 1);
int pos = 0;
if (!out)
@@ -752,8 +747,7 @@ static char *xmlescape(const char *str) {
return out;
}
-static void write_time(AVIOContext *out, int64_t time)
-{
+static void write_time(AVIOContext *out, int64_t time) {
int seconds = time / AV_TIME_BASE;
int fractions = time % AV_TIME_BASE;
int minutes = seconds / 60;
@@ -768,8 +762,7 @@ static void write_time(AVIOContext *out, int64_t time)
avio_printf(out, "%d.%dS", seconds, fractions / (AV_TIME_BASE / 10));
}
-static void format_date(char *buf, int size, int64_t time_us)
-{
+static void format_date(char *buf, int size, int64_t time_us) {
struct tm *ptm, tmbuf;
int64_t time_ms = time_us / 1000;
const time_t time_s = time_ms / 1000;
@@ -787,18 +780,21 @@ static void format_date(char *buf, int size, int64_t time_us)
}
static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_index,
- int final)
-{
+ int final) {
DASHContext *c = s->priv_data;
AdaptationSet *as = &c->as[as_index];
AVDictionaryEntry *lang, *role;
int i;
- avio_printf(out, "\t\t<AdaptationSet id=\"%d\" contentType=\"%s\" startWithSAP=\"1\" segmentAlignment=\"true\" bitstreamSwitching=\"true\"",
- as->id, as->media_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio");
- if (as->media_type == AVMEDIA_TYPE_VIDEO && as->max_frame_rate.num && !as->ambiguous_frame_rate && av_cmp_q(as->min_frame_rate, as->max_frame_rate) < 0)
+ avio_printf(
+ out,
+ "\t\t<AdaptationSet id=\"%d\" contentType=\"%s\" startWithSAP=\"1\" segmentAlignment=\"true\" bitstreamSwitching=\"true\"",
+ as->id, as->media_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio");
+ if (as->media_type == AVMEDIA_TYPE_VIDEO && as->max_frame_rate.num && !as->ambiguous_frame_rate && av_cmp_q(
+ as->min_frame_rate, as->max_frame_rate) < 0)
avio_printf(out, " maxFrameRate=\"%d/%d\"", as->max_frame_rate.num, as->max_frame_rate.den);
- else if (as->media_type == AVMEDIA_TYPE_VIDEO && as->max_frame_rate.num && !as->ambiguous_frame_rate && !av_cmp_q(as->min_frame_rate, as->max_frame_rate))
+ else if (as->media_type == AVMEDIA_TYPE_VIDEO && as->max_frame_rate.num && !as->ambiguous_frame_rate && !av_cmp_q(
+ as->min_frame_rate, as->max_frame_rate))
avio_printf(out, " frameRate=\"%d/%d\"", as->max_frame_rate.num, as->max_frame_rate.den);
if (as->media_type == AVMEDIA_TYPE_VIDEO) {
avio_printf(out, " maxWidth=\"%d\" maxHeight=\"%d\"", as->max_width, as->max_height);
@@ -812,7 +808,10 @@ static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_ind
if (!final && c->ldash && as->max_frag_duration && !(c->profile & MPD_PROFILE_DVB))
avio_printf(out, "\t\t\t<Resync dT=\"%"PRId64"\" type=\"0\"/>\n", as->max_frag_duration);
if (as->trick_idx >= 0)
- avio_printf(out, "\t\t\t<EssentialProperty id=\"%d\" schemeIdUri=\"http://dashif.org/guidelines/trickmode\" value=\"%d\"/>\n", as->id, as->trick_idx);
+ avio_printf(
+ out,
+ "\t\t\t<EssentialProperty id=\"%d\" schemeIdUri=\"http://dashif.org/guidelines/trickmode\" value=\"%d\"/>\n",
+ as->id, as->trick_idx);
role = av_dict_get(as->metadata, "role", NULL, 0);
if (role)
avio_printf(out, "\t\t\t<Role schemeIdUri=\"urn:mpeg:dash:role:2011\" value=\"%s\"/>\n", role->value);
@@ -835,8 +834,10 @@ static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_ind
snprintf(bandwidth_str, sizeof(bandwidth_str), " bandwidth=\"%d\"", os->first_segment_bit_rate);
if (as->media_type == AVMEDIA_TYPE_VIDEO) {
- avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"video/%s\" codecs=\"%s\"%s width=\"%d\" height=\"%d\"",
- i, os->format_name, os->codec_str, bandwidth_str, s->streams[i]->codecpar->width, s->streams[i]->codecpar->height);
+ avio_printf(
+ out, "\t\t\t<Representation id=\"%d\" mimeType=\"video/%s\" codecs=\"%s\"%s width=\"%d\" height=\"%d\"",
+ i, os->format_name, os->codec_str, bandwidth_str, s->streams[i]->codecpar->width,
+ s->streams[i]->codecpar->height);
if (st->codecpar->field_order == AV_FIELD_UNKNOWN)
avio_printf(out, " scanType=\"unknown\"");
else if (st->codecpar->field_order != AV_FIELD_PROGRESSIVE)
@@ -847,21 +848,31 @@ static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_ind
if (as->trick_idx >= 0) {
AdaptationSet *tas = &c->as[as->trick_idx];
if (!as->ambiguous_frame_rate && !tas->ambiguous_frame_rate)
- avio_printf(out, " maxPlayoutRate=\"%d\"", FFMAX((int)av_q2d(av_div_q(tas->min_frame_rate, as->min_frame_rate)), 1));
+ avio_printf(out, " maxPlayoutRate=\"%d\"",
+ FFMAX((int)av_q2d(av_div_q(tas->min_frame_rate, as->min_frame_rate)), 1));
}
if (!os->coding_dependency)
avio_printf(out, " codingDependency=\"false\"");
avio_printf(out, ">\n");
} else {
- avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"audio/%s\" codecs=\"%s\"%s audioSamplingRate=\"%d\">\n",
+ avio_printf(
+ out,
+ "\t\t\t<Representation id=\"%d\" mimeType=\"audio/%s\" codecs=\"%s\"%s audioSamplingRate=\"%d\">\n",
i, os->format_name, os->codec_str, bandwidth_str, s->streams[i]->codecpar->sample_rate);
- avio_printf(out, "\t\t\t\t<AudioChannelConfiguration schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\" value=\"%d\" />\n",
+ avio_printf(
+ out,
+ "\t\t\t\t<AudioChannelConfiguration schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\" value=\"%d\" />\n",
s->streams[i]->codecpar->ch_layout.nb_channels);
}
if (!final && c->write_prft && os->producer_reference_time_str[0]) {
- avio_printf(out, "\t\t\t\t<ProducerReferenceTime id=\"%d\" inband=\"true\" type=\"%s\" wallClockTime=\"%s\" presentationTime=\"%"PRId64"\">\n",
- i, os->producer_reference_time.flags ? "captured" : "encoder", os->producer_reference_time_str, c->presentation_time_offset);
- avio_printf(out, "\t\t\t\t\t<UTCTiming schemeIdUri=\"urn:mpeg:dash:utc:http-xsdate:2014\" value=\"%s\"/>\n", c->utc_timing_url);
+ avio_printf(
+ out,
+ "\t\t\t\t<ProducerReferenceTime id=\"%d\" inband=\"true\" type=\"%s\" wallClockTime=\"%s\" presentationTime=\"%"
+ PRId64"\">\n",
+ i, os->producer_reference_time.flags ? "captured" : "encoder", os->producer_reference_time_str,
+ c->presentation_time_offset);
+ avio_printf(out, "\t\t\t\t\t<UTCTiming schemeIdUri=\"urn:mpeg:dash:utc:http-xsdate:2014\" value=\"%s\"/>\n",
+ c->utc_timing_url);
avio_printf(out, "\t\t\t\t</ProducerReferenceTime>\n");
}
if (!final && c->ldash && os->gop_size && os->frag_type != FRAG_TYPE_NONE && !(c->profile & MPD_PROFILE_DVB) &&
@@ -875,8 +886,7 @@ static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_ind
return 0;
}
-static int add_adaptation_set(AVFormatContext *s, AdaptationSet **as, enum AVMediaType type)
-{
+static int add_adaptation_set(AVFormatContext *s, AdaptationSet **as, enum AVMediaType type) {
DASHContext *c = s->priv_data;
void *mem;
@@ -899,8 +909,7 @@ static int add_adaptation_set(AVFormatContext *s, AdaptationSet **as, enum AVMed
return 0;
}
-static int adaptation_set_add_stream(AVFormatContext *s, int as_idx, int i)
-{
+static int adaptation_set_add_stream(AVFormatContext *s, int as_idx, int i) {
DASHContext *c = s->priv_data;
AdaptationSet *as = &c->as[as_idx - 1];
OutputStream *os = &c->streams[i];
@@ -922,8 +931,7 @@ static int adaptation_set_add_stream(AVFormatContext *s, int as_idx, int i)
return 0;
}
-static int parse_adaptation_sets(AVFormatContext *s)
-{
+static int parse_adaptation_sets(AVFormatContext *s) {
DASHContext *c = s->priv_data;
const char *p = c->adaptation_sets;
enum { new_set, parse_default, parsing_streams, parse_seg_duration, parse_frag_duration } state;
@@ -1049,7 +1057,8 @@ static int parse_adaptation_sets(AVFormatContext *s)
if (*p)
p++;
state = parse_default;
- } else if ((state != new_set) && av_strstart(p, "streams=", &p)) { //descriptor and durations are optional
+ } else if ((state != new_set) && av_strstart(p, "streams=", &p)) {
+ //descriptor and durations are optional
state = parsing_streams;
} else if (state == parsing_streams) {
AdaptationSet *as = &c->as[c->nb_as - 1];
@@ -1073,7 +1082,8 @@ static int parse_adaptation_sets(AVFormatContext *s)
if ((ret = adaptation_set_add_stream(s, c->nb_as, i)) < 0)
return ret;
}
- } else { // select single stream
+ } else {
+ // select single stream
i = strtol(idx_str, &end_str, 10);
if (idx_str == end_str || i < 0 || i >= s->nb_streams) {
av_log(s, AV_LOG_ERROR, "Selected stream \"%s\" not found!\n", idx_str);
@@ -1118,7 +1128,9 @@ end:
break;
}
if (n >= c->nb_as) {
- av_log(s, AV_LOG_ERROR, "reference AdaptationSet id \"%d\" not found for trick mode AdaptationSet id \"%d\"\n", as->trick_idx, as->id);
+ av_log(s, AV_LOG_ERROR,
+ "reference AdaptationSet id \"%d\" not found for trick mode AdaptationSet id \"%d\"\n",
+ as->trick_idx, as->id);
return AVERROR(EINVAL);
}
}
@@ -1126,8 +1138,7 @@ end:
return 0;
}
-static int write_manifest(AVFormatContext *s, int final)
-{
+static int write_manifest(AVFormatContext *s, int final) {
DASHContext *c = s->priv_data;
AVIOContext *out;
char temp_filename[1024];
@@ -1139,7 +1150,8 @@ static int write_manifest(AVFormatContext *s, int final)
AVDictionary *opts = NULL;
if (!use_rename && !warned_non_file++)
- av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this may lead to races and temporary partial files\n");
+ av_log(s, AV_LOG_ERROR,
+ "Cannot use rename on non file protocol, this may lead to races and temporary partial files\n");
snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", s->url);
set_http_options(&opts, c);
@@ -1156,9 +1168,9 @@ static int write_manifest(AVFormatContext *s, int final)
"\txsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd\"\n"
"\tprofiles=\"");
if (c->profile & MPD_PROFILE_DASH)
- avio_printf(out, "%s%s", "urn:mpeg:dash:profile:isoff-live:2011", c->profile & MPD_PROFILE_DVB ? "," : "\"\n");
+ avio_printf(out, "%s%s", "urn:mpeg:dash:profile:isoff-live:2011", c->profile & MPD_PROFILE_DVB ? "," : "\"\n");
if (c->profile & MPD_PROFILE_DVB)
- avio_printf(out, "%s", "urn:dvb:dash:profile:dvb-dash:2014\"\n");
+ avio_printf(out, "%s", "urn:dvb:dash:profile:dvb-dash:2014\"\n");
avio_printf(out, "\ttype=\"%s\"\n",
final ? "static" : "dynamic");
if (final) {
@@ -1207,8 +1219,8 @@ static int write_manifest(AVFormatContext *s, int final)
avio_printf(out, " referenceId=\"%d\"", c->target_latency_refid);
avio_printf(out, "/>\n");
}
- if (av_cmp_q(c->min_playback_rate, (AVRational) {1, 1}) ||
- av_cmp_q(c->max_playback_rate, (AVRational) {1, 1}))
+ if (av_cmp_q(c->min_playback_rate, (AVRational){1, 1}) ||
+ av_cmp_q(c->max_playback_rate, (AVRational){1, 1}))
avio_printf(out, "\t\t<PlaybackRate min=\"%.2f\" max=\"%.2f\"/>\n",
av_q2d(c->min_playback_rate), av_q2d(c->max_playback_rate));
avio_printf(out, "\t</ServiceDescription>\n");
@@ -1231,7 +1243,8 @@ static int write_manifest(AVFormatContext *s, int final)
avio_printf(out, "\t</Period>\n");
if (c->utc_timing_url)
- avio_printf(out, "\t<UTCTiming schemeIdUri=\"urn:mpeg:dash:utc:http-xsdate:2014\" value=\"%s\"/>\n", c->utc_timing_url);
+ avio_printf(out, "\t<UTCTiming schemeIdUri=\"urn:mpeg:dash:utc:http-xsdate:2014\" value=\"%s\"/>\n",
+ c->utc_timing_url);
avio_printf(out, "</MPD>\n");
avio_flush(out);
@@ -1247,7 +1260,7 @@ static int write_manifest(AVFormatContext *s, int final)
// Publish master playlist only the configured rate
if (c->master_playlist_created && (!c->master_publish_rate ||
- c->streams[0].segment_index % c->master_publish_rate))
+ c->streams[0].segment_index % c->master_publish_rate))
return 0;
if (*c->dirname)
@@ -1324,7 +1337,6 @@ static int write_manifest(AVFormatContext *s, int final)
playlist_file, agroup,
codec_str, NULL, NULL);
}
-
} else {
// treat audio streams as separate renditions
@@ -1362,16 +1374,14 @@ static int write_manifest(AVFormatContext *s, int final)
return 0;
}
-static int dict_copy_entry(AVDictionary **dst, const AVDictionary *src, const char *key)
-{
+static int dict_copy_entry(AVDictionary **dst, const AVDictionary *src, const char *key) {
AVDictionaryEntry *entry = av_dict_get(src, key, NULL, 0);
if (entry)
av_dict_set(dst, key, entry->value, AV_DICT_DONT_OVERWRITE);
return 0;
}
-static int dash_init(AVFormatContext *s)
-{
+static int dash_init(AVFormatContext *s) {
DASHContext *c = s->priv_data;
int ret = 0, i;
char *ptr;
@@ -1434,27 +1444,31 @@ static int dash_init(AVFormatContext *s)
}
if (c->write_prft && !c->utc_timing_url) {
- av_log(s, AV_LOG_WARNING, "Producer Reference Time element option will be ignored as utc_timing_url is not set\n");
+ av_log(s, AV_LOG_WARNING,
+ "Producer Reference Time element option will be ignored as utc_timing_url is not set\n");
c->write_prft = 0;
}
if (c->write_prft && !c->streaming) {
- av_log(s, AV_LOG_WARNING, "Producer Reference Time element option will be ignored as streaming is not enabled\n");
+ av_log(s, AV_LOG_WARNING,
+ "Producer Reference Time element option will be ignored as streaming is not enabled\n");
c->write_prft = 0;
}
if (c->ldash && !c->write_prft) {
- av_log(s, AV_LOG_WARNING, "Low Latency mode enabled without Producer Reference Time element option! Resulting manifest may not be complaint\n");
+ av_log(s, AV_LOG_WARNING,
+ "Low Latency mode enabled without Producer Reference Time element option! Resulting manifest may not be complaint\n");
}
if (c->target_latency && !c->write_prft) {
- av_log(s, AV_LOG_WARNING, "Target latency option will be ignored as Producer Reference Time element will not be written\n");
+ av_log(s, AV_LOG_WARNING,
+ "Target latency option will be ignored as Producer Reference Time element will not be written\n");
c->target_latency = 0;
}
if (av_cmp_q(c->max_playback_rate, c->min_playback_rate) < 0) {
av_log(s, AV_LOG_WARNING, "Minimum playback rate value is higher than the Maximum. Both will be ignored\n");
- c->min_playback_rate = c->max_playback_rate = (AVRational) {1, 1};
+ c->min_playback_rate = c->max_playback_rate = (AVRational){1, 1};
}
av_strlcpy(c->dirname, s->url, sizeof(c->dirname));
@@ -1491,8 +1505,7 @@ static int dash_init(AVFormatContext *s)
os->bit_rate = s->streams[i]->codecpar->bit_rate;
if (!os->bit_rate) {
- int level = s->strict_std_compliance >= FF_COMPLIANCE_STRICT ?
- AV_LOG_ERROR : AV_LOG_WARNING;
+ int level = s->strict_std_compliance >= FF_COMPLIANCE_STRICT ? AV_LOG_ERROR : AV_LOG_WARNING;
av_log(s, level, "No bit rate set for stream %d\n", i);
if (s->strict_std_compliance >= FF_COMPLIANCE_STRICT)
return AVERROR(EINVAL);
@@ -1519,9 +1532,9 @@ static int dash_init(AVFormatContext *s)
}
if (os->segment_type == SEGMENT_TYPE_WEBM) {
- if ((!c->single_file && !av_match_ext(os->init_seg_name, os->format_name)) ||
+ if ((!c->single_file && !av_match_ext(os->init_seg_name, os->format_name)) ||
(!c->single_file && !av_match_ext(os->media_seg_name, os->format_name)) ||
- ( c->single_file && !av_match_ext(os->single_file_name, os->format_name))) {
+ (c->single_file && !av_match_ext(os->single_file_name, os->format_name))) {
av_log(s, AV_LOG_WARNING,
"One or many segment file names doesn't end with .webm. "
"Override -init_seg_name and/or -media_seg_name and/or "
@@ -1529,7 +1542,8 @@ static int dash_init(AVFormatContext *s)
}
if (c->streaming) {
// Streaming not supported as matroskaenc buffers internally before writing the output
- av_log(s, AV_LOG_WARNING, "One or more streams in WebM output format. Streaming option will be ignored\n");
+ av_log(s, AV_LOG_WARNING,
+ "One or more streams in WebM output format. Streaming option will be ignored\n");
c->streaming = 0;
}
}
@@ -1541,10 +1555,10 @@ static int dash_init(AVFormatContext *s)
ctx->oformat = av_guess_format(os->format_name, NULL, NULL);
if (!ctx->oformat)
return AVERROR_MUXER_NOT_FOUND;
- ctx->interrupt_callback = s->interrupt_callback;
- ctx->opaque = s->opaque;
- ctx->io_close2 = s->io_close2;
- ctx->io_open = s->io_open;
+ ctx->interrupt_callback = s->interrupt_callback;
+ ctx->opaque = s->opaque;
+ ctx->io_close2 = s->io_close2;
+ ctx->io_open = s->io_open;
ctx->strict_std_compliance = s->strict_std_compliance;
if (!(st = avformat_new_stream(ctx, NULL)))
@@ -1570,7 +1584,8 @@ static int dash_init(AVFormatContext *s)
if (c->single_file) {
if (os->single_file_name)
- ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), os->single_file_name, i, 0, os->bit_rate, 0);
+ ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), os->single_file_name, i, 0, os->bit_rate,
+ 0);
else
snprintf(os->initfile, sizeof(os->initfile), "%s-stream%d.%s", basename, i, os->format_name);
} else {
@@ -1605,7 +1620,8 @@ static int dash_init(AVFormatContext *s)
c->max_segment_duration = FFMAX(c->max_segment_duration, as->seg_duration);
if (c->profile & MPD_PROFILE_DVB && (os->seg_duration > 15000000 || os->seg_duration < 960000)) {
- av_log(s, AV_LOG_ERROR, "Segment duration %"PRId64" is outside the allowed range for DVB-DASH profile\n", os->seg_duration);
+ av_log(s, AV_LOG_ERROR, "Segment duration %"PRId64" is outside the allowed range for DVB-DASH profile\n",
+ os->seg_duration);
return AVERROR(EINVAL);
}
@@ -1614,12 +1630,14 @@ static int dash_init(AVFormatContext *s)
os->frag_type = c->streaming ? FRAG_TYPE_EVERY_FRAME : FRAG_TYPE_NONE;
}
if (os->frag_type == FRAG_TYPE_DURATION && os->frag_duration > os->seg_duration) {
- av_log(s, AV_LOG_ERROR, "Fragment duration %"PRId64" is longer than Segment duration %"PRId64"\n", os->frag_duration, os->seg_duration);
+ av_log(s, AV_LOG_ERROR, "Fragment duration %"PRId64" is longer than Segment duration %"PRId64"\n",
+ os->frag_duration, os->seg_duration);
return AVERROR(EINVAL);
}
if (os->frag_type == FRAG_TYPE_PFRAMES && (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO || !os->parser)) {
if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && !os->parser)
- av_log(s, AV_LOG_WARNING, "frag_type set to P-Frame reordering, but no parser found for stream %d\n", i);
+ av_log(s, AV_LOG_WARNING, "frag_type set to P-Frame reordering, but no parser found for stream %d\n",
+ i);
os->frag_type = c->streaming ? FRAG_TYPE_EVERY_FRAME : FRAG_TYPE_NONE;
}
if (os->frag_type != FRAG_TYPE_PFRAMES && as->trick_idx < 0)
@@ -1628,8 +1646,8 @@ static int dash_init(AVFormatContext *s)
if (os->segment_type == SEGMENT_TYPE_MP4) {
if (c->streaming)
- // skip_sidx : Reduce bitrate overhead
- // skip_trailer : Avoids growing memory usage with time
+ // skip_sidx : Reduce bitrate overhead
+ // skip_trailer : Avoids growing memory usage with time
av_dict_set(&opts, "movflags", "+dash+delay_moov+skip_sidx+skip_trailer", AV_DICT_APPEND);
else {
if (c->global_sidx)
@@ -1686,14 +1704,16 @@ static int dash_init(AVFormatContext *s)
if (st->sample_aspect_ratio.num)
os->sar = st->sample_aspect_ratio;
else
- os->sar = (AVRational){1,1};
+ os->sar = (AVRational){1, 1};
av_reduce(&par.num, &par.den,
- st->codecpar->width * (int64_t)os->sar.num,
- st->codecpar->height * (int64_t)os->sar.den,
+ st->codecpar->width * (int64_t) os->sar.num,
+ st->codecpar->height * (int64_t) os->sar.den,
1024 * 1024);
if (as->par.num && av_cmp_q(par, as->par)) {
- av_log(s, AV_LOG_ERROR, "Conflicting stream aspect ratios values in Adaptation Set %d. Please ensure all adaptation sets have the same aspect ratio\n", os->as_idx);
+ av_log(s, AV_LOG_ERROR,
+ "Conflicting stream aspect ratios values in Adaptation Set %d. Please ensure all adaptation sets have the same aspect ratio\n",
+ os->as_idx);
return AVERROR(EINVAL);
}
as->par = par;
@@ -1712,6 +1732,7 @@ static int dash_init(AVFormatContext *s)
c->nr_of_streams_to_flush++;
}
+
if (!c->has_video && c->seg_duration <= 0) {
av_log(s, AV_LOG_WARNING, "no video stream and no seg duration set\n");
return AVERROR(EINVAL);
@@ -1725,15 +1746,15 @@ static int dash_init(AVFormatContext *s)
return 0;
}
-static int dash_write_header(AVFormatContext *s)
-{
+static int dash_write_header(AVFormatContext *s) {
DASHContext *c = s->priv_data;
int i, ret;
for (i = 0; i < s->nb_streams; i++) {
OutputStream *os = &c->streams[i];
+ av_dict_copy(&os->ctx->metadata, s->metadata, 0);
+ av_dict_copy(&os->ctx->metadata, s->streams[i]->metadata, 0);
if ((ret = avformat_write_header(os->ctx, NULL)) < 0)
return ret;
-
// Flush init segment
// Only for WebM segment, since for mp4 delay_moov is set and
// the init segment is thus flushed after the first packets.
@@ -1747,14 +1768,13 @@ static int dash_write_header(AVFormatContext *s)
static int add_segment(OutputStream *os, const char *file,
int64_t time, int64_t duration,
int64_t start_pos, int64_t range_length,
- int64_t index_length, int next_exp_index)
-{
+ int64_t index_length, int next_exp_index) {
int err;
Segment *seg;
if (os->nb_segments >= os->segments_size) {
os->segments_size = (os->segments_size + 1) * 2;
if ((err = av_reallocp_array(&os->segments, sizeof(*os->segments),
- os->segments_size)) < 0) {
+ os->segments_size)) < 0) {
os->segments_size = 0;
os->nb_segments = 0;
return err;
@@ -1766,7 +1786,8 @@ static int add_segment(OutputStream *os, const char *file,
av_strlcpy(seg->file, file, sizeof(seg->file));
seg->time = time;
seg->duration = duration;
- if (seg->time < 0) { // If pts<0, it is expected to be cut away with an edit list
+ if (seg->time < 0) {
+ // If pts<0, it is expected to be cut away with an edit list
seg->duration += seg->time;
seg->time = 0;
}
@@ -1784,8 +1805,7 @@ static int add_segment(OutputStream *os, const char *file,
return 0;
}
-static void write_styp(AVIOContext *pb)
-{
+static void write_styp(AVIOContext *pb) {
avio_wb32(pb, 24);
ffio_wfourcc(pb, "styp");
ffio_wfourcc(pb, "msdh");
@@ -1795,8 +1815,7 @@ static void write_styp(AVIOContext *pb)
}
static void find_index_range(AVFormatContext *s, const char *full_path,
- int64_t pos, int *index_length)
-{
+ int64_t pos, int *index_length) {
uint8_t buf[8];
AVIOContext *pb;
int ret;
@@ -1818,8 +1837,7 @@ static void find_index_range(AVFormatContext *s, const char *full_path,
}
static int update_stream_extradata(AVFormatContext *s, OutputStream *os,
- AVPacket *pkt, AVRational *frame_rate)
-{
+ AVPacket *pkt, AVRational *frame_rate) {
AVCodecParameters *par = os->ctx->streams[0]->codecpar;
uint8_t *extradata;
size_t extradata_size;
@@ -1864,13 +1882,12 @@ static void dashenc_delete_file(AVFormatContext *s, char *filename) {
int res = ffurl_delete(filename);
if (res < 0) {
av_log(s, (res == AVERROR(ENOENT) ? AV_LOG_WARNING : AV_LOG_ERROR),
- "failed to delete %s: %s\n", filename, av_err2str(res));
+ "failed to delete %s: %s\n", filename, av_err2str(res));
}
}
}
-static int dashenc_delete_segment_file(AVFormatContext *s, const char* file)
-{
+static int dashenc_delete_segment_file(AVFormatContext *s, const char *file) {
DASHContext *c = s->priv_data;
AVBPrint buf;
@@ -1889,8 +1906,7 @@ static int dashenc_delete_segment_file(AVFormatContext *s, const char* file)
return 0;
}
-static inline void dashenc_delete_media_segments(AVFormatContext *s, OutputStream *os, int remove_count)
-{
+static inline void dashenc_delete_media_segments(AVFormatContext *s, OutputStream *os, int remove_count) {
for (int i = 0; i < remove_count; ++i) {
dashenc_delete_segment_file(s, os->segments[i]->file);
@@ -1902,8 +1918,7 @@ static inline void dashenc_delete_media_segments(AVFormatContext *s, OutputStrea
memmove(os->segments, os->segments + remove_count, os->nb_segments * sizeof(*os->segments));
}
-static int dash_flush(AVFormatContext *s, int final, int stream)
-{
+static int dash_flush(AVFormatContext *s, int final, int stream) {
DASHContext *c = s->priv_data;
int i, ret = 0;
@@ -1982,8 +1997,10 @@ static int dash_flush(AVFormatContext *s, int final, int stream)
if (!os->bit_rate && !os->first_segment_bit_rate) {
os->first_segment_bit_rate = (int64_t) range_length * 8 * AV_TIME_BASE / duration;
}
- add_segment(os, os->filename, os->start_pts, os->max_pts - os->start_pts, os->pos, range_length, index_length, next_exp_index);
- av_log(s, AV_LOG_VERBOSE, "Representation %d media segment %d written to: %s\n", i, os->segment_index, os->full_path);
+ add_segment(os, os->filename, os->start_pts, os->max_pts - os->start_pts, os->pos, range_length, index_length,
+ next_exp_index);
+ av_log(s, AV_LOG_VERBOSE, "Representation %d media segment %d written to: %s\n", i, os->segment_index,
+ os->full_path);
os->pos += range_length;
}
@@ -2016,7 +2033,6 @@ static int dash_flush(AVFormatContext *s, int final, int stream)
seg->start_pos += sidx_size;
}
}
-
}
}
}
@@ -2036,18 +2052,17 @@ static int dash_flush(AVFormatContext *s, int final, int stream)
return ret;
}
-static int dash_parse_prft(DASHContext *c, AVPacket *pkt)
-{
+static int dash_parse_prft(DASHContext *c, AVPacket *pkt) {
OutputStream *os = &c->streams[pkt->stream_index];
AVProducerReferenceTime *prft;
size_t side_data_size;
- prft = (AVProducerReferenceTime *)av_packet_get_side_data(pkt, AV_PKT_DATA_PRFT, &side_data_size);
+ prft = (AVProducerReferenceTime *) av_packet_get_side_data(pkt, AV_PKT_DATA_PRFT, &side_data_size);
if (!prft || side_data_size != sizeof(AVProducerReferenceTime) || (prft->flags && prft->flags != 24)) {
// No encoder generated or user provided capture time AVProducerReferenceTime side data. Instead
// of letting the mov muxer generate one, do it here so we can also use it for the manifest.
- prft = (AVProducerReferenceTime *)av_packet_new_side_data(pkt, AV_PKT_DATA_PRFT,
- sizeof(AVProducerReferenceTime));
+ prft = (AVProducerReferenceTime *) av_packet_new_side_data(pkt, AV_PKT_DATA_PRFT,
+ sizeof(AVProducerReferenceTime));
if (!prft)
return AVERROR(ENOMEM);
prft->wallclock = av_gettime();
@@ -2062,8 +2077,7 @@ static int dash_parse_prft(DASHContext *c, AVPacket *pkt)
return 0;
}
-static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
-{
+static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) {
DASHContext *c = s->priv_data;
AVStream *st = s->streams[pkt->stream_index];
OutputStream *os = &c->streams[pkt->stream_index];
@@ -2090,7 +2104,7 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
if (os->first_pts == AV_NOPTS_VALUE &&
s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO) {
pkt->pts -= pkt->dts;
- pkt->dts = 0;
+ pkt->dts = 0;
}
if (c->write_prft) {
@@ -2121,16 +2135,16 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
int64_t frame_duration = 0;
switch (os->frag_type) {
- case FRAG_TYPE_DURATION:
- frame_duration = os->frag_duration;
- break;
- case FRAG_TYPE_EVERY_FRAME:
- frame_duration = av_rescale_q(pkt->duration, st->time_base, AV_TIME_BASE_Q);
- break;
+ case FRAG_TYPE_DURATION:
+ frame_duration = os->frag_duration;
+ break;
+ case FRAG_TYPE_EVERY_FRAME:
+ frame_duration = av_rescale_q(pkt->duration, st->time_base, AV_TIME_BASE_Q);
+ break;
}
- os->availability_time_offset = ((double) os->seg_duration -
- frame_duration) / AV_TIME_BASE;
+ os->availability_time_offset = ((double) os->seg_duration -
+ frame_duration) / AV_TIME_BASE;
as->max_frag_duration = FFMAX(frame_duration, as->max_frag_duration);
}
@@ -2160,18 +2174,18 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
seg_end_duration, AV_TIME_BASE_Q) >= 0) {
if (!c->has_video || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
c->last_duration = av_rescale_q(pkt->pts - os->start_pts,
- st->time_base,
- AV_TIME_BASE_Q);
+ st->time_base,
+ AV_TIME_BASE_Q);
c->total_duration = av_rescale_q(pkt->pts - os->first_pts,
- st->time_base,
- AV_TIME_BASE_Q);
+ st->time_base,
+ AV_TIME_BASE_Q);
if ((!c->use_timeline || !c->use_template) && os->last_duration) {
- if (c->last_duration < os->last_duration*9/10 ||
- c->last_duration > os->last_duration*11/10) {
+ if (c->last_duration < os->last_duration * 9 / 10 ||
+ c->last_duration > os->last_duration * 11 / 10) {
av_log(s, AV_LOG_WARNING,
- "Segment durations differ too much, enable use_timeline "
- "and use_template, or keep a stricter keyframe interval\n");
+ "Segment durations differ too much, enable use_timeline "
+ "and use_template, or keep a stricter keyframe interval\n");
}
}
}
@@ -2215,13 +2229,14 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
int64_t frag_duration = av_rescale_q(os->total_pkt_duration, st->time_base,
AV_TIME_BASE_Q);
os->availability_time_offset = ((double) os->seg_duration -
- frag_duration) / AV_TIME_BASE;
- as->max_frag_duration = FFMAX(frag_duration, as->max_frag_duration);
+ frag_duration) / AV_TIME_BASE;
+ as->max_frag_duration = FFMAX(frag_duration, as->max_frag_duration);
}
}
}
- if (pkt->flags & AV_PKT_FLAG_KEY && (os->packets_written || os->nb_segments) && !os->gop_size && as->trick_idx < 0) {
+ if (pkt->flags & AV_PKT_FLAG_KEY && (os->packets_written || os->nb_segments) && !os->gop_size && as->trick_idx <
+ 0) {
os->gop_size = os->last_duration + av_rescale_q(os->total_pkt_duration, st->time_base, AV_TIME_BASE_Q);
c->max_gop_size = FFMAX(c->max_gop_size, os->gop_size);
}
@@ -2277,7 +2292,7 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
int len = 0;
uint8_t *buf = NULL;
avio_flush(os->ctx->pb);
- len = avio_get_dyn_buf (os->ctx->pb, &buf);
+ len = avio_get_dyn_buf(os->ctx->pb, &buf);
if (os->out) {
avio_write(os->out, buf + os->written_len, len - os->written_len);
avio_flush(os->out);
@@ -2288,8 +2303,7 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
return ret;
}
-static int dash_write_trailer(AVFormatContext *s)
-{
+static int dash_write_trailer(AVFormatContext *s) {
DASHContext *c = s->priv_data;
int i;
@@ -2331,8 +2345,7 @@ static int dash_write_trailer(AVFormatContext *s)
}
static int dash_check_bitstream(AVFormatContext *s, AVStream *st,
- const AVPacket *avpkt)
-{
+ const AVPacket *avpkt) {
DASHContext *c = s->priv_data;
OutputStream *os = &c->streams[st->index];
AVFormatContext *oc = os->ctx;
@@ -2341,9 +2354,9 @@ static int dash_check_bitstream(AVFormatContext *s, AVStream *st,
int ret;
ret = ffofmt(oc->oformat)->check_bitstream(oc, ost, avpkt);
if (ret == 1) {
- FFStream *const sti = ffstream(st);
+ FFStream *const sti = ffstream(st);
FFStream *const osti = ffstream(ost);
- sti->bsfc = osti->bsfc;
+ sti->bsfc = osti->bsfc;
osti->bsfc = NULL;
}
return ret;
@@ -2354,74 +2367,204 @@ static int dash_check_bitstream(AVFormatContext *s, AVStream *st,
#define OFFSET(x) offsetof(DASHContext, x)
#define E AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
- { "adaptation_sets", "Adaptation sets. Syntax: id=0,streams=0,1,2 id=1,streams=3,4 and so on", OFFSET(adaptation_sets), AV_OPT_TYPE_STRING, { 0 }, 0, 0, AV_OPT_FLAG_ENCODING_PARAM },
- { "dash_segment_type", "set dash segment files type", OFFSET(segment_type_option), AV_OPT_TYPE_INT, {.i64 = SEGMENT_TYPE_AUTO }, 0, SEGMENT_TYPE_NB - 1, E, .unit = "segment_type"},
- { "auto", "select segment file format based on codec", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_AUTO }, 0, UINT_MAX, E, .unit = "segment_type"},
- { "mp4", "make segment file in ISOBMFF format", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_MP4 }, 0, UINT_MAX, E, .unit = "segment_type"},
- { "webm", "make segment file in WebM format", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_WEBM }, 0, UINT_MAX, E, .unit = "segment_type"},
- { "extra_window_size", "number of segments kept outside of the manifest before removing from disk", OFFSET(extra_window_size), AV_OPT_TYPE_INT, { .i64 = 5 }, 0, INT_MAX, E },
- { "format_options","set list of options for the container format (mp4/webm) used for dash", OFFSET(format_options), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, E},
- { "frag_duration", "fragment duration (in seconds, fractional value can be set)", OFFSET(frag_duration), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT_MAX, E },
- { "frag_type", "set type of interval for fragments", OFFSET(frag_type), AV_OPT_TYPE_INT, {.i64 = FRAG_TYPE_NONE }, 0, FRAG_TYPE_NB - 1, E, .unit = "frag_type"},
- { "none", "one fragment per segment", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_NONE }, 0, UINT_MAX, E, .unit = "frag_type"},
- { "every_frame", "fragment at every frame", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_EVERY_FRAME }, 0, UINT_MAX, E, .unit = "frag_type"},
- { "duration", "fragment at specific time intervals", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_DURATION }, 0, UINT_MAX, E, .unit = "frag_type"},
- { "pframes", "fragment at keyframes and following P-Frame reordering (Video only, experimental)", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_PFRAMES }, 0, UINT_MAX, E, .unit = "frag_type"},
- { "global_sidx", "Write global SIDX atom. Applicable only for single file, mp4 output, non-streaming mode", OFFSET(global_sidx), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
- { "hls_master_name", "HLS master playlist name", OFFSET(hls_master_name), AV_OPT_TYPE_STRING, {.str = "master.m3u8"}, 0, 0, E },
- { "hls_playlist", "Generate HLS playlist files(master.m3u8, media_%d.m3u8)", OFFSET(hls_playlist), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
- { "http_opts", "HTTP protocol options", OFFSET(http_opts), AV_OPT_TYPE_DICT, { .str = NULL }, 0, 0, E },
- { "http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
- { "http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
- { "ignore_io_errors", "Ignore IO errors during open and write. Useful for long-duration runs with network output", OFFSET(ignore_io_errors), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
- { "index_correction", "Enable/Disable segment index correction logic", OFFSET(index_correction), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
- { "init_seg_name", "DASH-templated name to used for the initialization segment", OFFSET(init_seg_name), AV_OPT_TYPE_STRING, {.str = "init-stream$RepresentationID$.$ext$"}, 0, 0, E },
- { "ldash", "Enable Low-latency dash. Constrains the value of a few elements", OFFSET(ldash), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
- { "lhls", "Enable Low-latency HLS(Experimental). Adds #EXT-X-PREFETCH tag with current segment's URI", OFFSET(lhls), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
- { "master_m3u8_publish_rate", "Publish master playlist every after this many segment intervals", OFFSET(master_publish_rate), AV_OPT_TYPE_INT, {.i64 = 0}, 0, UINT_MAX, E},
- { "max_playback_rate", "Set desired maximum playback rate", OFFSET(max_playback_rate), AV_OPT_TYPE_RATIONAL, { .dbl = 1.0 }, 0.5, 1.5, E },
- { "media_seg_name", "DASH-templated name to used for the media segments", OFFSET(media_seg_name), AV_OPT_TYPE_STRING, {.str = "chunk-stream$RepresentationID$-$Number%05d$.$ext$"}, 0, 0, E },
- { "method", "set the HTTP method", OFFSET(method), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
- { "min_playback_rate", "Set desired minimum playback rate", OFFSET(min_playback_rate), AV_OPT_TYPE_RATIONAL, { .dbl = 1.0 }, 0.5, 1.5, E },
- { "mpd_profile", "Set profiles. Elements and values used in the manifest may be constrained by them", OFFSET(profile), AV_OPT_TYPE_FLAGS, {.i64 = MPD_PROFILE_DASH }, 0, UINT_MAX, E, .unit = "mpd_profile"},
- { "dash", "MPEG-DASH ISO Base media file format live profile", 0, AV_OPT_TYPE_CONST, {.i64 = MPD_PROFILE_DASH }, 0, UINT_MAX, E, .unit = "mpd_profile"},
- { "dvb_dash", "DVB-DASH profile", 0, AV_OPT_TYPE_CONST, {.i64 = MPD_PROFILE_DVB }, 0, UINT_MAX, E, .unit = "mpd_profile"},
- { "remove_at_exit", "remove all segments when finished", OFFSET(remove_at_exit), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
- { "seg_duration", "segment duration (in seconds, fractional value can be set)", OFFSET(seg_duration), AV_OPT_TYPE_DURATION, { .i64 = 5000000 }, 0, INT_MAX, E },
- { "single_file", "Store all segments in one file, accessed using byte ranges", OFFSET(single_file), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
- { "single_file_name", "DASH-templated name to be used for baseURL. Implies storing all segments in one file, accessed using byte ranges", OFFSET(single_file_name), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E },
- { "streaming", "Enable/Disable streaming mode of output. Each frame will be moof fragment", OFFSET(streaming), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
- { "target_latency", "Set desired target latency for Low-latency dash", OFFSET(target_latency), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT_MAX, E },
- { "timeout", "set timeout for socket I/O operations", OFFSET(timeout), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT_MAX, .flags = E },
- { "update_period", "Set the mpd update interval", OFFSET(update_period), AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, E},
- { "use_template", "Use SegmentTemplate instead of SegmentList", OFFSET(use_template), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },
- { "use_timeline", "Use SegmentTimeline in SegmentTemplate", OFFSET(use_timeline), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },
- { "utc_timing_url", "URL of the page that will return the UTC timestamp in ISO format", OFFSET(utc_timing_url), AV_OPT_TYPE_STRING, { 0 }, 0, 0, E },
- { "window_size", "number of segments kept in the manifest", OFFSET(window_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, E },
- { "write_prft", "Write producer reference time element", OFFSET(write_prft), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, E},
- { NULL },
+ {
+ "adaptation_sets", "Adaptation sets. Syntax: id=0,streams=0,1,2 id=1,streams=3,4 and so on",
+ OFFSET(adaptation_sets), AV_OPT_TYPE_STRING, {0}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM
+ },
+ {
+ "dash_segment_type", "set dash segment files type", OFFSET(segment_type_option), AV_OPT_TYPE_INT,
+ {.i64 = SEGMENT_TYPE_AUTO}, 0, SEGMENT_TYPE_NB - 1, E, .unit = "segment_type"
+ },
+ {
+ "auto", "select segment file format based on codec", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_AUTO}, 0,
+ UINT_MAX, E, .unit = "segment_type"
+ },
+ {
+ "mp4", "make segment file in ISOBMFF format", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_MP4}, 0, UINT_MAX, E,
+ .unit = "segment_type"
+ },
+ {
+ "webm", "make segment file in WebM format", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_WEBM}, 0, UINT_MAX, E,
+ .unit = "segment_type"
+ },
+ {
+ "extra_window_size", "number of segments kept outside of the manifest before removing from disk",
+ OFFSET(extra_window_size), AV_OPT_TYPE_INT, {.i64 = 5}, 0, INT_MAX, E
+ },
+ {
+ "format_options", "set list of options for the container format (mp4/webm) used for dash",
+ OFFSET(format_options), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, E
+ },
+ {
+ "frag_duration", "fragment duration (in seconds, fractional value can be set)", OFFSET(frag_duration),
+ AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT_MAX, E
+ },
+ {
+ "frag_type", "set type of interval for fragments", OFFSET(frag_type), AV_OPT_TYPE_INT, {.i64 = FRAG_TYPE_NONE},
+ 0, FRAG_TYPE_NB - 1, E, .unit = "frag_type"
+ },
+ {
+ "none", "one fragment per segment", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_NONE}, 0, UINT_MAX, E,
+ .unit = "frag_type"
+ },
+ {
+ "every_frame", "fragment at every frame", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_EVERY_FRAME}, 0, UINT_MAX, E,
+ .unit = "frag_type"
+ },
+ {
+ "duration", "fragment at specific time intervals", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_DURATION}, 0,
+ UINT_MAX, E, .unit = "frag_type"
+ },
+ {
+ "pframes", "fragment at keyframes and following P-Frame reordering (Video only, experimental)", 0,
+ AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_PFRAMES}, 0, UINT_MAX, E, .unit = "frag_type"
+ },
+ {
+ "global_sidx", "Write global SIDX atom. Applicable only for single file, mp4 output, non-streaming mode",
+ OFFSET(global_sidx), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E
+ },
+ {
+ "hls_master_name", "HLS master playlist name", OFFSET(hls_master_name), AV_OPT_TYPE_STRING,
+ {.str = "master.m3u8"}, 0, 0, E
+ },
+ {
+ "hls_playlist", "Generate HLS playlist files(master.m3u8, media_%d.m3u8)", OFFSET(hls_playlist),
+ AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E
+ },
+ {"http_opts", "HTTP protocol options", OFFSET(http_opts), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, E},
+ {
+ "http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0,
+ 1, E
+ },
+ {
+ "http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING,
+ {.str = NULL}, 0, 0, E
+ },
+ {
+ "ignore_io_errors", "Ignore IO errors during open and write. Useful for long-duration runs with network output",
+ OFFSET(ignore_io_errors), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E
+ },
+ {
+ "index_correction", "Enable/Disable segment index correction logic", OFFSET(index_correction), AV_OPT_TYPE_BOOL,
+ {.i64 = 0}, 0, 1, E
+ },
+ {
+ "init_seg_name", "DASH-templated name to used for the initialization segment", OFFSET(init_seg_name),
+ AV_OPT_TYPE_STRING, {.str = "init-stream$RepresentationID$.$ext$"}, 0, 0, E
+ },
+ {
+ "ldash", "Enable Low-latency dash. Constrains the value of a few elements", OFFSET(ldash), AV_OPT_TYPE_BOOL,
+ {.i64 = 0}, 0, 1, E
+ },
+ {
+ "lhls", "Enable Low-latency HLS(Experimental). Adds #EXT-X-PREFETCH tag with current segment's URI",
+ OFFSET(lhls), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E
+ },
+ {
+ "master_m3u8_publish_rate", "Publish master playlist every after this many segment intervals",
+ OFFSET(master_publish_rate), AV_OPT_TYPE_INT, {.i64 = 0}, 0, UINT_MAX, E
+ },
+ {
+ "max_playback_rate", "Set desired maximum playback rate", OFFSET(max_playback_rate), AV_OPT_TYPE_RATIONAL,
+ {.dbl = 1.0}, 0.5, 1.5, E
+ },
+ {
+ "media_seg_name", "DASH-templated name to used for the media segments", OFFSET(media_seg_name),
+ AV_OPT_TYPE_STRING, {.str = "chunk-stream$RepresentationID$-$Number%05d$.$ext$"}, 0, 0, E
+ },
+ {"method", "set the HTTP method", OFFSET(method), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
+ {
+ "min_playback_rate", "Set desired minimum playback rate", OFFSET(min_playback_rate), AV_OPT_TYPE_RATIONAL,
+ {.dbl = 1.0}, 0.5, 1.5, E
+ },
+ {
+ "mpd_profile", "Set profiles. Elements and values used in the manifest may be constrained by them",
+ OFFSET(profile), AV_OPT_TYPE_FLAGS, {.i64 = MPD_PROFILE_DASH}, 0, UINT_MAX, E, .unit = "mpd_profile"
+ },
+ {
+ "dash", "MPEG-DASH ISO Base media file format live profile", 0, AV_OPT_TYPE_CONST, {.i64 = MPD_PROFILE_DASH}, 0,
+ UINT_MAX, E, .unit = "mpd_profile"
+ },
+ {
+ "dvb_dash", "DVB-DASH profile", 0, AV_OPT_TYPE_CONST, {.i64 = MPD_PROFILE_DVB}, 0, UINT_MAX, E,
+ .unit = "mpd_profile"
+ },
+ {
+ "remove_at_exit", "remove all segments when finished", OFFSET(remove_at_exit), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0,
+ 1, E
+ },
+ {
+ "seg_duration", "segment duration (in seconds, fractional value can be set)", OFFSET(seg_duration),
+ AV_OPT_TYPE_DURATION, {.i64 = 5000000}, 0, INT_MAX, E
+ },
+ {
+ "single_file", "Store all segments in one file, accessed using byte ranges", OFFSET(single_file),
+ AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E
+ },
+ {
+ "single_file_name",
+ "DASH-templated name to be used for baseURL. Implies storing all segments in one file, accessed using byte ranges",
+ OFFSET(single_file_name), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E
+ },
+ {
+ "streaming", "Enable/Disable streaming mode of output. Each frame will be moof fragment", OFFSET(streaming),
+ AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E
+ },
+ {
+ "target_latency", "Set desired target latency for Low-latency dash", OFFSET(target_latency),
+ AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT_MAX, E
+ },
+ {
+ "timeout", "set timeout for socket I/O operations", OFFSET(timeout), AV_OPT_TYPE_DURATION, {.i64 = -1}, -1,
+ INT_MAX, .flags = E
+ },
+ {
+ "update_period", "Set the mpd update interval", OFFSET(update_period), AV_OPT_TYPE_INT64, {.i64 = 0}, 0,
+ INT64_MAX, E
+ },
+ {
+ "use_template", "Use SegmentTemplate instead of SegmentList", OFFSET(use_template), AV_OPT_TYPE_BOOL,
+ {.i64 = 1}, 0, 1, E
+ },
+ {
+ "use_timeline", "Use SegmentTimeline in SegmentTemplate", OFFSET(use_timeline), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0,
+ 1, E
+ },
+ {
+ "utc_timing_url", "URL of the page that will return the UTC timestamp in ISO format", OFFSET(utc_timing_url),
+ AV_OPT_TYPE_STRING, {0}, 0, 0, E
+ },
+ {
+ "window_size", "number of segments kept in the manifest", OFFSET(window_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0,
+ INT_MAX, E
+ },
+ {
+ "write_prft", "Write producer reference time element", OFFSET(write_prft), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
+ E
+ },
+ {NULL},
};
static const AVClass dash_class = {
.class_name = "dash muxer",
- .item_name = av_default_item_name,
- .option = options,
- .version = LIBAVUTIL_VERSION_INT,
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
};
const FFOutputFormat ff_dash_muxer = {
- .p.name = "dash",
- .p.long_name = NULL_IF_CONFIG_SMALL("DASH Muxer"),
- .p.extensions = "mpd",
- .p.audio_codec = AV_CODEC_ID_AAC,
- .p.video_codec = AV_CODEC_ID_H264,
- .p.flags = AVFMT_GLOBALHEADER | AVFMT_NOFILE | AVFMT_TS_NEGATIVE,
- .p.priv_class = &dash_class,
+ .p.name = "dash",
+ .p.long_name = NULL_IF_CONFIG_SMALL("DASH Muxer"),
+ .p.extensions = "mpd",
+ .p.audio_codec = AV_CODEC_ID_AAC,
+ .p.video_codec = AV_CODEC_ID_H264,
+ .p.flags = AVFMT_GLOBALHEADER | AVFMT_NOFILE | AVFMT_TS_NEGATIVE,
+ .p.priv_class = &dash_class,
.priv_data_size = sizeof(DASHContext),
- .init = dash_init,
- .write_header = dash_write_header,
- .write_packet = dash_write_packet,
- .write_trailer = dash_write_trailer,
- .deinit = dash_free,
+ .init = dash_init,
+ .write_header = dash_write_header,
+ .write_packet = dash_write_packet,
+ .write_trailer = dash_write_trailer,
+ .deinit = dash_free,
.check_bitstream = dash_check_bitstream,
};
--
2.49.1
>From ac11dd508c3e06ec4b59e38098b6f24ef16b0be3 Mon Sep 17 00:00:00 2001
From: Damitha Gunawardena <damitha.guns@gmail.com>
Date: Wed, 24 Sep 2025 20:28:30 +1000
Subject: [PATCH 2/2] preserve metadata in dashenc
---
libavformat/dashenc.c | 619 ++++++++++++++++--------------------------
1 file changed, 239 insertions(+), 380 deletions(-)
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 7ca46e201a..9a5a2bc675 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -123,10 +123,10 @@ typedef struct OutputStream {
int last_flags;
int bit_rate;
int first_segment_bit_rate;
- SegmentType segment_type; /* segment type selected for this particular stream */
+ SegmentType segment_type; /* segment type selected for this particular stream */
const char *format_name;
const char *extension_name;
- const char *single_file_name; /* file names selected for this particular stream */
+ const char *single_file_name; /* file names selected for this particular stream */
const char *init_seg_name;
const char *media_seg_name;
@@ -148,7 +148,7 @@ typedef struct OutputStream {
} OutputStream;
typedef struct DASHContext {
- const AVClass *class; /* Class for private options. */
+ const AVClass *class; /* Class for private options. */
char *adaptation_sets;
AdaptationSet *as;
int nb_as;
@@ -168,7 +168,7 @@ typedef struct DASHContext {
time_t start_time_s;
int64_t presentation_time_offset;
char dirname[1024];
- const char *single_file_name; /* file names as specified in options */
+ const char *single_file_name; /* file names as specified in options */
const char *init_seg_name;
const char *media_seg_name;
const char *utc_timing_url;
@@ -187,7 +187,7 @@ typedef struct DASHContext {
int index_correction;
AVDictionary *format_options;
int global_sidx;
- SegmentType segment_type_option; /* segment type as specified in options */
+ SegmentType segment_type_option; /* segment type as specified in options */
int ignore_io_errors;
int lhls;
int ldash;
@@ -210,12 +210,12 @@ static const struct codec_string {
enum AVCodecID id;
const char str[8];
} codecs[] = {
- {AV_CODEC_ID_VP8, "vp8"},
- {AV_CODEC_ID_VP9, "vp9"},
- {AV_CODEC_ID_VORBIS, "vorbis"},
- {AV_CODEC_ID_OPUS, "opus"},
- {AV_CODEC_ID_FLAC, "flac"},
- {AV_CODEC_ID_NONE}
+ { AV_CODEC_ID_VP8, "vp8" },
+ { AV_CODEC_ID_VP9, "vp9" },
+ { AV_CODEC_ID_VORBIS, "vorbis" },
+ { AV_CODEC_ID_OPUS, "opus" },
+ { AV_CODEC_ID_FLAC, "flac" },
+ { AV_CODEC_ID_NONE }
};
static int dashenc_io_open(AVFormatContext *s, AVIOContext **pb, char *filename,
@@ -256,19 +256,22 @@ static void dashenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filenam
}
}
-static const char *get_format_str(SegmentType segment_type) {
+static const char *get_format_str(SegmentType segment_type)
+{
switch (segment_type) {
- case SEGMENT_TYPE_MP4: return "mp4";
- case SEGMENT_TYPE_WEBM: return "webm";
+ case SEGMENT_TYPE_MP4: return "mp4";
+ case SEGMENT_TYPE_WEBM: return "webm";
}
return NULL;
}
-static const char *get_extension_str(SegmentType type, int single_file) {
+static const char *get_extension_str(SegmentType type, int single_file)
+{
switch (type) {
- case SEGMENT_TYPE_MP4: return single_file ? "mp4" : "m4s";
- case SEGMENT_TYPE_WEBM: return "webm";
- default: return NULL;
+
+ case SEGMENT_TYPE_MP4: return single_file ? "mp4" : "m4s";
+ case SEGMENT_TYPE_WEBM: return "webm";
+ default: return NULL;
}
}
@@ -279,7 +282,8 @@ static int handle_io_open_error(AVFormatContext *s, int err, char *url) {
return c->ignore_io_errors ? 0 : err;
}
-static inline SegmentType select_segment_type(SegmentType segment_type, enum AVCodecID codec_id) {
+static inline SegmentType select_segment_type(SegmentType segment_type, enum AVCodecID codec_id)
+{
if (segment_type == SEGMENT_TYPE_AUTO) {
if (codec_id == AV_CODEC_ID_OPUS || codec_id == AV_CODEC_ID_VORBIS ||
codec_id == AV_CODEC_ID_VP8 || codec_id == AV_CODEC_ID_VP9) {
@@ -292,7 +296,8 @@ static inline SegmentType select_segment_type(SegmentType segment_type, enum AVC
return segment_type;
}
-static int init_segment_types(AVFormatContext *s) {
+static int init_segment_types(AVFormatContext *s)
+{
DASHContext *c = s->priv_data;
int has_mp4_streams = 0;
for (int i = 0; i < s->nb_streams; ++i) {
@@ -315,8 +320,8 @@ static int init_segment_types(AVFormatContext *s) {
}
if (c->hls_playlist && !has_mp4_streams) {
- av_log(s, AV_LOG_WARNING, "No mp4 streams, disabling HLS manifest generation\n");
- c->hls_playlist = 0;
+ av_log(s, AV_LOG_WARNING, "No mp4 streams, disabling HLS manifest generation\n");
+ c->hls_playlist = 0;
}
return 0;
@@ -338,8 +343,9 @@ static void set_vp9_codec_str(AVFormatContext *s, AVCodecParameters *par,
}
static void set_codec_str(AVFormatContext *s, AVCodecParameters *par,
- AVRational *frame_rate, char *str, int size) {
- const AVCodecTag *tags[2] = {NULL, NULL};
+ AVRational *frame_rate, char *str, int size)
+{
+ const AVCodecTag *tags[2] = { NULL, NULL };
uint32_t tag;
int i;
@@ -432,7 +438,8 @@ static void set_codec_str(AVFormatContext *s, AVCodecParameters *par,
}
}
-static int flush_dynbuf(DASHContext *c, OutputStream *os, int *range_length) {
+static int flush_dynbuf(DASHContext *c, OutputStream *os, int *range_length)
+{
uint8_t *buffer;
if (!os->ctx->pb) {
@@ -460,7 +467,8 @@ static int flush_dynbuf(DASHContext *c, OutputStream *os, int *range_length) {
}
}
-static void set_http_options(AVDictionary **options, DASHContext *c) {
+static void set_http_options(AVDictionary **options, DASHContext *c)
+{
if (c->method)
av_dict_set(options, "method", c->method, 0);
av_dict_copy(options, c->http_opts, 0);
@@ -485,7 +493,7 @@ static void get_start_index_number(OutputStream *os, DASHContext *c,
*start_index = 0;
*start_number = 1;
if (c->window_size) {
- *start_index = FFMAX(os->nb_segments - c->window_size, 0);
+ *start_index = FFMAX(os->nb_segments - c->window_size, 0);
*start_number = FFMAX(os->segment_index - c->window_size, 1);
}
}
@@ -548,10 +556,10 @@ static void write_hls_media_playlist(OutputStream *os, AVFormatContext *s,
seg->prog_date_time = prog_date_time;
ret = ff_hls_write_file_entry(c->m3u8_out, 0, c->single_file,
- (double) seg->duration / timescale, 0,
- seg->range_length, seg->start_pos, NULL,
- c->single_file ? os->initfile : seg->file,
- &prog_date_time, 0, 0, 0);
+ (double) seg->duration / timescale, 0,
+ seg->range_length, seg->start_pos, NULL,
+ c->single_file ? os->initfile : seg->file,
+ &prog_date_time, 0, 0, 0);
if (ret < 0) {
av_log(os->ctx, AV_LOG_WARNING, "ff_hls_write_file_entry get error\n");
}
@@ -569,7 +577,8 @@ static void write_hls_media_playlist(OutputStream *os, AVFormatContext *s,
ff_rename(temp_filename_hls, filename_hls, os->ctx);
}
-static int flush_init_segment(AVFormatContext *s, OutputStream *os) {
+static int flush_init_segment(AVFormatContext *s, OutputStream *os)
+{
DASHContext *c = s->priv_data;
int ret, range_length;
@@ -586,7 +595,8 @@ static int flush_init_segment(AVFormatContext *s, OutputStream *os) {
return 0;
}
-static void dash_free(AVFormatContext *s) {
+static void dash_free(AVFormatContext *s)
+{
DASHContext *c = s->priv_data;
int i, j;
@@ -628,7 +638,8 @@ static void dash_free(AVFormatContext *s) {
}
static void output_segment_list(OutputStream *os, AVIOContext *out, AVFormatContext *s,
- int representation_id, int final) {
+ int representation_id, int final)
+{
DASHContext *c = s->priv_data;
int i, start_index, start_number;
get_start_index_number(os, c, &start_index, &start_number);
@@ -645,15 +656,14 @@ static void output_segment_list(OutputStream *os, AVIOContext *out, AVFormatCont
if (c->streaming && os->availability_time_offset && !final)
avio_printf(out, "availabilityTimeComplete=\"false\" ");
- avio_printf(out, "initialization=\"%s\" media=\"%s\" startNumber=\"%d\"", os->init_seg_name, os->media_seg_name,
- c->use_timeline ? start_number : 1);
+ avio_printf(out, "initialization=\"%s\" media=\"%s\" startNumber=\"%d\"", os->init_seg_name, os->media_seg_name, c->use_timeline ? start_number : 1);
if (c->presentation_time_offset)
avio_printf(out, " presentationTimeOffset=\"%"PRId64"\"", c->presentation_time_offset);
avio_printf(out, ">\n");
if (c->use_timeline) {
int64_t cur_time = 0;
avio_printf(out, "\t\t\t\t\t<SegmentTimeline>\n");
- for (i = start_index; i < os->nb_segments;) {
+ for (i = start_index; i < os->nb_segments; ) {
Segment *seg = os->segments[i];
int repeat = 0;
avio_printf(out, "\t\t\t\t\t\t<S ");
@@ -664,8 +674,7 @@ static void output_segment_list(OutputStream *os, AVIOContext *out, AVFormatCont
avio_printf(out, "d=\"%"PRId64"\" ", seg->duration);
while (i + repeat + 1 < os->nb_segments &&
os->segments[i + repeat + 1]->duration == seg->duration &&
- os->segments[i + repeat + 1]->time == os->segments[i + repeat]->time + os->segments[i + repeat]->
- duration)
+ os->segments[i + repeat + 1]->time == os->segments[i + repeat]->time + os->segments[i + repeat]->duration)
repeat++;
if (repeat > 0)
avio_printf(out, "r=\"%d\" ", repeat);
@@ -678,23 +687,18 @@ static void output_segment_list(OutputStream *os, AVIOContext *out, AVFormatCont
avio_printf(out, "\t\t\t\t</SegmentTemplate>\n");
} else if (c->single_file) {
avio_printf(out, "\t\t\t\t<BaseURL>%s</BaseURL>\n", os->initfile);
- avio_printf(out, "\t\t\t\t<SegmentList timescale=\"%d\" duration=\"%"PRId64"\" startNumber=\"%d\">\n",
- AV_TIME_BASE, FFMIN(os->seg_duration, os->last_duration), start_number);
- avio_printf(out, "\t\t\t\t\t<Initialization range=\"%"PRId64"-%"PRId64"\" />\n", os->init_start_pos,
- os->init_start_pos + os->init_range_length - 1);
+ avio_printf(out, "\t\t\t\t<SegmentList timescale=\"%d\" duration=\"%"PRId64"\" startNumber=\"%d\">\n", AV_TIME_BASE, FFMIN(os->seg_duration, os->last_duration), start_number);
+ avio_printf(out, "\t\t\t\t\t<Initialization range=\"%"PRId64"-%"PRId64"\" />\n", os->init_start_pos, os->init_start_pos + os->init_range_length - 1);
for (i = start_index; i < os->nb_segments; i++) {
Segment *seg = os->segments[i];
- avio_printf(out, "\t\t\t\t\t<SegmentURL mediaRange=\"%"PRId64"-%"PRId64"\" ", seg->start_pos,
- seg->start_pos + seg->range_length - 1);
+ avio_printf(out, "\t\t\t\t\t<SegmentURL mediaRange=\"%"PRId64"-%"PRId64"\" ", seg->start_pos, seg->start_pos + seg->range_length - 1);
if (seg->index_length)
- avio_printf(out, "indexRange=\"%"PRId64"-%"PRId64"\" ", seg->start_pos,
- seg->start_pos + seg->index_length - 1);
+ avio_printf(out, "indexRange=\"%"PRId64"-%"PRId64"\" ", seg->start_pos, seg->start_pos + seg->index_length - 1);
avio_printf(out, "/>\n");
}
avio_printf(out, "\t\t\t\t</SegmentList>\n");
} else {
- avio_printf(out, "\t\t\t\t<SegmentList timescale=\"%d\" duration=\"%"PRId64"\" startNumber=\"%d\">\n",
- AV_TIME_BASE, FFMIN(os->seg_duration, os->last_duration), start_number);
+ avio_printf(out, "\t\t\t\t<SegmentList timescale=\"%d\" duration=\"%"PRId64"\" startNumber=\"%d\">\n", AV_TIME_BASE, FFMIN(os->seg_duration, os->last_duration), start_number);
avio_printf(out, "\t\t\t\t\t<Initialization sourceURL=\"%s\" />\n", os->initfile);
for (i = start_index; i < os->nb_segments; i++) {
Segment *seg = os->segments[i];
@@ -705,10 +709,11 @@ static void output_segment_list(OutputStream *os, AVIOContext *out, AVFormatCont
if (!c->lhls || final) {
write_hls_media_playlist(os, s, representation_id, final, NULL);
}
+
}
static char *xmlescape(const char *str) {
- int outlen = strlen(str) * 3 / 2 + 6;
+ int outlen = strlen(str)*3/2 + 6;
char *out = av_realloc(NULL, outlen + 1);
int pos = 0;
if (!out)
@@ -747,7 +752,8 @@ static char *xmlescape(const char *str) {
return out;
}
-static void write_time(AVIOContext *out, int64_t time) {
+static void write_time(AVIOContext *out, int64_t time)
+{
int seconds = time / AV_TIME_BASE;
int fractions = time % AV_TIME_BASE;
int minutes = seconds / 60;
@@ -762,7 +768,8 @@ static void write_time(AVIOContext *out, int64_t time) {
avio_printf(out, "%d.%dS", seconds, fractions / (AV_TIME_BASE / 10));
}
-static void format_date(char *buf, int size, int64_t time_us) {
+static void format_date(char *buf, int size, int64_t time_us)
+{
struct tm *ptm, tmbuf;
int64_t time_ms = time_us / 1000;
const time_t time_s = time_ms / 1000;
@@ -780,21 +787,18 @@ static void format_date(char *buf, int size, int64_t time_us) {
}
static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_index,
- int final) {
+ int final)
+{
DASHContext *c = s->priv_data;
AdaptationSet *as = &c->as[as_index];
AVDictionaryEntry *lang, *role;
int i;
- avio_printf(
- out,
- "\t\t<AdaptationSet id=\"%d\" contentType=\"%s\" startWithSAP=\"1\" segmentAlignment=\"true\" bitstreamSwitching=\"true\"",
- as->id, as->media_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio");
- if (as->media_type == AVMEDIA_TYPE_VIDEO && as->max_frame_rate.num && !as->ambiguous_frame_rate && av_cmp_q(
- as->min_frame_rate, as->max_frame_rate) < 0)
+ avio_printf(out, "\t\t<AdaptationSet id=\"%d\" contentType=\"%s\" startWithSAP=\"1\" segmentAlignment=\"true\" bitstreamSwitching=\"true\"",
+ as->id, as->media_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio");
+ if (as->media_type == AVMEDIA_TYPE_VIDEO && as->max_frame_rate.num && !as->ambiguous_frame_rate && av_cmp_q(as->min_frame_rate, as->max_frame_rate) < 0)
avio_printf(out, " maxFrameRate=\"%d/%d\"", as->max_frame_rate.num, as->max_frame_rate.den);
- else if (as->media_type == AVMEDIA_TYPE_VIDEO && as->max_frame_rate.num && !as->ambiguous_frame_rate && !av_cmp_q(
- as->min_frame_rate, as->max_frame_rate))
+ else if (as->media_type == AVMEDIA_TYPE_VIDEO && as->max_frame_rate.num && !as->ambiguous_frame_rate && !av_cmp_q(as->min_frame_rate, as->max_frame_rate))
avio_printf(out, " frameRate=\"%d/%d\"", as->max_frame_rate.num, as->max_frame_rate.den);
if (as->media_type == AVMEDIA_TYPE_VIDEO) {
avio_printf(out, " maxWidth=\"%d\" maxHeight=\"%d\"", as->max_width, as->max_height);
@@ -808,10 +812,7 @@ static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_ind
if (!final && c->ldash && as->max_frag_duration && !(c->profile & MPD_PROFILE_DVB))
avio_printf(out, "\t\t\t<Resync dT=\"%"PRId64"\" type=\"0\"/>\n", as->max_frag_duration);
if (as->trick_idx >= 0)
- avio_printf(
- out,
- "\t\t\t<EssentialProperty id=\"%d\" schemeIdUri=\"http://dashif.org/guidelines/trickmode\" value=\"%d\"/>\n",
- as->id, as->trick_idx);
+ avio_printf(out, "\t\t\t<EssentialProperty id=\"%d\" schemeIdUri=\"http://dashif.org/guidelines/trickmode\" value=\"%d\"/>\n", as->id, as->trick_idx);
role = av_dict_get(as->metadata, "role", NULL, 0);
if (role)
avio_printf(out, "\t\t\t<Role schemeIdUri=\"urn:mpeg:dash:role:2011\" value=\"%s\"/>\n", role->value);
@@ -834,10 +835,8 @@ static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_ind
snprintf(bandwidth_str, sizeof(bandwidth_str), " bandwidth=\"%d\"", os->first_segment_bit_rate);
if (as->media_type == AVMEDIA_TYPE_VIDEO) {
- avio_printf(
- out, "\t\t\t<Representation id=\"%d\" mimeType=\"video/%s\" codecs=\"%s\"%s width=\"%d\" height=\"%d\"",
- i, os->format_name, os->codec_str, bandwidth_str, s->streams[i]->codecpar->width,
- s->streams[i]->codecpar->height);
+ avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"video/%s\" codecs=\"%s\"%s width=\"%d\" height=\"%d\"",
+ i, os->format_name, os->codec_str, bandwidth_str, s->streams[i]->codecpar->width, s->streams[i]->codecpar->height);
if (st->codecpar->field_order == AV_FIELD_UNKNOWN)
avio_printf(out, " scanType=\"unknown\"");
else if (st->codecpar->field_order != AV_FIELD_PROGRESSIVE)
@@ -848,31 +847,21 @@ static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_ind
if (as->trick_idx >= 0) {
AdaptationSet *tas = &c->as[as->trick_idx];
if (!as->ambiguous_frame_rate && !tas->ambiguous_frame_rate)
- avio_printf(out, " maxPlayoutRate=\"%d\"",
- FFMAX((int)av_q2d(av_div_q(tas->min_frame_rate, as->min_frame_rate)), 1));
+ avio_printf(out, " maxPlayoutRate=\"%d\"", FFMAX((int)av_q2d(av_div_q(tas->min_frame_rate, as->min_frame_rate)), 1));
}
if (!os->coding_dependency)
avio_printf(out, " codingDependency=\"false\"");
avio_printf(out, ">\n");
} else {
- avio_printf(
- out,
- "\t\t\t<Representation id=\"%d\" mimeType=\"audio/%s\" codecs=\"%s\"%s audioSamplingRate=\"%d\">\n",
+ avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"audio/%s\" codecs=\"%s\"%s audioSamplingRate=\"%d\">\n",
i, os->format_name, os->codec_str, bandwidth_str, s->streams[i]->codecpar->sample_rate);
- avio_printf(
- out,
- "\t\t\t\t<AudioChannelConfiguration schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\" value=\"%d\" />\n",
+ avio_printf(out, "\t\t\t\t<AudioChannelConfiguration schemeIdUri=\"urn:mpeg:dash:23003:3:audio_channel_configuration:2011\" value=\"%d\" />\n",
s->streams[i]->codecpar->ch_layout.nb_channels);
}
if (!final && c->write_prft && os->producer_reference_time_str[0]) {
- avio_printf(
- out,
- "\t\t\t\t<ProducerReferenceTime id=\"%d\" inband=\"true\" type=\"%s\" wallClockTime=\"%s\" presentationTime=\"%"
- PRId64"\">\n",
- i, os->producer_reference_time.flags ? "captured" : "encoder", os->producer_reference_time_str,
- c->presentation_time_offset);
- avio_printf(out, "\t\t\t\t\t<UTCTiming schemeIdUri=\"urn:mpeg:dash:utc:http-xsdate:2014\" value=\"%s\"/>\n",
- c->utc_timing_url);
+ avio_printf(out, "\t\t\t\t<ProducerReferenceTime id=\"%d\" inband=\"true\" type=\"%s\" wallClockTime=\"%s\" presentationTime=\"%"PRId64"\">\n",
+ i, os->producer_reference_time.flags ? "captured" : "encoder", os->producer_reference_time_str, c->presentation_time_offset);
+ avio_printf(out, "\t\t\t\t\t<UTCTiming schemeIdUri=\"urn:mpeg:dash:utc:http-xsdate:2014\" value=\"%s\"/>\n", c->utc_timing_url);
avio_printf(out, "\t\t\t\t</ProducerReferenceTime>\n");
}
if (!final && c->ldash && os->gop_size && os->frag_type != FRAG_TYPE_NONE && !(c->profile & MPD_PROFILE_DVB) &&
@@ -886,7 +875,8 @@ static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_ind
return 0;
}
-static int add_adaptation_set(AVFormatContext *s, AdaptationSet **as, enum AVMediaType type) {
+static int add_adaptation_set(AVFormatContext *s, AdaptationSet **as, enum AVMediaType type)
+{
DASHContext *c = s->priv_data;
void *mem;
@@ -909,7 +899,8 @@ static int add_adaptation_set(AVFormatContext *s, AdaptationSet **as, enum AVMed
return 0;
}
-static int adaptation_set_add_stream(AVFormatContext *s, int as_idx, int i) {
+static int adaptation_set_add_stream(AVFormatContext *s, int as_idx, int i)
+{
DASHContext *c = s->priv_data;
AdaptationSet *as = &c->as[as_idx - 1];
OutputStream *os = &c->streams[i];
@@ -931,7 +922,8 @@ static int adaptation_set_add_stream(AVFormatContext *s, int as_idx, int i) {
return 0;
}
-static int parse_adaptation_sets(AVFormatContext *s) {
+static int parse_adaptation_sets(AVFormatContext *s)
+{
DASHContext *c = s->priv_data;
const char *p = c->adaptation_sets;
enum { new_set, parse_default, parsing_streams, parse_seg_duration, parse_frag_duration } state;
@@ -1057,8 +1049,7 @@ static int parse_adaptation_sets(AVFormatContext *s) {
if (*p)
p++;
state = parse_default;
- } else if ((state != new_set) && av_strstart(p, "streams=", &p)) {
- //descriptor and durations are optional
+ } else if ((state != new_set) && av_strstart(p, "streams=", &p)) { //descriptor and durations are optional
state = parsing_streams;
} else if (state == parsing_streams) {
AdaptationSet *as = &c->as[c->nb_as - 1];
@@ -1082,8 +1073,7 @@ static int parse_adaptation_sets(AVFormatContext *s) {
if ((ret = adaptation_set_add_stream(s, c->nb_as, i)) < 0)
return ret;
}
- } else {
- // select single stream
+ } else { // select single stream
i = strtol(idx_str, &end_str, 10);
if (idx_str == end_str || i < 0 || i >= s->nb_streams) {
av_log(s, AV_LOG_ERROR, "Selected stream \"%s\" not found!\n", idx_str);
@@ -1128,9 +1118,7 @@ end:
break;
}
if (n >= c->nb_as) {
- av_log(s, AV_LOG_ERROR,
- "reference AdaptationSet id \"%d\" not found for trick mode AdaptationSet id \"%d\"\n",
- as->trick_idx, as->id);
+ av_log(s, AV_LOG_ERROR, "reference AdaptationSet id \"%d\" not found for trick mode AdaptationSet id \"%d\"\n", as->trick_idx, as->id);
return AVERROR(EINVAL);
}
}
@@ -1138,7 +1126,8 @@ end:
return 0;
}
-static int write_manifest(AVFormatContext *s, int final) {
+static int write_manifest(AVFormatContext *s, int final)
+{
DASHContext *c = s->priv_data;
AVIOContext *out;
char temp_filename[1024];
@@ -1150,8 +1139,7 @@ static int write_manifest(AVFormatContext *s, int final) {
AVDictionary *opts = NULL;
if (!use_rename && !warned_non_file++)
- av_log(s, AV_LOG_ERROR,
- "Cannot use rename on non file protocol, this may lead to races and temporary partial files\n");
+ av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this may lead to races and temporary partial files\n");
snprintf(temp_filename, sizeof(temp_filename), use_rename ? "%s.tmp" : "%s", s->url);
set_http_options(&opts, c);
@@ -1168,9 +1156,9 @@ static int write_manifest(AVFormatContext *s, int final) {
"\txsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd\"\n"
"\tprofiles=\"");
if (c->profile & MPD_PROFILE_DASH)
- avio_printf(out, "%s%s", "urn:mpeg:dash:profile:isoff-live:2011", c->profile & MPD_PROFILE_DVB ? "," : "\"\n");
+ avio_printf(out, "%s%s", "urn:mpeg:dash:profile:isoff-live:2011", c->profile & MPD_PROFILE_DVB ? "," : "\"\n");
if (c->profile & MPD_PROFILE_DVB)
- avio_printf(out, "%s", "urn:dvb:dash:profile:dvb-dash:2014\"\n");
+ avio_printf(out, "%s", "urn:dvb:dash:profile:dvb-dash:2014\"\n");
avio_printf(out, "\ttype=\"%s\"\n",
final ? "static" : "dynamic");
if (final) {
@@ -1219,8 +1207,8 @@ static int write_manifest(AVFormatContext *s, int final) {
avio_printf(out, " referenceId=\"%d\"", c->target_latency_refid);
avio_printf(out, "/>\n");
}
- if (av_cmp_q(c->min_playback_rate, (AVRational){1, 1}) ||
- av_cmp_q(c->max_playback_rate, (AVRational){1, 1}))
+ if (av_cmp_q(c->min_playback_rate, (AVRational) {1, 1}) ||
+ av_cmp_q(c->max_playback_rate, (AVRational) {1, 1}))
avio_printf(out, "\t\t<PlaybackRate min=\"%.2f\" max=\"%.2f\"/>\n",
av_q2d(c->min_playback_rate), av_q2d(c->max_playback_rate));
avio_printf(out, "\t</ServiceDescription>\n");
@@ -1243,8 +1231,7 @@ static int write_manifest(AVFormatContext *s, int final) {
avio_printf(out, "\t</Period>\n");
if (c->utc_timing_url)
- avio_printf(out, "\t<UTCTiming schemeIdUri=\"urn:mpeg:dash:utc:http-xsdate:2014\" value=\"%s\"/>\n",
- c->utc_timing_url);
+ avio_printf(out, "\t<UTCTiming schemeIdUri=\"urn:mpeg:dash:utc:http-xsdate:2014\" value=\"%s\"/>\n", c->utc_timing_url);
avio_printf(out, "</MPD>\n");
avio_flush(out);
@@ -1260,7 +1247,7 @@ static int write_manifest(AVFormatContext *s, int final) {
// Publish master playlist only the configured rate
if (c->master_playlist_created && (!c->master_publish_rate ||
- c->streams[0].segment_index % c->master_publish_rate))
+ c->streams[0].segment_index % c->master_publish_rate))
return 0;
if (*c->dirname)
@@ -1337,6 +1324,7 @@ static int write_manifest(AVFormatContext *s, int final) {
playlist_file, agroup,
codec_str, NULL, NULL);
}
+
} else {
// treat audio streams as separate renditions
@@ -1374,14 +1362,16 @@ static int write_manifest(AVFormatContext *s, int final) {
return 0;
}
-static int dict_copy_entry(AVDictionary **dst, const AVDictionary *src, const char *key) {
+static int dict_copy_entry(AVDictionary **dst, const AVDictionary *src, const char *key)
+{
AVDictionaryEntry *entry = av_dict_get(src, key, NULL, 0);
if (entry)
av_dict_set(dst, key, entry->value, AV_DICT_DONT_OVERWRITE);
return 0;
}
-static int dash_init(AVFormatContext *s) {
+static int dash_init(AVFormatContext *s)
+{
DASHContext *c = s->priv_data;
int ret = 0, i;
char *ptr;
@@ -1444,31 +1434,27 @@ static int dash_init(AVFormatContext *s) {
}
if (c->write_prft && !c->utc_timing_url) {
- av_log(s, AV_LOG_WARNING,
- "Producer Reference Time element option will be ignored as utc_timing_url is not set\n");
+ av_log(s, AV_LOG_WARNING, "Producer Reference Time element option will be ignored as utc_timing_url is not set\n");
c->write_prft = 0;
}
if (c->write_prft && !c->streaming) {
- av_log(s, AV_LOG_WARNING,
- "Producer Reference Time element option will be ignored as streaming is not enabled\n");
+ av_log(s, AV_LOG_WARNING, "Producer Reference Time element option will be ignored as streaming is not enabled\n");
c->write_prft = 0;
}
if (c->ldash && !c->write_prft) {
- av_log(s, AV_LOG_WARNING,
- "Low Latency mode enabled without Producer Reference Time element option! Resulting manifest may not be complaint\n");
+ av_log(s, AV_LOG_WARNING, "Low Latency mode enabled without Producer Reference Time element option! Resulting manifest may not be complaint\n");
}
if (c->target_latency && !c->write_prft) {
- av_log(s, AV_LOG_WARNING,
- "Target latency option will be ignored as Producer Reference Time element will not be written\n");
+ av_log(s, AV_LOG_WARNING, "Target latency option will be ignored as Producer Reference Time element will not be written\n");
c->target_latency = 0;
}
if (av_cmp_q(c->max_playback_rate, c->min_playback_rate) < 0) {
av_log(s, AV_LOG_WARNING, "Minimum playback rate value is higher than the Maximum. Both will be ignored\n");
- c->min_playback_rate = c->max_playback_rate = (AVRational){1, 1};
+ c->min_playback_rate = c->max_playback_rate = (AVRational) {1, 1};
}
av_strlcpy(c->dirname, s->url, sizeof(c->dirname));
@@ -1505,7 +1491,8 @@ static int dash_init(AVFormatContext *s) {
os->bit_rate = s->streams[i]->codecpar->bit_rate;
if (!os->bit_rate) {
- int level = s->strict_std_compliance >= FF_COMPLIANCE_STRICT ? AV_LOG_ERROR : AV_LOG_WARNING;
+ int level = s->strict_std_compliance >= FF_COMPLIANCE_STRICT ?
+ AV_LOG_ERROR : AV_LOG_WARNING;
av_log(s, level, "No bit rate set for stream %d\n", i);
if (s->strict_std_compliance >= FF_COMPLIANCE_STRICT)
return AVERROR(EINVAL);
@@ -1532,9 +1519,9 @@ static int dash_init(AVFormatContext *s) {
}
if (os->segment_type == SEGMENT_TYPE_WEBM) {
- if ((!c->single_file && !av_match_ext(os->init_seg_name, os->format_name)) ||
+ if ((!c->single_file && !av_match_ext(os->init_seg_name, os->format_name)) ||
(!c->single_file && !av_match_ext(os->media_seg_name, os->format_name)) ||
- (c->single_file && !av_match_ext(os->single_file_name, os->format_name))) {
+ ( c->single_file && !av_match_ext(os->single_file_name, os->format_name))) {
av_log(s, AV_LOG_WARNING,
"One or many segment file names doesn't end with .webm. "
"Override -init_seg_name and/or -media_seg_name and/or "
@@ -1542,8 +1529,7 @@ static int dash_init(AVFormatContext *s) {
}
if (c->streaming) {
// Streaming not supported as matroskaenc buffers internally before writing the output
- av_log(s, AV_LOG_WARNING,
- "One or more streams in WebM output format. Streaming option will be ignored\n");
+ av_log(s, AV_LOG_WARNING, "One or more streams in WebM output format. Streaming option will be ignored\n");
c->streaming = 0;
}
}
@@ -1555,10 +1541,10 @@ static int dash_init(AVFormatContext *s) {
ctx->oformat = av_guess_format(os->format_name, NULL, NULL);
if (!ctx->oformat)
return AVERROR_MUXER_NOT_FOUND;
- ctx->interrupt_callback = s->interrupt_callback;
- ctx->opaque = s->opaque;
- ctx->io_close2 = s->io_close2;
- ctx->io_open = s->io_open;
+ ctx->interrupt_callback = s->interrupt_callback;
+ ctx->opaque = s->opaque;
+ ctx->io_close2 = s->io_close2;
+ ctx->io_open = s->io_open;
ctx->strict_std_compliance = s->strict_std_compliance;
if (!(st = avformat_new_stream(ctx, NULL)))
@@ -1584,8 +1570,7 @@ static int dash_init(AVFormatContext *s) {
if (c->single_file) {
if (os->single_file_name)
- ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), os->single_file_name, i, 0, os->bit_rate,
- 0);
+ ff_dash_fill_tmpl_params(os->initfile, sizeof(os->initfile), os->single_file_name, i, 0, os->bit_rate, 0);
else
snprintf(os->initfile, sizeof(os->initfile), "%s-stream%d.%s", basename, i, os->format_name);
} else {
@@ -1620,8 +1605,7 @@ static int dash_init(AVFormatContext *s) {
c->max_segment_duration = FFMAX(c->max_segment_duration, as->seg_duration);
if (c->profile & MPD_PROFILE_DVB && (os->seg_duration > 15000000 || os->seg_duration < 960000)) {
- av_log(s, AV_LOG_ERROR, "Segment duration %"PRId64" is outside the allowed range for DVB-DASH profile\n",
- os->seg_duration);
+ av_log(s, AV_LOG_ERROR, "Segment duration %"PRId64" is outside the allowed range for DVB-DASH profile\n", os->seg_duration);
return AVERROR(EINVAL);
}
@@ -1630,14 +1614,12 @@ static int dash_init(AVFormatContext *s) {
os->frag_type = c->streaming ? FRAG_TYPE_EVERY_FRAME : FRAG_TYPE_NONE;
}
if (os->frag_type == FRAG_TYPE_DURATION && os->frag_duration > os->seg_duration) {
- av_log(s, AV_LOG_ERROR, "Fragment duration %"PRId64" is longer than Segment duration %"PRId64"\n",
- os->frag_duration, os->seg_duration);
+ av_log(s, AV_LOG_ERROR, "Fragment duration %"PRId64" is longer than Segment duration %"PRId64"\n", os->frag_duration, os->seg_duration);
return AVERROR(EINVAL);
}
if (os->frag_type == FRAG_TYPE_PFRAMES && (st->codecpar->codec_type != AVMEDIA_TYPE_VIDEO || !os->parser)) {
if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && !os->parser)
- av_log(s, AV_LOG_WARNING, "frag_type set to P-Frame reordering, but no parser found for stream %d\n",
- i);
+ av_log(s, AV_LOG_WARNING, "frag_type set to P-Frame reordering, but no parser found for stream %d\n", i);
os->frag_type = c->streaming ? FRAG_TYPE_EVERY_FRAME : FRAG_TYPE_NONE;
}
if (os->frag_type != FRAG_TYPE_PFRAMES && as->trick_idx < 0)
@@ -1646,8 +1628,8 @@ static int dash_init(AVFormatContext *s) {
if (os->segment_type == SEGMENT_TYPE_MP4) {
if (c->streaming)
- // skip_sidx : Reduce bitrate overhead
- // skip_trailer : Avoids growing memory usage with time
+ // skip_sidx : Reduce bitrate overhead
+ // skip_trailer : Avoids growing memory usage with time
av_dict_set(&opts, "movflags", "+dash+delay_moov+skip_sidx+skip_trailer", AV_DICT_APPEND);
else {
if (c->global_sidx)
@@ -1704,16 +1686,14 @@ static int dash_init(AVFormatContext *s) {
if (st->sample_aspect_ratio.num)
os->sar = st->sample_aspect_ratio;
else
- os->sar = (AVRational){1, 1};
+ os->sar = (AVRational){1,1};
av_reduce(&par.num, &par.den,
- st->codecpar->width * (int64_t) os->sar.num,
- st->codecpar->height * (int64_t) os->sar.den,
+ st->codecpar->width * (int64_t)os->sar.num,
+ st->codecpar->height * (int64_t)os->sar.den,
1024 * 1024);
if (as->par.num && av_cmp_q(par, as->par)) {
- av_log(s, AV_LOG_ERROR,
- "Conflicting stream aspect ratios values in Adaptation Set %d. Please ensure all adaptation sets have the same aspect ratio\n",
- os->as_idx);
+ av_log(s, AV_LOG_ERROR, "Conflicting stream aspect ratios values in Adaptation Set %d. Please ensure all adaptation sets have the same aspect ratio\n", os->as_idx);
return AVERROR(EINVAL);
}
as->par = par;
@@ -1732,7 +1712,6 @@ static int dash_init(AVFormatContext *s) {
c->nr_of_streams_to_flush++;
}
-
if (!c->has_video && c->seg_duration <= 0) {
av_log(s, AV_LOG_WARNING, "no video stream and no seg duration set\n");
return AVERROR(EINVAL);
@@ -1746,7 +1725,8 @@ static int dash_init(AVFormatContext *s) {
return 0;
}
-static int dash_write_header(AVFormatContext *s) {
+static int dash_write_header(AVFormatContext *s)
+{
DASHContext *c = s->priv_data;
int i, ret;
for (i = 0; i < s->nb_streams; i++) {
@@ -1755,6 +1735,7 @@ static int dash_write_header(AVFormatContext *s) {
av_dict_copy(&os->ctx->metadata, s->streams[i]->metadata, 0);
if ((ret = avformat_write_header(os->ctx, NULL)) < 0)
return ret;
+
// Flush init segment
// Only for WebM segment, since for mp4 delay_moov is set and
// the init segment is thus flushed after the first packets.
@@ -1768,13 +1749,14 @@ static int dash_write_header(AVFormatContext *s) {
static int add_segment(OutputStream *os, const char *file,
int64_t time, int64_t duration,
int64_t start_pos, int64_t range_length,
- int64_t index_length, int next_exp_index) {
+ int64_t index_length, int next_exp_index)
+{
int err;
Segment *seg;
if (os->nb_segments >= os->segments_size) {
os->segments_size = (os->segments_size + 1) * 2;
if ((err = av_reallocp_array(&os->segments, sizeof(*os->segments),
- os->segments_size)) < 0) {
+ os->segments_size)) < 0) {
os->segments_size = 0;
os->nb_segments = 0;
return err;
@@ -1786,8 +1768,7 @@ static int add_segment(OutputStream *os, const char *file,
av_strlcpy(seg->file, file, sizeof(seg->file));
seg->time = time;
seg->duration = duration;
- if (seg->time < 0) {
- // If pts<0, it is expected to be cut away with an edit list
+ if (seg->time < 0) { // If pts<0, it is expected to be cut away with an edit list
seg->duration += seg->time;
seg->time = 0;
}
@@ -1805,7 +1786,8 @@ static int add_segment(OutputStream *os, const char *file,
return 0;
}
-static void write_styp(AVIOContext *pb) {
+static void write_styp(AVIOContext *pb)
+{
avio_wb32(pb, 24);
ffio_wfourcc(pb, "styp");
ffio_wfourcc(pb, "msdh");
@@ -1815,7 +1797,8 @@ static void write_styp(AVIOContext *pb) {
}
static void find_index_range(AVFormatContext *s, const char *full_path,
- int64_t pos, int *index_length) {
+ int64_t pos, int *index_length)
+{
uint8_t buf[8];
AVIOContext *pb;
int ret;
@@ -1837,7 +1820,8 @@ static void find_index_range(AVFormatContext *s, const char *full_path,
}
static int update_stream_extradata(AVFormatContext *s, OutputStream *os,
- AVPacket *pkt, AVRational *frame_rate) {
+ AVPacket *pkt, AVRational *frame_rate)
+{
AVCodecParameters *par = os->ctx->streams[0]->codecpar;
uint8_t *extradata;
size_t extradata_size;
@@ -1882,12 +1866,13 @@ static void dashenc_delete_file(AVFormatContext *s, char *filename) {
int res = ffurl_delete(filename);
if (res < 0) {
av_log(s, (res == AVERROR(ENOENT) ? AV_LOG_WARNING : AV_LOG_ERROR),
- "failed to delete %s: %s\n", filename, av_err2str(res));
+ "failed to delete %s: %s\n", filename, av_err2str(res));
}
}
}
-static int dashenc_delete_segment_file(AVFormatContext *s, const char *file) {
+static int dashenc_delete_segment_file(AVFormatContext *s, const char* file)
+{
DASHContext *c = s->priv_data;
AVBPrint buf;
@@ -1906,7 +1891,8 @@ static int dashenc_delete_segment_file(AVFormatContext *s, const char *file) {
return 0;
}
-static inline void dashenc_delete_media_segments(AVFormatContext *s, OutputStream *os, int remove_count) {
+static inline void dashenc_delete_media_segments(AVFormatContext *s, OutputStream *os, int remove_count)
+{
for (int i = 0; i < remove_count; ++i) {
dashenc_delete_segment_file(s, os->segments[i]->file);
@@ -1918,7 +1904,8 @@ static inline void dashenc_delete_media_segments(AVFormatContext *s, OutputStrea
memmove(os->segments, os->segments + remove_count, os->nb_segments * sizeof(*os->segments));
}
-static int dash_flush(AVFormatContext *s, int final, int stream) {
+static int dash_flush(AVFormatContext *s, int final, int stream)
+{
DASHContext *c = s->priv_data;
int i, ret = 0;
@@ -1997,10 +1984,8 @@ static int dash_flush(AVFormatContext *s, int final, int stream) {
if (!os->bit_rate && !os->first_segment_bit_rate) {
os->first_segment_bit_rate = (int64_t) range_length * 8 * AV_TIME_BASE / duration;
}
- add_segment(os, os->filename, os->start_pts, os->max_pts - os->start_pts, os->pos, range_length, index_length,
- next_exp_index);
- av_log(s, AV_LOG_VERBOSE, "Representation %d media segment %d written to: %s\n", i, os->segment_index,
- os->full_path);
+ add_segment(os, os->filename, os->start_pts, os->max_pts - os->start_pts, os->pos, range_length, index_length, next_exp_index);
+ av_log(s, AV_LOG_VERBOSE, "Representation %d media segment %d written to: %s\n", i, os->segment_index, os->full_path);
os->pos += range_length;
}
@@ -2033,6 +2018,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream) {
seg->start_pos += sidx_size;
}
}
+
}
}
}
@@ -2052,17 +2038,18 @@ static int dash_flush(AVFormatContext *s, int final, int stream) {
return ret;
}
-static int dash_parse_prft(DASHContext *c, AVPacket *pkt) {
+static int dash_parse_prft(DASHContext *c, AVPacket *pkt)
+{
OutputStream *os = &c->streams[pkt->stream_index];
AVProducerReferenceTime *prft;
size_t side_data_size;
- prft = (AVProducerReferenceTime *) av_packet_get_side_data(pkt, AV_PKT_DATA_PRFT, &side_data_size);
+ prft = (AVProducerReferenceTime *)av_packet_get_side_data(pkt, AV_PKT_DATA_PRFT, &side_data_size);
if (!prft || side_data_size != sizeof(AVProducerReferenceTime) || (prft->flags && prft->flags != 24)) {
// No encoder generated or user provided capture time AVProducerReferenceTime side data. Instead
// of letting the mov muxer generate one, do it here so we can also use it for the manifest.
- prft = (AVProducerReferenceTime *) av_packet_new_side_data(pkt, AV_PKT_DATA_PRFT,
- sizeof(AVProducerReferenceTime));
+ prft = (AVProducerReferenceTime *)av_packet_new_side_data(pkt, AV_PKT_DATA_PRFT,
+ sizeof(AVProducerReferenceTime));
if (!prft)
return AVERROR(ENOMEM);
prft->wallclock = av_gettime();
@@ -2077,7 +2064,8 @@ static int dash_parse_prft(DASHContext *c, AVPacket *pkt) {
return 0;
}
-static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) {
+static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
DASHContext *c = s->priv_data;
AVStream *st = s->streams[pkt->stream_index];
OutputStream *os = &c->streams[pkt->stream_index];
@@ -2104,7 +2092,7 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) {
if (os->first_pts == AV_NOPTS_VALUE &&
s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO) {
pkt->pts -= pkt->dts;
- pkt->dts = 0;
+ pkt->dts = 0;
}
if (c->write_prft) {
@@ -2135,16 +2123,16 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) {
int64_t frame_duration = 0;
switch (os->frag_type) {
- case FRAG_TYPE_DURATION:
- frame_duration = os->frag_duration;
- break;
- case FRAG_TYPE_EVERY_FRAME:
- frame_duration = av_rescale_q(pkt->duration, st->time_base, AV_TIME_BASE_Q);
- break;
+ case FRAG_TYPE_DURATION:
+ frame_duration = os->frag_duration;
+ break;
+ case FRAG_TYPE_EVERY_FRAME:
+ frame_duration = av_rescale_q(pkt->duration, st->time_base, AV_TIME_BASE_Q);
+ break;
}
- os->availability_time_offset = ((double) os->seg_duration -
- frame_duration) / AV_TIME_BASE;
+ os->availability_time_offset = ((double) os->seg_duration -
+ frame_duration) / AV_TIME_BASE;
as->max_frag_duration = FFMAX(frame_duration, as->max_frag_duration);
}
@@ -2174,18 +2162,18 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) {
seg_end_duration, AV_TIME_BASE_Q) >= 0) {
if (!c->has_video || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
c->last_duration = av_rescale_q(pkt->pts - os->start_pts,
- st->time_base,
- AV_TIME_BASE_Q);
+ st->time_base,
+ AV_TIME_BASE_Q);
c->total_duration = av_rescale_q(pkt->pts - os->first_pts,
- st->time_base,
- AV_TIME_BASE_Q);
+ st->time_base,
+ AV_TIME_BASE_Q);
if ((!c->use_timeline || !c->use_template) && os->last_duration) {
- if (c->last_duration < os->last_duration * 9 / 10 ||
- c->last_duration > os->last_duration * 11 / 10) {
+ if (c->last_duration < os->last_duration*9/10 ||
+ c->last_duration > os->last_duration*11/10) {
av_log(s, AV_LOG_WARNING,
- "Segment durations differ too much, enable use_timeline "
- "and use_template, or keep a stricter keyframe interval\n");
+ "Segment durations differ too much, enable use_timeline "
+ "and use_template, or keep a stricter keyframe interval\n");
}
}
}
@@ -2229,14 +2217,13 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) {
int64_t frag_duration = av_rescale_q(os->total_pkt_duration, st->time_base,
AV_TIME_BASE_Q);
os->availability_time_offset = ((double) os->seg_duration -
- frag_duration) / AV_TIME_BASE;
- as->max_frag_duration = FFMAX(frag_duration, as->max_frag_duration);
+ frag_duration) / AV_TIME_BASE;
+ as->max_frag_duration = FFMAX(frag_duration, as->max_frag_duration);
}
}
}
- if (pkt->flags & AV_PKT_FLAG_KEY && (os->packets_written || os->nb_segments) && !os->gop_size && as->trick_idx <
- 0) {
+ if (pkt->flags & AV_PKT_FLAG_KEY && (os->packets_written || os->nb_segments) && !os->gop_size && as->trick_idx < 0) {
os->gop_size = os->last_duration + av_rescale_q(os->total_pkt_duration, st->time_base, AV_TIME_BASE_Q);
c->max_gop_size = FFMAX(c->max_gop_size, os->gop_size);
}
@@ -2292,7 +2279,7 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) {
int len = 0;
uint8_t *buf = NULL;
avio_flush(os->ctx->pb);
- len = avio_get_dyn_buf(os->ctx->pb, &buf);
+ len = avio_get_dyn_buf (os->ctx->pb, &buf);
if (os->out) {
avio_write(os->out, buf + os->written_len, len - os->written_len);
avio_flush(os->out);
@@ -2303,7 +2290,8 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) {
return ret;
}
-static int dash_write_trailer(AVFormatContext *s) {
+static int dash_write_trailer(AVFormatContext *s)
+{
DASHContext *c = s->priv_data;
int i;
@@ -2345,7 +2333,8 @@ static int dash_write_trailer(AVFormatContext *s) {
}
static int dash_check_bitstream(AVFormatContext *s, AVStream *st,
- const AVPacket *avpkt) {
+ const AVPacket *avpkt)
+{
DASHContext *c = s->priv_data;
OutputStream *os = &c->streams[st->index];
AVFormatContext *oc = os->ctx;
@@ -2354,9 +2343,9 @@ static int dash_check_bitstream(AVFormatContext *s, AVStream *st,
int ret;
ret = ffofmt(oc->oformat)->check_bitstream(oc, ost, avpkt);
if (ret == 1) {
- FFStream *const sti = ffstream(st);
+ FFStream *const sti = ffstream(st);
FFStream *const osti = ffstream(ost);
- sti->bsfc = osti->bsfc;
+ sti->bsfc = osti->bsfc;
osti->bsfc = NULL;
}
return ret;
@@ -2367,204 +2356,74 @@ static int dash_check_bitstream(AVFormatContext *s, AVStream *st,
#define OFFSET(x) offsetof(DASHContext, x)
#define E AV_OPT_FLAG_ENCODING_PARAM
static const AVOption options[] = {
- {
- "adaptation_sets", "Adaptation sets. Syntax: id=0,streams=0,1,2 id=1,streams=3,4 and so on",
- OFFSET(adaptation_sets), AV_OPT_TYPE_STRING, {0}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM
- },
- {
- "dash_segment_type", "set dash segment files type", OFFSET(segment_type_option), AV_OPT_TYPE_INT,
- {.i64 = SEGMENT_TYPE_AUTO}, 0, SEGMENT_TYPE_NB - 1, E, .unit = "segment_type"
- },
- {
- "auto", "select segment file format based on codec", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_AUTO}, 0,
- UINT_MAX, E, .unit = "segment_type"
- },
- {
- "mp4", "make segment file in ISOBMFF format", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_MP4}, 0, UINT_MAX, E,
- .unit = "segment_type"
- },
- {
- "webm", "make segment file in WebM format", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_WEBM}, 0, UINT_MAX, E,
- .unit = "segment_type"
- },
- {
- "extra_window_size", "number of segments kept outside of the manifest before removing from disk",
- OFFSET(extra_window_size), AV_OPT_TYPE_INT, {.i64 = 5}, 0, INT_MAX, E
- },
- {
- "format_options", "set list of options for the container format (mp4/webm) used for dash",
- OFFSET(format_options), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, E
- },
- {
- "frag_duration", "fragment duration (in seconds, fractional value can be set)", OFFSET(frag_duration),
- AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT_MAX, E
- },
- {
- "frag_type", "set type of interval for fragments", OFFSET(frag_type), AV_OPT_TYPE_INT, {.i64 = FRAG_TYPE_NONE},
- 0, FRAG_TYPE_NB - 1, E, .unit = "frag_type"
- },
- {
- "none", "one fragment per segment", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_NONE}, 0, UINT_MAX, E,
- .unit = "frag_type"
- },
- {
- "every_frame", "fragment at every frame", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_EVERY_FRAME}, 0, UINT_MAX, E,
- .unit = "frag_type"
- },
- {
- "duration", "fragment at specific time intervals", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_DURATION}, 0,
- UINT_MAX, E, .unit = "frag_type"
- },
- {
- "pframes", "fragment at keyframes and following P-Frame reordering (Video only, experimental)", 0,
- AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_PFRAMES}, 0, UINT_MAX, E, .unit = "frag_type"
- },
- {
- "global_sidx", "Write global SIDX atom. Applicable only for single file, mp4 output, non-streaming mode",
- OFFSET(global_sidx), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E
- },
- {
- "hls_master_name", "HLS master playlist name", OFFSET(hls_master_name), AV_OPT_TYPE_STRING,
- {.str = "master.m3u8"}, 0, 0, E
- },
- {
- "hls_playlist", "Generate HLS playlist files(master.m3u8, media_%d.m3u8)", OFFSET(hls_playlist),
- AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E
- },
- {"http_opts", "HTTP protocol options", OFFSET(http_opts), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, E},
- {
- "http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0,
- 1, E
- },
- {
- "http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING,
- {.str = NULL}, 0, 0, E
- },
- {
- "ignore_io_errors", "Ignore IO errors during open and write. Useful for long-duration runs with network output",
- OFFSET(ignore_io_errors), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E
- },
- {
- "index_correction", "Enable/Disable segment index correction logic", OFFSET(index_correction), AV_OPT_TYPE_BOOL,
- {.i64 = 0}, 0, 1, E
- },
- {
- "init_seg_name", "DASH-templated name to used for the initialization segment", OFFSET(init_seg_name),
- AV_OPT_TYPE_STRING, {.str = "init-stream$RepresentationID$.$ext$"}, 0, 0, E
- },
- {
- "ldash", "Enable Low-latency dash. Constrains the value of a few elements", OFFSET(ldash), AV_OPT_TYPE_BOOL,
- {.i64 = 0}, 0, 1, E
- },
- {
- "lhls", "Enable Low-latency HLS(Experimental). Adds #EXT-X-PREFETCH tag with current segment's URI",
- OFFSET(lhls), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E
- },
- {
- "master_m3u8_publish_rate", "Publish master playlist every after this many segment intervals",
- OFFSET(master_publish_rate), AV_OPT_TYPE_INT, {.i64 = 0}, 0, UINT_MAX, E
- },
- {
- "max_playback_rate", "Set desired maximum playback rate", OFFSET(max_playback_rate), AV_OPT_TYPE_RATIONAL,
- {.dbl = 1.0}, 0.5, 1.5, E
- },
- {
- "media_seg_name", "DASH-templated name to used for the media segments", OFFSET(media_seg_name),
- AV_OPT_TYPE_STRING, {.str = "chunk-stream$RepresentationID$-$Number%05d$.$ext$"}, 0, 0, E
- },
- {"method", "set the HTTP method", OFFSET(method), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
- {
- "min_playback_rate", "Set desired minimum playback rate", OFFSET(min_playback_rate), AV_OPT_TYPE_RATIONAL,
- {.dbl = 1.0}, 0.5, 1.5, E
- },
- {
- "mpd_profile", "Set profiles. Elements and values used in the manifest may be constrained by them",
- OFFSET(profile), AV_OPT_TYPE_FLAGS, {.i64 = MPD_PROFILE_DASH}, 0, UINT_MAX, E, .unit = "mpd_profile"
- },
- {
- "dash", "MPEG-DASH ISO Base media file format live profile", 0, AV_OPT_TYPE_CONST, {.i64 = MPD_PROFILE_DASH}, 0,
- UINT_MAX, E, .unit = "mpd_profile"
- },
- {
- "dvb_dash", "DVB-DASH profile", 0, AV_OPT_TYPE_CONST, {.i64 = MPD_PROFILE_DVB}, 0, UINT_MAX, E,
- .unit = "mpd_profile"
- },
- {
- "remove_at_exit", "remove all segments when finished", OFFSET(remove_at_exit), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0,
- 1, E
- },
- {
- "seg_duration", "segment duration (in seconds, fractional value can be set)", OFFSET(seg_duration),
- AV_OPT_TYPE_DURATION, {.i64 = 5000000}, 0, INT_MAX, E
- },
- {
- "single_file", "Store all segments in one file, accessed using byte ranges", OFFSET(single_file),
- AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E
- },
- {
- "single_file_name",
- "DASH-templated name to be used for baseURL. Implies storing all segments in one file, accessed using byte ranges",
- OFFSET(single_file_name), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E
- },
- {
- "streaming", "Enable/Disable streaming mode of output. Each frame will be moof fragment", OFFSET(streaming),
- AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E
- },
- {
- "target_latency", "Set desired target latency for Low-latency dash", OFFSET(target_latency),
- AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT_MAX, E
- },
- {
- "timeout", "set timeout for socket I/O operations", OFFSET(timeout), AV_OPT_TYPE_DURATION, {.i64 = -1}, -1,
- INT_MAX, .flags = E
- },
- {
- "update_period", "Set the mpd update interval", OFFSET(update_period), AV_OPT_TYPE_INT64, {.i64 = 0}, 0,
- INT64_MAX, E
- },
- {
- "use_template", "Use SegmentTemplate instead of SegmentList", OFFSET(use_template), AV_OPT_TYPE_BOOL,
- {.i64 = 1}, 0, 1, E
- },
- {
- "use_timeline", "Use SegmentTimeline in SegmentTemplate", OFFSET(use_timeline), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0,
- 1, E
- },
- {
- "utc_timing_url", "URL of the page that will return the UTC timestamp in ISO format", OFFSET(utc_timing_url),
- AV_OPT_TYPE_STRING, {0}, 0, 0, E
- },
- {
- "window_size", "number of segments kept in the manifest", OFFSET(window_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0,
- INT_MAX, E
- },
- {
- "write_prft", "Write producer reference time element", OFFSET(write_prft), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1,
- E
- },
- {NULL},
+ { "adaptation_sets", "Adaptation sets. Syntax: id=0,streams=0,1,2 id=1,streams=3,4 and so on", OFFSET(adaptation_sets), AV_OPT_TYPE_STRING, { 0 }, 0, 0, AV_OPT_FLAG_ENCODING_PARAM },
+ { "dash_segment_type", "set dash segment files type", OFFSET(segment_type_option), AV_OPT_TYPE_INT, {.i64 = SEGMENT_TYPE_AUTO }, 0, SEGMENT_TYPE_NB - 1, E, .unit = "segment_type"},
+ { "auto", "select segment file format based on codec", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_AUTO }, 0, UINT_MAX, E, .unit = "segment_type"},
+ { "mp4", "make segment file in ISOBMFF format", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_MP4 }, 0, UINT_MAX, E, .unit = "segment_type"},
+ { "webm", "make segment file in WebM format", 0, AV_OPT_TYPE_CONST, {.i64 = SEGMENT_TYPE_WEBM }, 0, UINT_MAX, E, .unit = "segment_type"},
+ { "extra_window_size", "number of segments kept outside of the manifest before removing from disk", OFFSET(extra_window_size), AV_OPT_TYPE_INT, { .i64 = 5 }, 0, INT_MAX, E },
+ { "format_options","set list of options for the container format (mp4/webm) used for dash", OFFSET(format_options), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, E},
+ { "frag_duration", "fragment duration (in seconds, fractional value can be set)", OFFSET(frag_duration), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT_MAX, E },
+ { "frag_type", "set type of interval for fragments", OFFSET(frag_type), AV_OPT_TYPE_INT, {.i64 = FRAG_TYPE_NONE }, 0, FRAG_TYPE_NB - 1, E, .unit = "frag_type"},
+ { "none", "one fragment per segment", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_NONE }, 0, UINT_MAX, E, .unit = "frag_type"},
+ { "every_frame", "fragment at every frame", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_EVERY_FRAME }, 0, UINT_MAX, E, .unit = "frag_type"},
+ { "duration", "fragment at specific time intervals", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_DURATION }, 0, UINT_MAX, E, .unit = "frag_type"},
+ { "pframes", "fragment at keyframes and following P-Frame reordering (Video only, experimental)", 0, AV_OPT_TYPE_CONST, {.i64 = FRAG_TYPE_PFRAMES }, 0, UINT_MAX, E, .unit = "frag_type"},
+ { "global_sidx", "Write global SIDX atom. Applicable only for single file, mp4 output, non-streaming mode", OFFSET(global_sidx), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
+ { "hls_master_name", "HLS master playlist name", OFFSET(hls_master_name), AV_OPT_TYPE_STRING, {.str = "master.m3u8"}, 0, 0, E },
+ { "hls_playlist", "Generate HLS playlist files(master.m3u8, media_%d.m3u8)", OFFSET(hls_playlist), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
+ { "http_opts", "HTTP protocol options", OFFSET(http_opts), AV_OPT_TYPE_DICT, { .str = NULL }, 0, 0, E },
+ { "http_persistent", "Use persistent HTTP connections", OFFSET(http_persistent), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
+ { "http_user_agent", "override User-Agent field in HTTP header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E},
+ { "ignore_io_errors", "Ignore IO errors during open and write. Useful for long-duration runs with network output", OFFSET(ignore_io_errors), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
+ { "index_correction", "Enable/Disable segment index correction logic", OFFSET(index_correction), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
+ { "init_seg_name", "DASH-templated name to used for the initialization segment", OFFSET(init_seg_name), AV_OPT_TYPE_STRING, {.str = "init-stream$RepresentationID$.$ext$"}, 0, 0, E },
+ { "ldash", "Enable Low-latency dash. Constrains the value of a few elements", OFFSET(ldash), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
+ { "lhls", "Enable Low-latency HLS(Experimental). Adds #EXT-X-PREFETCH tag with current segment's URI", OFFSET(lhls), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
+ { "master_m3u8_publish_rate", "Publish master playlist every after this many segment intervals", OFFSET(master_publish_rate), AV_OPT_TYPE_INT, {.i64 = 0}, 0, UINT_MAX, E},
+ { "max_playback_rate", "Set desired maximum playback rate", OFFSET(max_playback_rate), AV_OPT_TYPE_RATIONAL, { .dbl = 1.0 }, 0.5, 1.5, E },
+ { "media_seg_name", "DASH-templated name to used for the media segments", OFFSET(media_seg_name), AV_OPT_TYPE_STRING, {.str = "chunk-stream$RepresentationID$-$Number%05d$.$ext$"}, 0, 0, E },
+ { "method", "set the HTTP method", OFFSET(method), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
+ { "min_playback_rate", "Set desired minimum playback rate", OFFSET(min_playback_rate), AV_OPT_TYPE_RATIONAL, { .dbl = 1.0 }, 0.5, 1.5, E },
+ { "mpd_profile", "Set profiles. Elements and values used in the manifest may be constrained by them", OFFSET(profile), AV_OPT_TYPE_FLAGS, {.i64 = MPD_PROFILE_DASH }, 0, UINT_MAX, E, .unit = "mpd_profile"},
+ { "dash", "MPEG-DASH ISO Base media file format live profile", 0, AV_OPT_TYPE_CONST, {.i64 = MPD_PROFILE_DASH }, 0, UINT_MAX, E, .unit = "mpd_profile"},
+ { "dvb_dash", "DVB-DASH profile", 0, AV_OPT_TYPE_CONST, {.i64 = MPD_PROFILE_DVB }, 0, UINT_MAX, E, .unit = "mpd_profile"},
+ { "remove_at_exit", "remove all segments when finished", OFFSET(remove_at_exit), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
+ { "seg_duration", "segment duration (in seconds, fractional value can be set)", OFFSET(seg_duration), AV_OPT_TYPE_DURATION, { .i64 = 5000000 }, 0, INT_MAX, E },
+ { "single_file", "Store all segments in one file, accessed using byte ranges", OFFSET(single_file), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
+ { "single_file_name", "DASH-templated name to be used for baseURL. Implies storing all segments in one file, accessed using byte ranges", OFFSET(single_file_name), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E },
+ { "streaming", "Enable/Disable streaming mode of output. Each frame will be moof fragment", OFFSET(streaming), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
+ { "target_latency", "Set desired target latency for Low-latency dash", OFFSET(target_latency), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT_MAX, E },
+ { "timeout", "set timeout for socket I/O operations", OFFSET(timeout), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT_MAX, .flags = E },
+ { "update_period", "Set the mpd update interval", OFFSET(update_period), AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, E},
+ { "use_template", "Use SegmentTemplate instead of SegmentList", OFFSET(use_template), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },
+ { "use_timeline", "Use SegmentTimeline in SegmentTemplate", OFFSET(use_timeline), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, E },
+ { "utc_timing_url", "URL of the page that will return the UTC timestamp in ISO format", OFFSET(utc_timing_url), AV_OPT_TYPE_STRING, { 0 }, 0, 0, E },
+ { "window_size", "number of segments kept in the manifest", OFFSET(window_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, E },
+ { "write_prft", "Write producer reference time element", OFFSET(write_prft), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, E},
+ { NULL },
};
static const AVClass dash_class = {
.class_name = "dash muxer",
- .item_name = av_default_item_name,
- .option = options,
- .version = LIBAVUTIL_VERSION_INT,
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
};
const FFOutputFormat ff_dash_muxer = {
- .p.name = "dash",
- .p.long_name = NULL_IF_CONFIG_SMALL("DASH Muxer"),
- .p.extensions = "mpd",
- .p.audio_codec = AV_CODEC_ID_AAC,
- .p.video_codec = AV_CODEC_ID_H264,
- .p.flags = AVFMT_GLOBALHEADER | AVFMT_NOFILE | AVFMT_TS_NEGATIVE,
- .p.priv_class = &dash_class,
+ .p.name = "dash",
+ .p.long_name = NULL_IF_CONFIG_SMALL("DASH Muxer"),
+ .p.extensions = "mpd",
+ .p.audio_codec = AV_CODEC_ID_AAC,
+ .p.video_codec = AV_CODEC_ID_H264,
+ .p.flags = AVFMT_GLOBALHEADER | AVFMT_NOFILE | AVFMT_TS_NEGATIVE,
+ .p.priv_class = &dash_class,
.priv_data_size = sizeof(DASHContext),
- .init = dash_init,
- .write_header = dash_write_header,
- .write_packet = dash_write_packet,
- .write_trailer = dash_write_trailer,
- .deinit = dash_free,
+ .init = dash_init,
+ .write_header = dash_write_header,
+ .write_packet = dash_write_packet,
+ .write_trailer = dash_write_trailer,
+ .deinit = dash_free,
.check_bitstream = dash_check_bitstream,
};
--
2.49.1
_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2025-09-24 10:36 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-09-24 10:35 [FFmpeg-devel] [PATCH] libavformat/dashenc: preserve metadata from container and streams (PR #20594) damitha via ffmpeg-devel
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror http://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ http://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git