From patchwork Wed Apr 4 08:38:21 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Dixit, Vishwanath" X-Patchwork-Id: 8319 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.2.1.70 with SMTP id c67csp4619985jad; Wed, 4 Apr 2018 01:38:41 -0700 (PDT) X-Google-Smtp-Source: AIpwx4/WozVijrxWhsrw/z5cHKSTEDfUuhZYSItP+fHBDLUy0OLLPSQhg66z4fqh+Zyz1f3Vv7Be X-Received: by 10.28.160.1 with SMTP id j1mr7032052wme.21.1522831121634; Wed, 04 Apr 2018 01:38:41 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1522831121; cv=none; d=google.com; s=arc-20160816; b=fnpwni2aWEYbElUImw0A8f4OSO56LWiiCxeIGS/DYDavwhVlOq2tsV6KNJ1liUqTAK p1I1wzWK9ekFEdEOqFYS7b0jkLi8Uchbg7HxUFtnWsK0t5mEQbODokFJu/24tuj1XRkY vHEiShQgjpTpaAGf+hqowavvgRzCjQVxHqwmguUjUkjVVU1rqK/3oTYL46t6kLXOiI1i oErfTYMQ9xBKU9q0Z+VaBiFxUV5sANbQ421Gpp0jKjyfpnmJMAf/fwOEWYnXAEH2uMd0 m45nThyUADIn7HzrLOumSt4d81P0kbBFUyFVi6wJi21LQUZDfMMX2Bf1JHbg+4aXGNQK fYSw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:feedback-id:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to :arc-authentication-results; bh=0k2sYJoMRwaAiALi5Te0ne6MkpQsUgpEKNhtDndtHh8=; b=pisYXmJaPALACVM3icZs0C82CXfwn/pTW8zhtiLrpJ2sFkXaikKN+yah378zbCL9Dl BP2j128CULAjtudmzv3NmzRwzqQldX2pvbtPnxSkVecR3T8Fx+MfPjdHLewhX5kMv6ir o1aXJeKRtcvuFrhrJZJMapwb4MGdHCU3afmtIHwdy14jmKGduaRLTuBc/d+pUTseGuBn NWRbinVkCsGysJwzIwbc9uAY4jiUoV4HRdxpH/yhxt6zY1tY6nnzljy0ircw6F0ZGC8f Fw6r42cpblo/BiGJLl4mplfpXpBB3OKucZlbeXXWNXx8PpVRHoHtp1WoHpYDn5yT2b5E V3Lw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@smtpservice.net header.s=m78bu0.a1-4.dyn header.b=F4RAXOC/; 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=QUARANTINE sp=NONE dis=NONE) header.from=akamai.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id v130si3511239wma.131.2018.04.04.01.38.41; Wed, 04 Apr 2018 01:38:41 -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=@smtpservice.net header.s=m78bu0.a1-4.dyn header.b=F4RAXOC/; 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=QUARANTINE sp=NONE dis=NONE) header.from=akamai.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 8E85C689CBF; Wed, 4 Apr 2018 11:38:08 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from a1i318.smtp2go.com (a1i318.smtp2go.com [43.228.185.62]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id BEE08689CBF for ; Wed, 4 Apr 2018 11:38:06 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=smtpservice.net; s=m78bu0.a1-4.dyn; x=1522832008; h=Feedback-ID: X-Smtpcorp-Track:Message-Id:Date:Subject:To:From:Reply-To:Sender: List-Unsubscribe; bh=/Key8HEk3QPheJhd7qIzH6+0jop31lgOMqw8jcMbqUM=; b=F4RAXOC/ OquBWR99We4SoMoJhILRbgQ6IBi1bP6UwmuGsv+C8tPJa0H1oIYsw/H+vJd6+lOZbY6ta4XCveKZ2 Yt5/zK5Xneul6ndP9sF9yCuMgZXEPxYBg4mB63qcigkGr8l34v/SHK19NlF3xhQrKYIO0AO0kIg6D oLivpb3iuyaWVD3Ny4qXrC2Prjv45UfXlwUWxYI/PcHSAJSQqRN0SYuHPwZp5c4JI/uc22xOwFClI C1pHJHrlH8anjLluej+MPZ4wxoVCdQzrE83iqlm5osGJLJA9aejIVpCIUixSf+5PIqGvQCxPmWxjO x9mwTW5DlF3jgBcjad9Y71rhgA==; From: vdixit@akamai.com To: ffmpeg-devel@ffmpeg.org Date: Wed, 4 Apr 2018 14:08:21 +0530 Message-Id: <1522831101-7665-1-git-send-email-vdixit@akamai.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1521782875-27623-1-git-send-email-vdixit@akamai.com> References: <1521782875-27623-1-git-send-email-vdixit@akamai.com> X-Smtpcorp-Track: 1f3dw0DIIdH-Tz.xu8Ux8wK2 Feedback-ID: 337386m:337386asVRLGB:337386sQ1whA23Q5:SMTPCORP X-Report-Abuse: Please forward a copy of this message, including all headers, to Subject: [FFmpeg-devel] [PATCH v2 11/11] avformat/dashenc: addition of segment index correction logic 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: Vishwanath Dixit MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From: Vishwanath Dixit The logic is applicable only when use_template is enabled and use_timeline is disabled. The logic monitors the flow of segment indexes. If a streams's segment index value is not at the expected real time position, then the logic corrects that index value. Typically this logic is needed in live streaming use cases. The network bandwidth fluctuations are common during long run streaming. Each fluctuation can cause the segment indexes fall behind the expected real time position. Without this logic, players will not be able to consume the content, even after encoder's network condition comes back to normal state. --- doc/muxers.texi | 11 +++++++++++ libavformat/dashenc.c | 31 ++++++++++++++++++++++++++----- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index 9e8b8a4..e5c9be1 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -271,6 +271,17 @@ To map all video (or audio) streams to an AdaptationSet, "v" (or "a") can be use When no assignment is defined, this defaults to an AdaptationSet for each stream. @item -timeout @var{timeout} Set timeout for socket I/O operations. Applicable only for HTTP output. +@item -index_correction @var{index_correction} +Enable (1) or Disable (0) segment index correction logic. Applicable only when +@var{use_template} is enabled and @var{use_timeline} is disabled. + +When enabled, the logic monitors the flow of segment indexes. If a streams's +segment index value is not at the expected real time position, then the logic +corrects that index value. + +Typically this logic is needed in live streaming use cases. The network bandwidth +fluctuations are common during long run streaming. Each fluctuation can cause +the segment indexes fall behind the expected real time position. @end table @anchor{framecrc} diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index ac05378..f0848c5 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -76,7 +76,7 @@ typedef struct OutputStream { int nb_segments, segments_size, segment_index; Segment **segments; int64_t first_pts, start_pts, max_pts; - int64_t last_dts; + int64_t last_dts, last_pts; int bit_rate; char codec_str[100]; @@ -121,6 +121,7 @@ typedef struct DASHContext { AVIOContext *m3u8_out; int streaming; int64_t timeout; + int index_correction; } DASHContext; static struct codec_string { @@ -1056,7 +1057,7 @@ static int dash_write_header(AVFormatContext *s) static int add_segment(OutputStream *os, const char *file, int64_t time, int duration, int64_t start_pos, int64_t range_length, - int64_t index_length) + int64_t index_length, int next_exp_index) { int err; Segment *seg; @@ -1084,6 +1085,12 @@ static int add_segment(OutputStream *os, const char *file, seg->index_length = index_length; os->segments[os->nb_segments++] = seg; os->segment_index++; + //correcting the segment index if it has fallen behind the expected value + if (os->segment_index < next_exp_index) { + av_log(NULL, AV_LOG_WARNING, "Correcting the segment index after file %s: current=%d corrected=%d\n", + file, os->segment_index, next_exp_index); + os->segment_index = next_exp_index; + } return 0; } @@ -1173,10 +1180,22 @@ static int dash_flush(AVFormatContext *s, int final, int stream) const char *proto = avio_find_protocol_name(s->url); int use_rename = proto && !strcmp(proto, "file"); - int cur_flush_segment_index = 0; - if (stream >= 0) + int cur_flush_segment_index = 0, next_exp_index = -1; + if (stream >= 0) { cur_flush_segment_index = c->streams[stream].segment_index; + //finding the next segment's expected index, based on the current pts value + if (c->use_template && !c->use_timeline && c->index_correction && + c->streams[stream].last_pts != AV_NOPTS_VALUE && + c->streams[stream].first_pts != AV_NOPTS_VALUE) { + int64_t pts_diff = av_rescale_q(c->streams[stream].last_pts - + c->streams[stream].first_pts, + s->streams[stream]->time_base, + AV_TIME_BASE_Q); + next_exp_index = (pts_diff / c->seg_duration) + 1; + } + } + for (i = 0; i < s->nb_streams; i++) { OutputStream *os = &c->streams[i]; AVStream *st = s->streams[i]; @@ -1236,7 +1255,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream) if (bitrate >= 0) os->bit_rate = bitrate; } - add_segment(os, os->filename, os->start_pts, os->max_pts - os->start_pts, os->pos, range_length, index_length); + add_segment(os, os->filename, os->start_pts, os->max_pts - os->start_pts, os->pos, range_length, index_length, next_exp_index); av_log(s, AV_LOG_VERBOSE, "Representation %d media segment %d written to: %s\n", i, os->segment_index, os->full_path); os->pos += range_length; @@ -1299,6 +1318,7 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) if (os->first_pts == AV_NOPTS_VALUE) os->first_pts = pkt->pts; + os->last_pts = pkt->pts; if (!c->availability_start_time[0]) format_date_now(c->availability_start_time, @@ -1479,6 +1499,7 @@ static const AVOption options[] = { { "hls_playlist", "Generate HLS playlist files(master.m3u8, media_%d.m3u8)", OFFSET(hls_playlist), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, { "streaming", "Enable/Disable streaming mode of output. Each frame will be moof fragment", OFFSET(streaming), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, { "timeout", "set timeout for socket I/O operations", OFFSET(timeout), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT_MAX, .flags = E }, + { "index_correction", "Enable/Disable segment index correction logic", OFFSET(index_correction), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, { NULL }, };