From patchwork Tue Oct 18 18:23:28 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregor Riepl X-Patchwork-Id: 38808 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp2246210pzb; Tue, 18 Oct 2022 11:23:44 -0700 (PDT) X-Google-Smtp-Source: AMsMyM67mmQ2dWwgNKBkEqQyv5c4E23goIrMLxeFvBaVcrhhEOjeSL7Ps1tkQUQ9P3pUBkvDjDqk X-Received: by 2002:a05:6402:1e88:b0:45d:237f:f468 with SMTP id f8-20020a0564021e8800b0045d237ff468mr3732120edf.45.1666117423726; Tue, 18 Oct 2022 11:23:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1666117423; cv=none; d=google.com; s=arc-20160816; b=P7Z2YI6HC9VcG7YDLjTObXeCmq3/W1D7rEwpdgLf9dcCS46GeIxWNbaikAh1Zvgcy/ NqfwaWmaxySkXYeM/FO8t0iQyVIcRSM1sPHiSrX8QJALQXpoOiwPH6aX5cYTAXFnagMK TKitTV03UEL4hBXQpwwsTn04ycW928xfe7cYlzGhngAoWcpa5GyNP+61v8+u1YfBF2BO epRuyM/Y1tY5QpEyPI6PrMRAlnM7B4cgZ6p36PdB1XeJ/7YkxR/NnTLfWQsbVQFoLb6M ADUZhRxJCmFTmqFKTxsFfz37ptEVESc01XomKdtdFiN0+4IC3Uw/XtNFafJKQDcC3xdd hT2Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:in-reply-to:from:references:to:content-language :user-agent:mime-version:date:message-id:dkim-signature:delivered-to; bh=U5SFlHhgSVWiGHushxZRee/ulGR8dSHffpkoYKYtoXQ=; b=P7I1fXMGvktoOGdUFWi6QFy3JZpeFmrBRiwARIV4JCi5KJspNtAGkdlVD7gowMHEm2 h9WXLzT+ylrP+TWIoCEulDe7XCQXBSSpHDxTRxwYoK7zK0zUeQl/GVk6nmV+zDLP1Dgd cRvRcktuHFeyaJ+74UiT/xw52LpDJtuiEsD+hpoGoZLDtZtHCYkt/Eibpwzw7iNn3kmW Z0LaggoP/i68O0eOsEQHi4PniZW72FKJct/jXn73QgSGhQyRcmwU/57EnaACbF7eZhaU 4pt+OyuDiy2SKaw78YEhHahS8PAZoJP/J0NLfcAQL8NRDSgyjDxBw1/BC58e6lOSCcdV gvcw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=KhTV36bj; 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 fk24-20020a056402399800b0045cafc51fbfsi12463486edb.525.2022.10.18.11.23.42; Tue, 18 Oct 2022 11:23:43 -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=20210112 header.b=KhTV36bj; 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 9AB8068BD21; Tue, 18 Oct 2022 21:23:38 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-ej1-f41.google.com (mail-ej1-f41.google.com [209.85.218.41]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id A9EC868BC9B for ; Tue, 18 Oct 2022 21:23:32 +0300 (EEST) Received: by mail-ej1-f41.google.com with SMTP id bj12so34301177ejb.13 for ; Tue, 18 Oct 2022 11:23:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:in-reply-to:from:references:to :content-language:subject:user-agent:mime-version:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=hofh49tYgEAHz5/R9rpi+3nuZOAI1TX8zqA+X+XT9/g=; b=KhTV36bj7159T7DPBkyJbUVyiRoT74TMkarKJgr3JJQlk6xvBMRcOg1evjVwZoSdsS 5gaNU97931vLqceNhMVuG+bqmr0iJD5VYTXvrBi9ad9PZ0JnGQ6vuwXUbKkkTO6eiFCO UqQ5tEuUq5I3yXGbrYqPWA7TbdH51Ehw/iFxCtNq4FyhPcqVlOzrTT5xEKlrJ6lj3ou+ HP/SCRPuaNwKHmJc1XbIIVAHDcKOD+0Pngw8Scrqhgg8qwKeK5Jnz0gVdEHmgKLHz/aa 7OP9oYLnqDGbc2wzkUI9fQOeffJP1d84r73OKDAoWBMZjHTzcGudIrlu5FHyvZo5ZwbD FMQg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:in-reply-to:from:references:to :content-language:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=hofh49tYgEAHz5/R9rpi+3nuZOAI1TX8zqA+X+XT9/g=; b=nqaZcwScrMktM4Njw6d8gmEjjh4rQpfgVfkyio19h/e8IWHIzLbvJEy6lrlkqc9Sjw MH8IjZRafdpFdiXtMzLkLlP7/y3o6GyAmUraW+dBosGVCcfg4UeD0rSVueImEMLCJz7i RUyah+3tni5bmbmVwBAsKGJLbu/6WdhQKd4nJv98XKEb6Zzi35GMlj++yx9t+yzsh25q 8Z3ypc8Ey/uO/4oq+UGEm7bIjWJjihPQVuCrCEqTd/8lNg91z82F2cMGs90Oc0IoB9pC OKDS3O7kU9wHXRjMu4Lb63UIv9Ef6VUOFIKadQd8SF67sJhuwQfP7Dh27Rka6I5hz6he Kb/w== X-Gm-Message-State: ACrzQf3NJ26VNS/sJDSkEyHDnPfW4l2MlzlROuhue+mlcByNZ32SaGDk PmRjFrswd2t9s+DnNH0o82mOC3Qh9ik= X-Received: by 2002:a17:906:eecb:b0:73c:5bcb:8eb3 with SMTP id wu11-20020a170906eecb00b0073c5bcb8eb3mr3439611ejb.284.1666117411812; Tue, 18 Oct 2022 11:23:31 -0700 (PDT) Received: from [100.75.122.69] ([213.55.221.51]) by smtp.googlemail.com with ESMTPSA id k13-20020a17090627cd00b0077826b92d99sm7909502ejc.12.2022.10.18.11.23.30 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 18 Oct 2022 11:23:31 -0700 (PDT) Message-ID: <30896212-1aca-4cb6-c415-5f86c98dc6a3@gmail.com> Date: Tue, 18 Oct 2022 20:23:28 +0200 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.3.2 Content-Language: en-US To: ffmpeg-devel@ffmpeg.org References: From: Gregor Riepl In-Reply-To: Subject: [FFmpeg-devel] [PATCH v2] avformat/dashdec: Differentiate unassigned and zero attributes X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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" X-TUID: hMnhKMC1M0X3 This fixes an issue where a timestamp attribute may have a valid zero value (the UNIX epoch 1970-01-01T00:00:00), but is misinterpreted by dashdec as being unassigned. This changes the logic that calculates segment numbers and makes the stream undecodable by dashdec. The fix originally posted to the issue tracker was incorrect and changed other parts of the segment calculation logic. With this patch, only the interpretation of the attributes is changed. Some warnings are added to account for potential errors in manifests. v2 change: Use int, 0 and 1 instead of C99 stdbool. This similar to what's done in fftools/ffmpeg_opt.c. Fixes: #8522 Signed-off-by: Gregor Riepl --- libavformat/dashdec.c | 209 ++++++++++++++++++++++++++++++++---------- 1 file changed, 161 insertions(+), 48 deletions(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index 29d4680c68..df5d453c5a 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -129,21 +129,34 @@ typedef struct DASHContext { struct representation **subtitles; /* MediaPresentationDescription Attribute */ - uint64_t media_presentation_duration; - uint64_t suggested_presentation_delay; - uint64_t availability_start_time; - uint64_t availability_end_time; - uint64_t publish_time; - uint64_t minimum_update_period; - uint64_t time_shift_buffer_depth; - uint64_t min_buffer_time; + uint64_t media_presentation_duration_value; + uint64_t suggested_presentation_delay_value; + uint64_t availability_start_time_value; + uint64_t availability_end_time_value; + uint64_t publish_time_value; + uint64_t minimum_update_period_value; + uint64_t time_shift_buffer_depth_value; + uint64_t min_buffer_time_value; /* Period Attribute */ - uint64_t period_duration; - uint64_t period_start; + uint64_t period_duration_value; + uint64_t period_start_value; /* AdaptationSet Attribute */ - char *adaptionset_lang; + char *adaptionset_lang_value; + + /* Attribute valid flags (true if the attribute exists in the XML manifest) */ + int media_presentation_duration_assigned; + int suggested_presentation_delay_assigned; + int availability_start_time_assigned; + int availability_end_time_assigned; + int publish_time_assigned; + int minimum_update_period_assigned; + int time_shift_buffer_depth_assigned; + int min_buffer_time_assigned; + int period_duration_assigned; + int period_start_assigned; + int adaptionset_lang_assigned; int is_live; AVIOInterruptCB *interrupt_callback; @@ -867,8 +880,8 @@ static int parse_manifest_representation(AVFormatContext *s, const char *url, rep = av_mallocz(sizeof(struct representation)); if (!rep) return AVERROR(ENOMEM); - if (c->adaptionset_lang) { - rep->lang = av_strdup(c->adaptionset_lang); + if (c->adaptionset_lang_assigned) { + rep->lang = av_strdup(c->adaptionset_lang_value); if (!rep->lang) { av_log(s, AV_LOG_ERROR, "alloc language memory failure\n"); av_freep(&rep); @@ -1106,7 +1119,10 @@ static int parse_manifest_adaptationset_attr(AVFormatContext *s, xmlNodePtr adap av_log(s, AV_LOG_WARNING, "Cannot get AdaptionSet\n"); return AVERROR(EINVAL); } - c->adaptionset_lang = xmlGetProp(adaptionset_node, "lang"); + c->adaptionset_lang_value = xmlGetProp(adaptionset_node, "lang"); + if (c->adaptionset_lang_value) { + c->adaptionset_lang_assigned = 1; + } return 0; } @@ -1162,8 +1178,9 @@ static int parse_manifest_adaptationset(AVFormatContext *s, const char *url, } err: - xmlFree(c->adaptionset_lang); - c->adaptionset_lang = NULL; + xmlFree(c->adaptionset_lang_value); + c->adaptionset_lang_value = NULL; + c->adaptionset_lang_assigned = 0; return ret; } @@ -1273,29 +1290,37 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in) val = xmlGetProp(node, attr->name); if (!av_strcasecmp(attr->name, "availabilityStartTime")) { - c->availability_start_time = get_utc_date_time_insec(s, val); - av_log(s, AV_LOG_TRACE, "c->availability_start_time = [%"PRId64"]\n", c->availability_start_time); + c->availability_start_time_value = get_utc_date_time_insec(s, val); + c->availability_start_time_assigned = 1; + av_log(s, AV_LOG_TRACE, "c->availability_start_time = [%"PRId64"]\n", c->availability_start_time_value); } else if (!av_strcasecmp(attr->name, "availabilityEndTime")) { - c->availability_end_time = get_utc_date_time_insec(s, val); - av_log(s, AV_LOG_TRACE, "c->availability_end_time = [%"PRId64"]\n", c->availability_end_time); + c->availability_end_time_value = get_utc_date_time_insec(s, val); + c->availability_end_time_assigned = 1; + av_log(s, AV_LOG_TRACE, "c->availability_end_time = [%"PRId64"]\n", c->availability_end_time_value); } else if (!av_strcasecmp(attr->name, "publishTime")) { - c->publish_time = get_utc_date_time_insec(s, val); - av_log(s, AV_LOG_TRACE, "c->publish_time = [%"PRId64"]\n", c->publish_time); + c->publish_time_value = get_utc_date_time_insec(s, val); + c->publish_time_assigned = 1; + av_log(s, AV_LOG_TRACE, "c->publish_time = [%"PRId64"]\n", c->publish_time_value); } else if (!av_strcasecmp(attr->name, "minimumUpdatePeriod")) { - c->minimum_update_period = get_duration_insec(s, val); - av_log(s, AV_LOG_TRACE, "c->minimum_update_period = [%"PRId64"]\n", c->minimum_update_period); + c->minimum_update_period_value = get_duration_insec(s, val); + c->minimum_update_period_assigned = 1; + av_log(s, AV_LOG_TRACE, "c->minimum_update_period = [%"PRId64"]\n", c->minimum_update_period_value); } else if (!av_strcasecmp(attr->name, "timeShiftBufferDepth")) { - c->time_shift_buffer_depth = get_duration_insec(s, val); - av_log(s, AV_LOG_TRACE, "c->time_shift_buffer_depth = [%"PRId64"]\n", c->time_shift_buffer_depth); + c->time_shift_buffer_depth_value = get_duration_insec(s, val); + c->time_shift_buffer_depth_assigned = 1; + av_log(s, AV_LOG_TRACE, "c->time_shift_buffer_depth = [%"PRId64"]\n", c->time_shift_buffer_depth_value); } else if (!av_strcasecmp(attr->name, "minBufferTime")) { - c->min_buffer_time = get_duration_insec(s, val); - av_log(s, AV_LOG_TRACE, "c->min_buffer_time = [%"PRId64"]\n", c->min_buffer_time); + c->min_buffer_time_value = get_duration_insec(s, val); + c->min_buffer_time_assigned = 1; + av_log(s, AV_LOG_TRACE, "c->min_buffer_time = [%"PRId64"]\n", c->min_buffer_time_value); } else if (!av_strcasecmp(attr->name, "suggestedPresentationDelay")) { - c->suggested_presentation_delay = get_duration_insec(s, val); - av_log(s, AV_LOG_TRACE, "c->suggested_presentation_delay = [%"PRId64"]\n", c->suggested_presentation_delay); + c->suggested_presentation_delay_value = get_duration_insec(s, val); + c->suggested_presentation_delay_assigned = 1; + av_log(s, AV_LOG_TRACE, "c->suggested_presentation_delay = [%"PRId64"]\n", c->suggested_presentation_delay_value); } else if (!av_strcasecmp(attr->name, "mediaPresentationDuration")) { - c->media_presentation_duration = get_duration_insec(s, val); - av_log(s, AV_LOG_TRACE, "c->media_presentation_duration = [%"PRId64"]\n", c->media_presentation_duration); + c->media_presentation_duration_value = get_duration_insec(s, val); + c->media_presentation_duration_assigned = 1; + av_log(s, AV_LOG_TRACE, "c->media_presentation_duration = [%"PRId64"]\n", c->media_presentation_duration_value); } attr = attr->next; xmlFree(val); @@ -1325,12 +1350,30 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in) attr = attr->next; xmlFree(val); } - if ((period_duration_sec) >= (c->period_duration)) { + if (c->period_duration_assigned) { + if ((period_duration_sec) >= (c->period_duration_value)) { + period_node = node; + c->period_duration_value = period_duration_sec; + c->period_start_value = period_start_sec; + c->period_start_assigned = 1; + if (c->period_start_value > 0) { + c->media_presentation_duration_value = c->period_duration_value; + c->media_presentation_duration_assigned = 1; + } + } else { + av_log(s, AV_LOG_VERBOSE, "previous period_duration is larger than new value. ignoring.\n"); + } + } else { + av_log(s, AV_LOG_VERBOSE, "period_duration attribute unset - updating from calculated value.\n"); period_node = node; - c->period_duration = period_duration_sec; - c->period_start = period_start_sec; - if (c->period_start > 0) - c->media_presentation_duration = c->period_duration; + c->period_duration_value = period_duration_sec; + c->period_duration_assigned = 1; + c->period_start_value = period_start_sec; + c->period_start_assigned = 1; + if (c->period_start_value > 0) { + c->media_presentation_duration_value = c->period_duration_value; + c->media_presentation_duration_assigned = 1; + } } } else if (!av_strcasecmp(node->name, "ProgramInformation")) { parse_programinformation(s, node); @@ -1391,15 +1434,54 @@ static int64_t calc_cur_seg_no(AVFormatContext *s, struct representation *pls) } else if (pls->fragment_duration){ av_log(s, AV_LOG_TRACE, "in fragment_duration mode fragment_timescale = %"PRId64", presentation_timeoffset = %"PRId64"\n", pls->fragment_timescale, pls->presentation_timeoffset); if (pls->presentation_timeoffset) { - num = pls->first_seq_no + (((get_current_time_in_sec() - c->availability_start_time) * pls->fragment_timescale)-pls->presentation_timeoffset) / pls->fragment_duration - c->min_buffer_time; - } else if (c->publish_time > 0 && !c->availability_start_time) { - if (c->min_buffer_time) { - num = pls->first_seq_no + (((c->publish_time + pls->fragment_duration) - c->suggested_presentation_delay) * pls->fragment_timescale) / pls->fragment_duration - c->min_buffer_time; + if (c->availability_start_time_assigned && c->min_buffer_time_assigned) { + num = pls->first_seq_no + (((get_current_time_in_sec() - c->availability_start_time_value) * pls->fragment_timescale)-pls->presentation_timeoffset) / pls->fragment_duration - c->min_buffer_time_assigned; } else { - num = pls->first_seq_no + (((c->publish_time - c->time_shift_buffer_depth + pls->fragment_duration) - c->suggested_presentation_delay) * pls->fragment_timescale) / pls->fragment_duration; + av_log(s, AV_LOG_WARNING, "availability_start_time and/or min_buffer_time attributes unset - using zero values. segment numbers may be incorrect.\n"); + if (c->availability_start_time_assigned) { + num = pls->first_seq_no + (((get_current_time_in_sec() - c->availability_start_time_value) * pls->fragment_timescale)-pls->presentation_timeoffset) / pls->fragment_duration; + } else if (c->min_buffer_time_assigned) { + num = pls->first_seq_no + (((get_current_time_in_sec()) * pls->fragment_timescale)-pls->presentation_timeoffset) / pls->fragment_duration - c->min_buffer_time_value; + } else { + num = pls->first_seq_no + (((get_current_time_in_sec()) * pls->fragment_timescale)-pls->presentation_timeoffset) / pls->fragment_duration; + } + } + } else if (c->publish_time_assigned && c->publish_time_value > 0 && !c->availability_start_time_assigned) { + // FIXME is publish_time_value > 0 a required condition, or are we only checking for existence of the attribute? + if (c->min_buffer_time_assigned) { + if (c->suggested_presentation_delay_assigned) { + num = pls->first_seq_no + (((c->publish_time_value + pls->fragment_duration) - c->suggested_presentation_delay_value) * pls->fragment_timescale) / pls->fragment_duration - c->min_buffer_time_value; + } else { + av_log(s, AV_LOG_WARNING, "suggested_presentation_delay attribute unset - using zero value. segment numbers may be incorrect.\n"); + num = pls->first_seq_no + ((c->publish_time_value + pls->fragment_duration) * pls->fragment_timescale) / pls->fragment_duration - c->min_buffer_time_value; + } + } else { + if (c->time_shift_buffer_depth_assigned && c->suggested_presentation_delay_assigned) { + num = pls->first_seq_no + (((c->publish_time_value - c->time_shift_buffer_depth_value + pls->fragment_duration) - c->suggested_presentation_delay_value) * pls->fragment_timescale) / pls->fragment_duration; + } else { + av_log(s, AV_LOG_WARNING, "time_shift_buffer_depth and/or suggested_presentation_delay attributes unset - using zero values. segment numbers may be incorrect.\n"); + if (c->time_shift_buffer_depth_assigned) { + num = pls->first_seq_no + ((c->publish_time_value - c->time_shift_buffer_depth_value + pls->fragment_duration) * pls->fragment_timescale) / pls->fragment_duration; + } else if (c->suggested_presentation_delay_assigned) { + num = pls->first_seq_no + (((c->publish_time_value + pls->fragment_duration) - c->suggested_presentation_delay_value) * pls->fragment_timescale) / pls->fragment_duration; + } else { + num = pls->first_seq_no + ((c->publish_time_value + pls->fragment_duration) * pls->fragment_timescale) / pls->fragment_duration; + } + } } } else { - num = pls->first_seq_no + (((get_current_time_in_sec() - c->availability_start_time) - c->suggested_presentation_delay) * pls->fragment_timescale) / pls->fragment_duration; + if (c->availability_start_time_assigned && c->suggested_presentation_delay_assigned) { + num = pls->first_seq_no + (((get_current_time_in_sec() - c->availability_start_time_value) - c->suggested_presentation_delay_value) * pls->fragment_timescale) / pls->fragment_duration; + } else { + av_log(s, AV_LOG_WARNING, "availability_start_time and/or suggested_presentation_delay attributes unset - using zero values. segment numbers may be incorrect.\n"); + if (c->availability_start_time_assigned) { + num = pls->first_seq_no + ((get_current_time_in_sec() - c->availability_start_time_value) * pls->fragment_timescale) / pls->fragment_duration; + } else if (c->suggested_presentation_delay_assigned) { + num = pls->first_seq_no + ((get_current_time_in_sec() - c->suggested_presentation_delay_value) * pls->fragment_timescale) / pls->fragment_duration; + } else { + num = pls->first_seq_no + (get_current_time_in_sec() * pls->fragment_timescale) / pls->fragment_duration; + } + } } } } else { @@ -1415,7 +1497,18 @@ static int64_t calc_min_seg_no(AVFormatContext *s, struct representation *pls) if (c->is_live && pls->fragment_duration) { av_log(s, AV_LOG_TRACE, "in live mode\n"); - num = pls->first_seq_no + (((get_current_time_in_sec() - c->availability_start_time) - c->time_shift_buffer_depth) * pls->fragment_timescale) / pls->fragment_duration; + if (c->availability_start_time_assigned && c->time_shift_buffer_depth_assigned) { + num = pls->first_seq_no + (((get_current_time_in_sec() - c->availability_start_time_value) - c->time_shift_buffer_depth_value) * pls->fragment_timescale) / pls->fragment_duration; + } else { + av_log(s, AV_LOG_WARNING, "availability_start_time and/or time_shift_buffer_depth attributes unset - using zero values. segment numbers may be incorrect.\n"); + if (c->availability_start_time_assigned) { + num = pls->first_seq_no + ((get_current_time_in_sec() - c->availability_start_time_value) * pls->fragment_timescale) / pls->fragment_duration; + } else if (c->time_shift_buffer_depth_assigned) { + num = pls->first_seq_no + ((get_current_time_in_sec() - c->time_shift_buffer_depth_value) * pls->fragment_timescale) / pls->fragment_duration; + } else { + num = pls->first_seq_no + (get_current_time_in_sec() * pls->fragment_timescale) / pls->fragment_duration; + } + } } else { num = pls->first_seq_no; } @@ -1434,15 +1527,30 @@ static int64_t calc_max_seg_no(struct representation *pls, DASHContext *c) for (i = 0; i < pls->n_timelines; i++) { if (pls->timelines[i]->repeat == -1) { int length_of_each_segment = pls->timelines[i]->duration / pls->fragment_timescale; - num = c->period_duration / length_of_each_segment; + if (c->period_duration_assigned) { + num = c->period_duration_value / length_of_each_segment; + } else { + av_log(NULL, AV_LOG_WARNING, "period_duration attribute unset - using zero value. segment numbers may be incorrect.\n"); + num = 0; + } } else { num += pls->timelines[i]->repeat; } } } else if (c->is_live && pls->fragment_duration) { - num = pls->first_seq_no + (((get_current_time_in_sec() - c->availability_start_time)) * pls->fragment_timescale) / pls->fragment_duration; + if (c->availability_start_time_assigned) { + num = pls->first_seq_no + (((get_current_time_in_sec() - c->availability_start_time_value)) * pls->fragment_timescale) / pls->fragment_duration; + } else { + av_log(NULL, AV_LOG_WARNING, "availability_start_time attribute unset - using zero value. segment numbers may be incorrect.\n"); + num = pls->first_seq_no + (get_current_time_in_sec() * pls->fragment_timescale) / pls->fragment_duration; + } } else if (pls->fragment_duration) { - num = pls->first_seq_no + av_rescale_rnd(1, c->media_presentation_duration * pls->fragment_timescale, pls->fragment_duration, AV_ROUND_UP); + if (c->media_presentation_duration_assigned) { + num = pls->first_seq_no + av_rescale_rnd(1, c->media_presentation_duration_value * pls->fragment_timescale, pls->fragment_duration, AV_ROUND_UP); + } else { + av_log(NULL, AV_LOG_WARNING, "media_presentation_duration attribute unset - using zero value. segment numbers may be incorrect.\n"); + num = pls->first_seq_no + av_rescale_rnd(1, 0, pls->fragment_duration, AV_ROUND_UP); + } } return num; @@ -2040,7 +2148,12 @@ static int dash_read_header(AVFormatContext *s) /* If this isn't a live stream, fill the total duration of the * stream. */ if (!c->is_live) { - s->duration = (int64_t) c->media_presentation_duration * AV_TIME_BASE; + if (c->media_presentation_duration_assigned) { + s->duration = (int64_t) c->media_presentation_duration_value * AV_TIME_BASE; + } else { + av_log(NULL, AV_LOG_WARNING, "media_presentation_duration attribute unset - using zero value. segment numbers may be incorrect.\n"); + s->duration = 0; + } } else { av_dict_set(&c->avio_opts, "seekable", "0", 0); }