[FFmpeg-devel] [PATCH 11/11] avformat/dashenc: implement DVB-DASH profile
James Almer
jamrial at gmail.com
Thu Oct 17 21:59:16 EEST 2019
Add new required elements and constrain presence and values for existing
ones based on the spec.
Signed-off-by: James Almer <jamrial at gmail.com>
---
libavformat/dashenc.c | 43 +++++++++++++++++++++++++++++++++++++++++--
1 file changed, 41 insertions(+), 2 deletions(-)
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index b32ff7393b..106800d268 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -66,6 +66,12 @@ enum {
FRAG_TYPE_NB
};
+enum {
+ MPD_PROFILE_DASH = 0,
+ MPD_PROFILE_DVB,
+ MPD_PROFILE_NB
+};
+
typedef struct Segment {
char file[1024];
int64_t start_pos;
@@ -85,6 +91,7 @@ typedef struct AdaptationSet {
AVDictionary *metadata;
AVRational min_frame_rate, max_frame_rate;
int ambiguous_frame_rate;
+ int max_width, max_height;
} AdaptationSet;
typedef struct OutputStream {
@@ -173,6 +180,7 @@ typedef struct DASHContext {
int nr_of_streams_flushed;
int frag_type;
int write_prft;
+ int profile;
} DASHContext;
static struct codec_string {
@@ -784,6 +792,8 @@ static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_ind
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);
+ if (as->media_type == AVMEDIA_TYPE_VIDEO)
+ avio_printf(out, " maxWidth=\"%d\" maxHeight=\"%d\"", as->max_width, as->max_height);
lang = av_dict_get(as->metadata, "language", NULL, 0);
if (lang)
avio_printf(out, " lang=\"%s\"", lang->value);
@@ -809,6 +819,19 @@ static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_ind
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);
+ if (st->codecpar->field_order == AV_FIELD_UNKNOWN)
+ avio_printf(out, " scanType=\"unknown\"");
+ else if (st->codecpar->field_order != AV_FIELD_PROGRESSIVE)
+ avio_printf(out, " scanType=\"interlaced\"");
+ if (st->sample_aspect_ratio.num) {
+ AVRational par;
+ av_reduce(&par.num, &par.den,
+ st->codecpar->width * (int64_t)st->sample_aspect_ratio.num,
+ st->codecpar->height * (int64_t)st->sample_aspect_ratio.den,
+ 1024 * 1024);
+ avio_printf(out, " sar=\"%d/%d\" par=\"%d/%d\"", st->sample_aspect_ratio.num, st->sample_aspect_ratio.den, par.num, par.den);
+ } else
+ avio_printf(out, " sar=\"1/1\"");
if (st->avg_frame_rate.num)
avio_printf(out, " frameRate=\"%d/%d\"", st->avg_frame_rate.num, st->avg_frame_rate.den);
avio_printf(out, ">\n");
@@ -1037,8 +1060,10 @@ static int write_manifest(AVFormatContext *s, int final)
"\txmlns=\"urn:mpeg:dash:schema:mpd:2011\"\n"
"\txmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
"\txsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd\"\n"
- "\tprofiles=\"urn:mpeg:dash:profile:isoff-live:2011\"\n"
- "\ttype=\"%s\"\n", final ? "static" : "dynamic");
+ "\tprofiles=\"%s\"\n"
+ "\ttype=\"%s\"\n",
+ c->profile == MPD_PROFILE_DVB ? "urn:dvb:dash:profile:dvb-dash:2014" : "urn:mpeg:dash:profile:isoff-live:2011",
+ final ? "static" : "dynamic");
if (final) {
avio_printf(out, "\tmediaPresentationDuration=\"");
write_time(out, c->total_duration);
@@ -1443,6 +1468,12 @@ static int dash_init(AVFormatContext *s)
} else {
as->ambiguous_frame_rate = 1;
}
+
+ if (st->codecpar->width > as->max_width)
+ as->max_width = st->codecpar->width;
+ if (st->codecpar->height > as->max_height)
+ as->max_height = st->codecpar->height;
+
c->has_video = 1;
}
@@ -1454,6 +1485,11 @@ static int dash_init(AVFormatContext *s)
os->seg_duration = as->seg_duration ? as->seg_duration : c->seg_duration;
os->segment_index = 1;
+ 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);
+ return AVERROR(EINVAL);
+ }
+
if (s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
c->nr_of_streams_to_flush++;
}
@@ -2108,6 +2144,9 @@ static const AVOption options[] = {
{ "ldash", "Enable Low-latency dash. Constrains the value of a few elements", OFFSET(ldash), 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},
{ "write_prft", "Write producer reference time element", OFFSET(write_prft), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E},
+ { "mpd_profile", "Set profile. Elements and values used in the manifest may be constrained by it", OFFSET(profile), AV_OPT_TYPE_INT, {.i64 = MPD_PROFILE_DASH }, 0, MPD_PROFILE_NB - 1, E, "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, "mpd_profile"},
+ { "dvb-dash", "DVB-DASH profile", 0, AV_OPT_TYPE_CONST, {.i64 = MPD_PROFILE_DVB }, 0, UINT_MAX, E, "mpd_profile"},
{ NULL },
};
--
2.23.0
More information about the ffmpeg-devel
mailing list