From patchwork Thu Oct 17 18:59:16 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Almer X-Patchwork-Id: 15825 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id D052A44A238 for ; Thu, 17 Oct 2019 22:00:20 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id A1A6868AB32; Thu, 17 Oct 2019 22:00:20 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-qt1-f194.google.com (mail-qt1-f194.google.com [209.85.160.194]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id DB98468AB29 for ; Thu, 17 Oct 2019 22:00:15 +0300 (EEST) Received: by mail-qt1-f194.google.com with SMTP id o12so5200920qtf.3 for ; Thu, 17 Oct 2019 12:00:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=svSF7ERjFSX7NXLdf+ZjLyqwPipoihFC3wXSQV1vMZ4=; b=tCxJc4g/eRFxcQ87EJHVugWYQfOv6/HNiVjW256jAVpCmrzQ4jQ5XZTPWCOqex+wdI osfcUVm/QIxXvvsKvODiNabmJyX9q2XyqwvYpJDH8T5i3VBw2AdA2eNPfld3XQgZPTDc hDNLSG0nW+/C4xxbXKMgKrSJ2MareB3l58R62qwZcaOCa5B/wELMcTGHNyERQJoJk9mL A+FLt6t1zgohaUFB+pMIkZ3WZji3+IZ3mlHCAnCOwP2xhaJ/hzHoF7ylXXD06MHVhzhE wzDYlZ5zNPrUkikfvsnwCtQ0eDNnoDGTAB8cWvsB1BERpXua6myo+ZYrkEdMn8k8nDXR VU7A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=svSF7ERjFSX7NXLdf+ZjLyqwPipoihFC3wXSQV1vMZ4=; b=Nlr+cQABgBoRV6aNjFbU0f6FaQRmWseGdmmwobuOMHDOEuVVpstcFzgfxZ4LCKKHTI miUINlSlgUYLCg1alu+4Y7HR4/583TcUPiSy0GxhHLAX76eSzibkFEsMzM5wdtEprM66 wvhLLg3cPMbgVEumYoPtmm+q0IcyiuqiCpAIhhaITWXLFLRhyVuyD40RsCiPYUKlTdqn l5c1z/uf/SuBJZzpxnBCHqaHuAieSgfMoBpI85VQkASEog0xHpaWJdAKP1ptJaK1Q2i9 mCqEGLlnL+x/CG1x/YkJFlOsbm3r7j/K6ohxXn+v2niUsmge/8zAz96hLfuIseRv+wZT Xl+g== X-Gm-Message-State: APjAAAVI6jz0mDHnqY5U0OO7zVqHYbLdT0jzbjARgBFcZdNM8iwev7H8 /f5rQxmLxTMIdu+N/PbXoBOenPYD X-Google-Smtp-Source: APXvYqxRU3C54qIDGvX4ru0r2Alf69PF2nSEiZuUeoVdKbAsyLnw7Eg3ibunnFrRoUiYJ+zwayPrGA== X-Received: by 2002:ad4:50c2:: with SMTP id e2mr5561378qvq.67.1571338813575; Thu, 17 Oct 2019 12:00:13 -0700 (PDT) Received: from localhost.localdomain ([191.83.221.234]) by smtp.gmail.com with ESMTPSA id v141sm798933qka.59.2019.10.17.12.00.12 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Oct 2019 12:00:13 -0700 (PDT) From: James Almer To: ffmpeg-devel@ffmpeg.org Date: Thu, 17 Oct 2019 15:59:16 -0300 Message-Id: <20191017185916.2957-12-jamrial@gmail.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20191017185916.2957-1-jamrial@gmail.com> References: <20191017185916.2957-1-jamrial@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 11/11] avformat/dashenc: implement DVB-DASH profile X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Add new required elements and constrain presence and values for existing ones based on the spec. Signed-off-by: James Almer --- 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\tformat_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 }, };