From patchwork Sat Sep 19 16:36:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Rheinhardt X-Patchwork-Id: 22531 Delivered-To: andriy.gelman@gmail.com Received: by 2002:a25:c650:0:0:0:0:0 with SMTP id k77csp2088594ybf; Sat, 19 Sep 2020 09:40:09 -0700 (PDT) X-Google-Smtp-Source: ABdhPJw639Ba0amdpusSZ1m0CK/nxusxKBEgU3FLWX7a30etTjvqrze4jigVZRUM9QWZ/sTH65qS X-Received: by 2002:adf:c64e:: with SMTP id u14mr42466646wrg.373.1600533609041; Sat, 19 Sep 2020 09:40:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1600533609; cv=none; d=google.com; s=arc-20160816; b=0+c9c8aW2zT41QYaitv2axqmS0KCrZLtKVmLMIed1fmssPZ4U54FxsbAtFaVp5cQe1 N3NqtVKWlX+59g4/uCNiyX9OhBFbs1FcPhYJ9qcAgjdT6FFzQxXEbAot0xCrtsIC5k1k zYQ3ckp4FkmjYIVcJrj8aZhJJ9yCa0vWxRlfU0eJykl1KC4cFHVuYkHN3j+cz/emTydu CCNc/sWWQiFRPEJl6zGkW/QYWQOEu8iynt7G7EqNwOktr6mGykG4CT7WiGsWzuk2MOVc 9rm7h0SrqtgrceUiWYS6sw1h4BPdcGnZgQINL7bg+mtaWRuRq/Z1aEyOJdWsVyeLcZYq aDVg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=pX+DLyJ9z8baEssYqEjtufE/gM1ShfbBuletAXBkDTA=; b=vuDYtnTTQ3hg2QcW1QDpB9ll+WD8iK9KEWi24BLIquaTecpcWChVc6jiGRyedxaYve QZgghOcKtO0g8YZcRED9ebMT0aIeN+OSZ5xbYQ4m/1wvGTJAquvibghnoOTKHoeMqsRk Jv7mel3TLMfXzwvOADnIe8zkUY6LQygI2Jwm0mk6cyWN/n4EB+GjAhCf+4mJyBJu4cQT 6Fb/LSTCSe/lxtlQFQKn2wVpFxqIB5Aelo2xe7FmaYYpJIwY7qZ/hiCt/UOGl19adJ+x W/zBYe75CfZleDZl4hXfS2K1ioZuT1mC3F6HKcjvpg/Fh4P+GTQdMhnZGIByZvNvpqze 7dLQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=d3BjnAcH; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id x16si6281512wmj.155.2020.09.19.09.40.08; Sat, 19 Sep 2020 09:40:09 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=d3BjnAcH; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 9C0F468B980; Sat, 19 Sep 2020 19:37:41 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm1-f67.google.com (mail-wm1-f67.google.com [209.85.128.67]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id D2F4468B7AB for ; Sat, 19 Sep 2020 19:37:34 +0300 (EEST) Received: by mail-wm1-f67.google.com with SMTP id z9so8462590wmk.1 for ; Sat, 19 Sep 2020 09:37:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Qbr59balKYXp8YRJmFp1qUTgu8aGRz1fYs/IDiSSCTI=; b=d3BjnAcH6+1cZWl0XyrOHCsHuXOBEdbr+M3pkkiaoFxFcsOaNEOtblVhgqeTNmnie9 0nzpFjfkMI9KEs39l8vNDoKglYWKFhpJRafKWxLsyU36dG+5tNAKdtL3qekYY2iQO5fM KpHs5nZOjVUz//Ktql7onWRwrpcbMqrkXxeK6gSe1bw2V/9WqW29TyUWm6YIqgXKSkar 1E0vmMFknxDmn7ED2yntce9glZpwduv68OhalnuqnZqjjSevxHL4iInrq1eW6x2xT2Gx TiJ2yfzvJ1CJnZwYwlFmbo85aTzi82YJ9GzsCMCMx/LmufBIzislAXOY8ElZ/1tIVPGQ Mnsg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Qbr59balKYXp8YRJmFp1qUTgu8aGRz1fYs/IDiSSCTI=; b=WVVUch/jdYQVAgKfC+2FM9KBegWQKy7ZHKQfg7E09UKRvrukXeEf2VdWvWofVXt5I2 C4LrExqTl5W7WjBsYC3pkyw5h1I2zM4GqZBFP81Pf0XOL6BUumir/cvPyIbAWVmOtvtM okoFLWAE+jyY1/tsmeIowNQBEWLJPgV+cvfBgc2G4HeREhD8PL2GEl++p7rtl3H5p05K 1YcJI0jIIPJwihX1JnryolJMSGzTxu0xRLo3XWZm0CW2buro0sneVaRxk4bO+P4/ROW6 oWwIw0iWQmQMr9UoLMToL/una99FvuAz6aMUzPh/elcJRmSXWTeRb5StxoKZy7ILtQEF yLag== X-Gm-Message-State: AOAM530vCRNg4upP9NmDiBlZZ9fVQFOPohX9IgTKBADQRQh/lnPDrPMD yfR+59aImYpFFRqQdxa/WpvzFbHkoxI= X-Received: by 2002:a1c:4c0d:: with SMTP id z13mr20687641wmf.115.1600533453477; Sat, 19 Sep 2020 09:37:33 -0700 (PDT) Received: from sblaptop.fritz.box (ipbcc1fb0f.dynamic.kabel-deutschland.de. [188.193.251.15]) by smtp.gmail.com with ESMTPSA id d5sm12451137wrb.28.2020.09.19.09.37.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 19 Sep 2020 09:37:32 -0700 (PDT) From: Andreas Rheinhardt To: ffmpeg-devel@ffmpeg.org Date: Sat, 19 Sep 2020 18:36:08 +0200 Message-Id: <20200919163610.1099233-19-andreas.rheinhardt@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200919163610.1099233-1-andreas.rheinhardt@gmail.com> References: <20200919163610.1099233-1-andreas.rheinhardt@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 19/21] avformat/dashdec: Cosmetics 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 Cc: Andreas Rheinhardt Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: gTJnyaPgAFd6 Content-Length: 38318 1. Perform the necessary reindentations after the last few commits. 2. Adapt switches to the ordinary indentation style. 3. Now that the effective lifetimes of the variables containing the freshly allocated strings used when parsing the representation are disjoint, the variables can be replaced by a single variable. Doing so has the advantage of making it more clear that these are throwaway variables, hence it has been done. Signed-off-by: Andreas Rheinhardt --- libavformat/dashdec.c | 498 +++++++++++++++++++++--------------------- 1 file changed, 245 insertions(+), 253 deletions(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index 71c6b5cc1a..73740eb061 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -227,21 +227,21 @@ static uint32_t get_duration_insec(AVFormatContext *s, const char *duration) return 0; /* parser error */ } switch (type) { - case 'D': - days = (uint32_t)value; - break; - case 'H': - hours = (uint32_t)value; - break; - case 'M': - mins = (uint32_t)value; - break; - case 'S': - secs = (uint32_t)value; - break; - default: - // handle invalid type - break; + case 'D': + days = (uint32_t)value; + break; + case 'H': + hours = (uint32_t)value; + break; + case 'M': + mins = (uint32_t)value; + break; + case 'S': + secs = (uint32_t)value; + break; + default: + // handle invalid type + break; } ptr += size; } @@ -843,12 +843,6 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, xmlNodePtr segmentlists_tab[3]; xmlNodePtr fragment_timeline_node = NULL; xmlNodePtr fragment_templates_tab[5]; - char *duration_val = NULL; - char *presentation_timeoffset_val = NULL; - char *startnumber_val = NULL; - char *timescale_val = NULL; - char *initialization_val = NULL; - char *media_val = NULL; char *val = NULL; xmlNodePtr baseurl_nodes[4]; xmlNodePtr representation_node = node; @@ -869,213 +863,214 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, av_log(s, AV_LOG_VERBOSE, "Parsing '%s' - skipp not supported representation type\n", url); return 0; } - // convert selected representation to our internal struct - rep = av_mallocz(sizeof(struct representation)); - if (!rep) + + // convert selected representation to our internal struct + rep = av_mallocz(sizeof(struct representation)); + if (!rep) + return AVERROR(ENOMEM); + if (c->adaptionset_lang) { + rep->lang = av_strdup(c->adaptionset_lang); + if (!rep->lang) { + av_log(s, AV_LOG_ERROR, "alloc language memory failure\n"); + av_freep(&rep); return AVERROR(ENOMEM); - if (c->adaptionset_lang) { - rep->lang = av_strdup(c->adaptionset_lang); - if (!rep->lang) { - av_log(s, AV_LOG_ERROR, "alloc language memory failure\n"); - av_freep(&rep); - return AVERROR(ENOMEM); - } } - rep->parent = s; - representation_segmenttemplate_node = find_child_node_by_name(representation_node, "SegmentTemplate"); - representation_baseurl_node = find_child_node_by_name(representation_node, "BaseURL"); - representation_segmentlist_node = find_child_node_by_name(representation_node, "SegmentList"); - rep_id_val = xmlGetProp(representation_node, "id"); - rep_bandwidth_val = xmlGetProp(representation_node, "bandwidth"); - - baseurl_nodes[0] = mpd_baseurl_node; - baseurl_nodes[1] = period_baseurl_node; - baseurl_nodes[2] = adaptionset_baseurl_node; - baseurl_nodes[3] = representation_baseurl_node; - - ret = resolve_content_path(s, url, &c->max_url_size, baseurl_nodes, 4); - c->max_url_size = aligned(c->max_url_size - + (rep_id_val ? strlen(rep_id_val) : 0) - + (rep_bandwidth_val ? strlen(rep_bandwidth_val) : 0)); - if (ret == AVERROR(ENOMEM) || ret == 0) - goto free; - if (representation_segmenttemplate_node || fragment_template_node || period_segmenttemplate_node) { - fragment_timeline_node = NULL; - fragment_templates_tab[0] = representation_segmenttemplate_node; - fragment_templates_tab[1] = adaptionset_segmentlist_node; - fragment_templates_tab[2] = fragment_template_node; - fragment_templates_tab[3] = period_segmenttemplate_node; - fragment_templates_tab[4] = period_segmentlist_node; - - initialization_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "initialization"); - if (initialization_val) { - rep->init_section = av_mallocz(sizeof(struct fragment)); - if (!rep->init_section) { - xmlFree(initialization_val); - goto enomem; - } - c->max_url_size = aligned(c->max_url_size + strlen(initialization_val)); - rep->init_section->url = get_content_url(baseurl_nodes, 4, c->max_url_size, rep_id_val, rep_bandwidth_val, initialization_val); - xmlFree(initialization_val); - if (!rep->init_section->url) - goto enomem; - rep->init_section->size = -1; - } - media_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "media"); - if (media_val) { - c->max_url_size = aligned(c->max_url_size + strlen(media_val)); - rep->url_template = get_content_url(baseurl_nodes, 4, c->max_url_size, rep_id_val, rep_bandwidth_val, media_val); - xmlFree(media_val); - } - presentation_timeoffset_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "presentationTimeOffset"); - if (presentation_timeoffset_val) { - rep->presentation_timeoffset = (int64_t) strtoll(presentation_timeoffset_val, NULL, 10); - av_log(s, AV_LOG_TRACE, "rep->presentation_timeoffset = [%"PRId64"]\n", rep->presentation_timeoffset); - xmlFree(presentation_timeoffset_val); - } - duration_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "duration"); - if (duration_val) { - rep->fragment_duration = (int64_t) strtoll(duration_val, NULL, 10); - av_log(s, AV_LOG_TRACE, "rep->fragment_duration = [%"PRId64"]\n", rep->fragment_duration); - xmlFree(duration_val); - } - timescale_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "timescale"); - if (timescale_val) { - rep->fragment_timescale = (int64_t) strtoll(timescale_val, NULL, 10); - av_log(s, AV_LOG_TRACE, "rep->fragment_timescale = [%"PRId64"]\n", rep->fragment_timescale); - xmlFree(timescale_val); - } - startnumber_val = get_val_from_nodes_tab(fragment_templates_tab, 4, "startNumber"); - if (startnumber_val) { - rep->start_number = rep->first_seq_no = (int64_t) strtoll(startnumber_val, NULL, 10); - av_log(s, AV_LOG_TRACE, "rep->first_seq_no = [%"PRId64"]\n", rep->first_seq_no); - xmlFree(startnumber_val); - } - if (adaptionset_supplementalproperty_node) { - if (!av_strcasecmp(xmlGetProp(adaptionset_supplementalproperty_node,"schemeIdUri"), "http://dashif.org/guidelines/last-segment-number")) { - val = xmlGetProp(adaptionset_supplementalproperty_node,"value"); - if (!val) { - av_log(s, AV_LOG_ERROR, "Missing value attribute in adaptionset_supplementalproperty_node\n"); - } else { - rep->last_seq_no =(int64_t) strtoll(val, NULL, 10) - 1; - xmlFree(val); - } - } - } - - fragment_timeline_node = find_child_node_by_name(representation_segmenttemplate_node, "SegmentTimeline"); - - if (!fragment_timeline_node) - fragment_timeline_node = find_child_node_by_name(fragment_template_node, "SegmentTimeline"); - if (!fragment_timeline_node) - fragment_timeline_node = find_child_node_by_name(adaptionset_segmentlist_node, "SegmentTimeline"); - if (!fragment_timeline_node) - fragment_timeline_node = find_child_node_by_name(period_segmentlist_node, "SegmentTimeline"); - if (fragment_timeline_node) { - fragment_timeline_node = xmlFirstElementChild(fragment_timeline_node); - while (fragment_timeline_node) { - ret = parse_manifest_segmenttimeline(s, rep, fragment_timeline_node); - if (ret < 0) - goto free; - fragment_timeline_node = xmlNextElementSibling(fragment_timeline_node); - } - } - } else if (representation_baseurl_node && !representation_segmentlist_node) { - seg = av_mallocz(sizeof(struct fragment)); - if (!seg) + } + rep->parent = s; + representation_segmenttemplate_node = find_child_node_by_name(representation_node, "SegmentTemplate"); + representation_baseurl_node = find_child_node_by_name(representation_node, "BaseURL"); + representation_segmentlist_node = find_child_node_by_name(representation_node, "SegmentList"); + rep_id_val = xmlGetProp(representation_node, "id"); + rep_bandwidth_val = xmlGetProp(representation_node, "bandwidth"); + + baseurl_nodes[0] = mpd_baseurl_node; + baseurl_nodes[1] = period_baseurl_node; + baseurl_nodes[2] = adaptionset_baseurl_node; + baseurl_nodes[3] = representation_baseurl_node; + + ret = resolve_content_path(s, url, &c->max_url_size, baseurl_nodes, 4); + c->max_url_size = aligned(c->max_url_size + + (rep_id_val ? strlen(rep_id_val) : 0) + + (rep_bandwidth_val ? strlen(rep_bandwidth_val) : 0)); + if (ret == AVERROR(ENOMEM) || ret == 0) + goto free; + if (representation_segmenttemplate_node || fragment_template_node || period_segmenttemplate_node) { + fragment_timeline_node = NULL; + fragment_templates_tab[0] = representation_segmenttemplate_node; + fragment_templates_tab[1] = adaptionset_segmentlist_node; + fragment_templates_tab[2] = fragment_template_node; + fragment_templates_tab[3] = period_segmenttemplate_node; + fragment_templates_tab[4] = period_segmentlist_node; + + val = get_val_from_nodes_tab(fragment_templates_tab, 4, "initialization"); + if (val) { + rep->init_section = av_mallocz(sizeof(struct fragment)); + if (!rep->init_section) { + xmlFree(val); goto enomem; - ret = av_dynarray_add_nofree(&rep->fragments, &rep->n_fragments, seg); - if (ret < 0) { - av_free(seg); - goto free; } - seg->url = get_content_url(baseurl_nodes, 4, c->max_url_size, rep_id_val, rep_bandwidth_val, NULL); - if (!seg->url) + c->max_url_size = aligned(c->max_url_size + strlen(val)); + rep->init_section->url = get_content_url(baseurl_nodes, 4, c->max_url_size, rep_id_val, rep_bandwidth_val, val); + xmlFree(val); + if (!rep->init_section->url) goto enomem; - seg->size = -1; - } else if (representation_segmentlist_node) { - // TODO: https://www.brendanlong.com/the-structure-of-an-mpeg-dash-mpd.html - // http://www-itec.uni-klu.ac.at/dash/ddash/mpdGenerator.php?fragmentlength=15&type=full - xmlNodePtr fragmenturl_node = NULL; - segmentlists_tab[0] = representation_segmentlist_node; - segmentlists_tab[1] = adaptionset_segmentlist_node; - segmentlists_tab[2] = period_segmentlist_node; - - duration_val = get_val_from_nodes_tab(segmentlists_tab, 3, "duration"); - timescale_val = get_val_from_nodes_tab(segmentlists_tab, 3, "timescale"); - startnumber_val = get_val_from_nodes_tab(segmentlists_tab, 3, "startNumber"); - if (duration_val) { - rep->fragment_duration = (int64_t) strtoll(duration_val, NULL, 10); - av_log(s, AV_LOG_TRACE, "rep->fragment_duration = [%"PRId64"]\n", rep->fragment_duration); - xmlFree(duration_val); - } - if (timescale_val) { - rep->fragment_timescale = (int64_t) strtoll(timescale_val, NULL, 10); - av_log(s, AV_LOG_TRACE, "rep->fragment_timescale = [%"PRId64"]\n", rep->fragment_timescale); - xmlFree(timescale_val); - } - if (startnumber_val) { - rep->start_number = rep->first_seq_no = (int64_t) strtoll(startnumber_val, NULL, 10); - av_log(s, AV_LOG_TRACE, "rep->first_seq_no = [%"PRId64"]\n", rep->first_seq_no); - xmlFree(startnumber_val); + rep->init_section->size = -1; + } + val = get_val_from_nodes_tab(fragment_templates_tab, 4, "media"); + if (val) { + c->max_url_size = aligned(c->max_url_size + strlen(val)); + rep->url_template = get_content_url(baseurl_nodes, 4, c->max_url_size, rep_id_val, rep_bandwidth_val, val); + xmlFree(val); + } + val = get_val_from_nodes_tab(fragment_templates_tab, 4, "presentationTimeOffset"); + if (val) { + rep->presentation_timeoffset = (int64_t) strtoll(val, NULL, 10); + av_log(s, AV_LOG_TRACE, "rep->presentation_timeoffset = [%"PRId64"]\n", rep->presentation_timeoffset); + xmlFree(val); + } + val = get_val_from_nodes_tab(fragment_templates_tab, 4, "duration"); + if (val) { + rep->fragment_duration = (int64_t) strtoll(val, NULL, 10); + av_log(s, AV_LOG_TRACE, "rep->fragment_duration = [%"PRId64"]\n", rep->fragment_duration); + xmlFree(val); + } + val = get_val_from_nodes_tab(fragment_templates_tab, 4, "timescale"); + if (val) { + rep->fragment_timescale = (int64_t) strtoll(val, NULL, 10); + av_log(s, AV_LOG_TRACE, "rep->fragment_timescale = [%"PRId64"]\n", rep->fragment_timescale); + xmlFree(val); + } + val = get_val_from_nodes_tab(fragment_templates_tab, 4, "startNumber"); + if (val) { + rep->start_number = rep->first_seq_no = (int64_t) strtoll(val, NULL, 10); + av_log(s, AV_LOG_TRACE, "rep->first_seq_no = [%"PRId64"]\n", rep->first_seq_no); + xmlFree(val); + } + if (adaptionset_supplementalproperty_node) { + if (!av_strcasecmp(xmlGetProp(adaptionset_supplementalproperty_node,"schemeIdUri"), "http://dashif.org/guidelines/last-segment-number")) { + val = xmlGetProp(adaptionset_supplementalproperty_node,"value"); + if (!val) { + av_log(s, AV_LOG_ERROR, "Missing value attribute in adaptionset_supplementalproperty_node\n"); + } else { + rep->last_seq_no =(int64_t) strtoll(val, NULL, 10) - 1; + xmlFree(val); + } } + } - fragmenturl_node = xmlFirstElementChild(representation_segmentlist_node); - while (fragmenturl_node) { - ret = parse_manifest_segmenturlnode(s, rep, fragmenturl_node, - baseurl_nodes, - rep_id_val, - rep_bandwidth_val); - if (ret < 0) - goto free; - fragmenturl_node = xmlNextElementSibling(fragmenturl_node); - } + fragment_timeline_node = find_child_node_by_name(representation_segmenttemplate_node, "SegmentTimeline"); + if (!fragment_timeline_node) + fragment_timeline_node = find_child_node_by_name(fragment_template_node, "SegmentTimeline"); + if (!fragment_timeline_node) fragment_timeline_node = find_child_node_by_name(adaptionset_segmentlist_node, "SegmentTimeline"); - if (!fragment_timeline_node) - fragment_timeline_node = find_child_node_by_name(period_segmentlist_node, "SegmentTimeline"); - if (fragment_timeline_node) { - fragment_timeline_node = xmlFirstElementChild(fragment_timeline_node); - while (fragment_timeline_node) { - ret = parse_manifest_segmenttimeline(s, rep, fragment_timeline_node); - if (ret < 0) - goto free; - fragment_timeline_node = xmlNextElementSibling(fragment_timeline_node); - } + if (!fragment_timeline_node) + fragment_timeline_node = find_child_node_by_name(period_segmentlist_node, "SegmentTimeline"); + if (fragment_timeline_node) { + fragment_timeline_node = xmlFirstElementChild(fragment_timeline_node); + while (fragment_timeline_node) { + ret = parse_manifest_segmenttimeline(s, rep, fragment_timeline_node); + if (ret < 0) + goto free; + fragment_timeline_node = xmlNextElementSibling(fragment_timeline_node); } - } else { - av_log(s, AV_LOG_ERROR, "Unknown format of Representation node id[%s] \n", rep_id_val); + } + } else if (representation_baseurl_node && !representation_segmentlist_node) { + seg = av_mallocz(sizeof(struct fragment)); + if (!seg) + goto enomem; + ret = av_dynarray_add_nofree(&rep->fragments, &rep->n_fragments, seg); + if (ret < 0) { + av_free(seg); goto free; } + seg->url = get_content_url(baseurl_nodes, 4, c->max_url_size, rep_id_val, rep_bandwidth_val, NULL); + if (!seg->url) + goto enomem; + seg->size = -1; + } else if (representation_segmentlist_node) { + // TODO: https://www.brendanlong.com/the-structure-of-an-mpeg-dash-mpd.html + // http://www-itec.uni-klu.ac.at/dash/ddash/mpdGenerator.php?fragmentlength=15&type=full + xmlNodePtr fragmenturl_node = NULL; + segmentlists_tab[0] = representation_segmentlist_node; + segmentlists_tab[1] = adaptionset_segmentlist_node; + segmentlists_tab[2] = period_segmentlist_node; + + val = get_val_from_nodes_tab(segmentlists_tab, 3, "duration"); + if (val) { + rep->fragment_duration = (int64_t) strtoll(val, NULL, 10); + av_log(s, AV_LOG_TRACE, "rep->fragment_duration = [%"PRId64"]\n", rep->fragment_duration); + xmlFree(val); + } + val = get_val_from_nodes_tab(segmentlists_tab, 3, "timescale"); + if (val) { + rep->fragment_timescale = (int64_t) strtoll(val, NULL, 10); + av_log(s, AV_LOG_TRACE, "rep->fragment_timescale = [%"PRId64"]\n", rep->fragment_timescale); + xmlFree(val); + } + val = get_val_from_nodes_tab(segmentlists_tab, 3, "startNumber"); + if (val) { + rep->start_number = rep->first_seq_no = (int64_t) strtoll(val, NULL, 10); + av_log(s, AV_LOG_TRACE, "rep->first_seq_no = [%"PRId64"]\n", rep->first_seq_no); + xmlFree(val); + } - if (rep->fragment_duration > 0 && !rep->fragment_timescale) - rep->fragment_timescale = 1; - rep->bandwidth = rep_bandwidth_val ? atoi(rep_bandwidth_val) : 0; - strncpy(rep->id, rep_id_val ? rep_id_val : "", sizeof(rep->id)); - rep->framerate = av_make_q(0, 0); - if (type == AVMEDIA_TYPE_VIDEO) { - char *rep_framerate_val = xmlGetProp(representation_node, "frameRate"); - if (rep_framerate_val) { - ret = av_parse_video_rate(&rep->framerate, rep_framerate_val); - if (ret < 0) - av_log(s, AV_LOG_VERBOSE, "Ignoring invalid frame rate '%s'\n", rep_framerate_val); - xmlFree(rep_framerate_val); - } - } + fragmenturl_node = xmlFirstElementChild(representation_segmentlist_node); + while (fragmenturl_node) { + ret = parse_manifest_segmenturlnode(s, rep, fragmenturl_node, + baseurl_nodes, + rep_id_val, + rep_bandwidth_val); + if (ret < 0) + goto free; + fragmenturl_node = xmlNextElementSibling(fragmenturl_node); + } - switch (type) { - case AVMEDIA_TYPE_VIDEO: - ret = av_dynarray_add_nofree(&c->videos, &c->n_videos, rep); - break; - case AVMEDIA_TYPE_AUDIO: - ret = av_dynarray_add_nofree(&c->audios, &c->n_audios, rep); - break; - case AVMEDIA_TYPE_SUBTITLE: - ret = av_dynarray_add_nofree(&c->subtitles, &c->n_subtitles, rep); - break; + fragment_timeline_node = find_child_node_by_name(adaptionset_segmentlist_node, "SegmentTimeline"); + if (!fragment_timeline_node) + fragment_timeline_node = find_child_node_by_name(period_segmentlist_node, "SegmentTimeline"); + if (fragment_timeline_node) { + fragment_timeline_node = xmlFirstElementChild(fragment_timeline_node); + while (fragment_timeline_node) { + ret = parse_manifest_segmenttimeline(s, rep, fragment_timeline_node); + if (ret < 0) + goto free; + fragment_timeline_node = xmlNextElementSibling(fragment_timeline_node); } + } + } else { + av_log(s, AV_LOG_ERROR, "Unknown format of Representation node id[%s] \n", rep_id_val); + goto free; + } + + if (rep->fragment_duration > 0 && !rep->fragment_timescale) + rep->fragment_timescale = 1; + rep->bandwidth = rep_bandwidth_val ? atoi(rep_bandwidth_val) : 0; + strncpy(rep->id, rep_id_val ? rep_id_val : "", sizeof(rep->id)); + rep->framerate = av_make_q(0, 0); + if (type == AVMEDIA_TYPE_VIDEO) { + char *rep_framerate_val = xmlGetProp(representation_node, "frameRate"); + if (rep_framerate_val) { + ret = av_parse_video_rate(&rep->framerate, rep_framerate_val); if (ret < 0) - goto free; + av_log(s, AV_LOG_VERBOSE, "Ignoring invalid frame rate '%s'\n", rep_framerate_val); + xmlFree(rep_framerate_val); + } + } + + switch (type) { + case AVMEDIA_TYPE_VIDEO: + ret = av_dynarray_add_nofree(&c->videos, &c->n_videos, rep); + break; + case AVMEDIA_TYPE_AUDIO: + ret = av_dynarray_add_nofree(&c->audios, &c->n_audios, rep); + break; + case AVMEDIA_TYPE_SUBTITLE: + ret = av_dynarray_add_nofree(&c->subtitles, &c->n_subtitles, rep); + break; + } + if (ret < 0) + goto free; end: if (rep_id_val) @@ -1901,11 +1896,8 @@ static int reopen_demux_for_component(AVFormatContext *s, struct representation pls->ctx = NULL; goto fail; } - if (c->is_live) { - ffio_init_context(&pls->pb, avio_ctx_buffer , INITIAL_BUFFER_SIZE, 0, pls, read_data, NULL, NULL); - } else { - ffio_init_context(&pls->pb, avio_ctx_buffer , INITIAL_BUFFER_SIZE, 0, pls, read_data, NULL, seek_data); - } + ffio_init_context(&pls->pb, avio_ctx_buffer , INITIAL_BUFFER_SIZE, 0, + pls, read_data, NULL, c->is_live ? NULL : seek_data); pls->pb.seekable = 0; if ((ret = ff_copy_whiteblacklists(pls->ctx, s)) < 0) @@ -2119,45 +2111,45 @@ static int dash_read_header(AVFormatContext *s) } /* Create a program */ - program = av_new_program(s, 0); - if (!program) { - ret = AVERROR(ENOMEM); - goto fail; - } + program = av_new_program(s, 0); + if (!program) { + ret = AVERROR(ENOMEM); + goto fail; + } - for (i = 0; i < c->n_videos; i++) { - rep = c->videos[i]; - av_program_add_stream_index(s, 0, rep->stream_index); - rep->assoc_stream = s->streams[rep->stream_index]; - if (rep->bandwidth > 0) - av_dict_set_int(&rep->assoc_stream->metadata, "variant_bitrate", rep->bandwidth, 0); - if (rep->id[0]) - av_dict_set(&rep->assoc_stream->metadata, "id", rep->id, 0); - } - for (i = 0; i < c->n_audios; i++) { - rep = c->audios[i]; - av_program_add_stream_index(s, 0, rep->stream_index); - rep->assoc_stream = s->streams[rep->stream_index]; - if (rep->bandwidth > 0) - av_dict_set_int(&rep->assoc_stream->metadata, "variant_bitrate", rep->bandwidth, 0); - if (rep->id[0]) - av_dict_set(&rep->assoc_stream->metadata, "id", rep->id, 0); - if (rep->lang) { - av_dict_set(&rep->assoc_stream->metadata, "language", rep->lang, 0); - av_freep(&rep->lang); - } + for (i = 0; i < c->n_videos; i++) { + rep = c->videos[i]; + av_program_add_stream_index(s, 0, rep->stream_index); + rep->assoc_stream = s->streams[rep->stream_index]; + if (rep->bandwidth > 0) + av_dict_set_int(&rep->assoc_stream->metadata, "variant_bitrate", rep->bandwidth, 0); + if (rep->id[0]) + av_dict_set(&rep->assoc_stream->metadata, "id", rep->id, 0); + } + for (i = 0; i < c->n_audios; i++) { + rep = c->audios[i]; + av_program_add_stream_index(s, 0, rep->stream_index); + rep->assoc_stream = s->streams[rep->stream_index]; + if (rep->bandwidth > 0) + av_dict_set_int(&rep->assoc_stream->metadata, "variant_bitrate", rep->bandwidth, 0); + if (rep->id[0]) + av_dict_set(&rep->assoc_stream->metadata, "id", rep->id, 0); + if (rep->lang) { + av_dict_set(&rep->assoc_stream->metadata, "language", rep->lang, 0); + av_freep(&rep->lang); } - for (i = 0; i < c->n_subtitles; i++) { - rep = c->subtitles[i]; - av_program_add_stream_index(s, 0, rep->stream_index); - rep->assoc_stream = s->streams[rep->stream_index]; - if (rep->id[0]) - av_dict_set(&rep->assoc_stream->metadata, "id", rep->id, 0); - if (rep->lang) { - av_dict_set(&rep->assoc_stream->metadata, "language", rep->lang, 0); - av_freep(&rep->lang); - } + } + for (i = 0; i < c->n_subtitles; i++) { + rep = c->subtitles[i]; + av_program_add_stream_index(s, 0, rep->stream_index); + rep->assoc_stream = s->streams[rep->stream_index]; + if (rep->id[0]) + av_dict_set(&rep->assoc_stream->metadata, "id", rep->id, 0); + if (rep->lang) { + av_dict_set(&rep->assoc_stream->metadata, "language", rep->lang, 0); + av_freep(&rep->lang); } + } return 0; fail: