From patchwork Fri Oct 7 21:31:23 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gregor Riepl X-Patchwork-Id: 38615 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a21:789c:b0:9c:c2cd:5584 with SMTP id bf28csp226674pzc; Fri, 7 Oct 2022 14:31:38 -0700 (PDT) X-Google-Smtp-Source: AMsMyM5XMRQzHD0Gi/DEcdNswL1FW4eTI/VLoV6QSAR4OmhAD6dQVqzQo9MyyYGdLiXXsGiQvfh/ X-Received: by 2002:a17:907:7fa3:b0:782:3034:cbc5 with SMTP id qk35-20020a1709077fa300b007823034cbc5mr5590129ejc.96.1665178297571; Fri, 07 Oct 2022 14:31:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665178297; cv=none; d=google.com; s=arc-20160816; b=VBvoKYqFXY630aWgXF8xULpReGiuUcDRlntylKznYluXWVJiT/eWXF9b1IGvKnUEiS VIDzmeFR2HDyMS7DfzeDVZz/MbKA4sC8F7iRCEedY/7DyLlYch0ypEbHxypBuWSsulIg iYmJEQgD9xdrL9yn/6DLtGtqH9dyfSBVQq0w0F9OMsTZJ1VuwrmKc6nO285qJo/N85K2 fskFUBASTPmk5UizpLXq/pJsp+o8pQZdFynaR4DTHYm3GTSGibx+QKoOBm30Cizc8Mvi tb4lBtlOmaQrSp1/GYs7wXC9IKhiVe8fO9MShv8gOXPvKDS9InKHhj3DY7aZmhAG8LOd qlZA== 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:from:content-language:to:user-agent:mime-version :date:message-id:dkim-signature:delivered-to; bh=rqvu1mUiztYVaArMxtBvMkW0baqAllxFLdsrDyyIkwQ=; b=OHuDV441dgP3GJQ4GVSSKrShGQDWccJuPtRA58LTX2q5BnzI/hotc5nQFZ3+LF3QRW 1vzDv4OCWn+qFj7YTrQ6h/WEOLBOK1h0jYqgPuMFC8/Bu+sWBkJF3I10jc/XljeeeRth o6aE45KS1o4yabwsN2NnGDGuuuJfCPta8tiCNRx4WkSMj/mUYhHSPxi4FWUAA2xJgzvv /HIv+WJoW65ST/MBnNLsOzNTLQKsJAuthSz30x6K3rN+3pdL9thZHNepI+l7hoBF4b0K +u08Bs6rWU3CSfdw15oaKruotFClNC4fR7yfp9aQJLlISsBbDqZFAObB+fOs83Xg6sGp //Qw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=oAcgwqot; 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 f9-20020aa7d849000000b00458cb72c57csi2714682eds.392.2022.10.07.14.31.36; Fri, 07 Oct 2022 14:31:37 -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=oAcgwqot; 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 1C95F68BA99; Sat, 8 Oct 2022 00:31:33 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-ej1-f54.google.com (mail-ej1-f54.google.com [209.85.218.54]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 8220968BA36 for ; Sat, 8 Oct 2022 00:31:26 +0300 (EEST) Received: by mail-ej1-f54.google.com with SMTP id k2so13962961ejr.2 for ; Fri, 07 Oct 2022 14:31:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:subject:from:content-language:to :user-agent:mime-version:date:message-id:from:to:cc:subject:date :message-id:reply-to; bh=44KaKTmQ+wy7JmP9bH6goWfSbO7HvYgDnWgDbRD/t58=; b=oAcgwqote5pbxcDth2Z0Ych6eyYqe+UZbgzuH3N41tw+6zfKkPGwMvqPx4k/W3r4kv R0OFxobOgmTP91NgFOPnC8xBCIMHELWjgWicSK+ja3TXyq3sLMGDTebaaVBKm1TLdbfg I1VCjxBgxOHBeABMd3NXivDy09KvG0Shz3IQK3Wb/Xc4CTKuX1ZQV7qBH4tKQsnyFTuF SlTrojA80atwtu0h0gkLe87eJe+HNl/f96eNq/yqf1HIMn3jXs7w3Cy5ChQQLpNsWtWC U7L0l6MXisbaLGbVwtEtSo5WUnPUjQwxER7emIbJFTBzp7WEuon9XAlwgusYdQBJ3hkO PkRA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:subject:from:content-language:to :user-agent:mime-version:date:message-id:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=44KaKTmQ+wy7JmP9bH6goWfSbO7HvYgDnWgDbRD/t58=; b=LJjWQIS5BCsOTxbuLE3I7gjiAoTnvnWQrvp4C6WHW6Qdj85fAZ5bvTYxyxMIy6a0LA Pf4+NiQu227Qz5oGttFBWY8YIfmaElUIOZasesBFT7y6rLk5CO8DH5cDSiI4uzZjgBm0 gZvKqdaDrtL1HHN1mEjzpbsJSMRScu48E/WekCIYG41ZPthUvo3IqTuyfq8dqqfhEIUZ e1JMJTCgFuFfhWfb5Rws4w51PA5tCYyNA6upxcColKYMeifMSqoXGuS8AYLvc8KfqHn7 ukb6yZbC3p4Bg63WOjlnPVda6NQZOWlA7+UY0OKOtmZwGKdsufOTq0teUKqPC7iLzpgI mDdg== X-Gm-Message-State: ACrzQf3RoDUvC3JLiu7p/DAO49M8CmGFAQsUbAr3EJafythQ5dm/zHVu jzm2Ij9+0/OW1V8QJfdNi1Tw7YoAJDc= X-Received: by 2002:a17:906:7310:b0:782:cfd4:9c07 with SMTP id di16-20020a170906731000b00782cfd49c07mr5923287ejc.708.1665178285721; Fri, 07 Oct 2022 14:31:25 -0700 (PDT) Received: from ?IPV6:2a02:168:575a:b00b:48a8:db33:3b94:651f? ([2a02:168:575a:b00b:48a8:db33:3b94:651f]) by smtp.googlemail.com with ESMTPSA id b17-20020a17090630d100b0078b03d57fa7sm1793740ejb.34.2022.10.07.14.31.24 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 07 Oct 2022 14:31:24 -0700 (PDT) Message-ID: Date: Fri, 7 Oct 2022 23:31:23 +0200 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.3.0 To: ffmpeg-devel@ffmpeg.org Content-Language: en-US From: Gregor Riepl Subject: [FFmpeg-devel] [PATCH] 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: wTG97yzw+zD5 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. Fixes: #8522 Signed-off-by: Gregor Riepl --- libavformat/dashdec.c | 210 ++++++++++++++++++++++++++++++++---------- 1 file changed, 162 insertions(+), 48 deletions(-) diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index 29d4680c68..f25d1a2bdf 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -20,6 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include +#include #include "libavutil/bprint.h" #include "libavutil/opt.h" #include "libavutil/time.h" @@ -129,21 +130,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) */ + bool media_presentation_duration_assigned; + bool suggested_presentation_delay_assigned; + bool availability_start_time_assigned; + bool availability_end_time_assigned; + bool publish_time_assigned; + bool minimum_update_period_assigned; + bool time_shift_buffer_depth_assigned; + bool min_buffer_time_assigned; + bool period_duration_assigned; + bool period_start_assigned; + bool adaptionset_lang_assigned; int is_live; AVIOInterruptCB *interrupt_callback; @@ -867,8 +881,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 +1120,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 = true; + } return 0; } @@ -1162,8 +1179,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 = false; return ret; } @@ -1273,29 +1291,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 = true; + 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 = true; + 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 = true; + 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 = true; + 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 = true; + 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 = true; + 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 = true; + 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 = true; + av_log(s, AV_LOG_TRACE, "c->media_presentation_duration = [%"PRId64"]\n", c->media_presentation_duration_value); } attr = attr->next; xmlFree(val); @@ -1325,12 +1351,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 = true; + if (c->period_start_value > 0) { + c->media_presentation_duration_value = c->period_duration_value; + c->media_presentation_duration_assigned = true; + } + } 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 = true; + c->period_start_value = period_start_sec; + c->period_start_assigned = true; + if (c->period_start_value > 0) { + c->media_presentation_duration_value = c->period_duration_value; + c->media_presentation_duration_assigned = true; + } } } else if (!av_strcasecmp(node->name, "ProgramInformation")) { parse_programinformation(s, node); @@ -1391,15 +1435,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 +1498,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 +1528,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 +2149,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); }