From patchwork Mon Apr 22 00:51:24 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jun Li X-Patchwork-Id: 12860 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 AE664446A36 for ; Mon, 22 Apr 2019 03:51:44 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 8CF1768973E; Mon, 22 Apr 2019 03:51:44 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-pg1-f179.google.com (mail-pg1-f179.google.com [209.85.215.179]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id DADBA680905 for ; Mon, 22 Apr 2019 03:51:37 +0300 (EEST) Received: by mail-pg1-f179.google.com with SMTP id g8so5075947pgf.2 for ; Sun, 21 Apr 2019 17:51:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id; bh=fO5dUnOtX0IKMqzx8Lt+a6YO6X0HQKRapumsZVVo9pw=; b=hkKXfwof4DTrclYGr56ZXFRclSBAwor35Lc4mBGFFg0vVKA5/s2Ji/1c6KAV5gCrAq XOjuvKZMbAj7mraK2MjyMz2+Jmuk5Fmv0llTFvUVdQfPFC1xOu1H/C6ORik7xIyUsEJI 9mDmeFK7cjO9crdDjqDdaSWjuxIu11tLd0EEd7bCJISnWqbU9Ll0i4iw0ERlMEJwIq+q kne3ePrh0Vh+jnRHjQCXB3MGo0XrzDf1ofSLzc13arJL0U1G/AudJ+vT05J9ekLms6z7 hRLRVSFqbBjUNnKbqd7wf3BrwGiGhgCGZNpycL7Ho0AcahdcB9+BguLr87dmCHBFF0+h sRNQ== 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; bh=fO5dUnOtX0IKMqzx8Lt+a6YO6X0HQKRapumsZVVo9pw=; b=EKkBQ5o8Oj0yHqecX1QLP/WtO84uFoOn90J1l6glfOYrl626dDXskf1PBdcIBA/Rkp ajGD2V8pLduN+sAD3g5GOXXAMtQVvtPPKwftYNAZfoKy2p0hX2NqD5GRWFR0KgMBAnB9 iiDmqIDoKTlXSUL8cUsmTO2gtNeYA6xQSyoYDe7kloMc/djL2ubF/H5qGejbwdtHQ20i xdMDsAsiIAMCsMRiwbYOoIdJd2RvbVB/k51iYBL+2w3ygOLBgjFcNWpIbtu4n9BOoC0E YDJlqmhZ7MWi843oTXR+Oxgh307mUmO0SIvY85pW2uFztmN7m3bOIsOBN29t7nCPhEiL kQIg== X-Gm-Message-State: APjAAAWogKiROyyBDv9Cl+dcE6m4yPXqhFPBhtlatQ3H/QYHp95fSD6Q 9eozXd1HIG6FbaICX4BXDDDEgOhJ X-Google-Smtp-Source: APXvYqzfWeDKwYZP3xOlTcc/9JQCzqg70dYUK5MJj2eyTzlDEbRAfxaSd0hptK6AgrxOe9d8wuDp7w== X-Received: by 2002:aa7:8494:: with SMTP id u20mr10670157pfn.76.1555894295258; Sun, 21 Apr 2019 17:51:35 -0700 (PDT) Received: from jun-ubuntu.corp.microsoft.com ([2001:4898:80e8:8:f58e:a62c:f8d2:3a88]) by smtp.googlemail.com with ESMTPSA id d187sm12713448pgc.43.2019.04.21.17.51.33 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 21 Apr 2019 17:51:34 -0700 (PDT) From: Jun Li To: ffmpeg-devel@ffmpeg.org Date: Sun, 21 Apr 2019 17:51:24 -0700 Message-Id: <20190422005124.15109-1-junli1026@gmail.com> X-Mailer: git-send-email 2.17.1 Subject: [FFmpeg-devel] [PATCH v1] lavf/dashenc: Add option for calculting pkt duration 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 MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Fix #7144. The current packet duration calculation is heuristic, which uses the historical durtion as current duration. This commit adds the option to buffer one packet and calcuate its duration when next packet arrives. Obviously it adds one frame latency, which might be significant for VFR live content, so expose it as an option for user to choose. --- doc/muxers.texi | 4 ++++ libavformat/dashenc.c | 44 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index ee99ef621e..76954877a6 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -321,6 +321,10 @@ This is an experimental feature. @item -master_m3u8_publish_rate @var{master_m3u8_publish_rate} Publish master playlist repeatedly every after specified number of segment intervals. +@item -skip_estimate_pkt_duration +If this flag is set, packet duration will be calcuated as the diff of the current and next packet timestamp. The option is not for constant frame rate +content because heuristic estimation will be accurate in this case. Default value is 0. + @end table @anchor{framecrc} diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 5f1333e436..f89d68a51b 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -101,6 +101,7 @@ typedef struct OutputStream { double availability_time_offset; int total_pkt_size; int muxer_overhead; + AVPacket* prev_pkt; } OutputStream; typedef struct DASHContext { @@ -145,6 +146,7 @@ typedef struct DASHContext { int ignore_io_errors; int lhls; int master_publish_rate; + int skip_estiamte_pkt_duration; int nr_of_streams_to_flush; int nr_of_streams_flushed; } DASHContext; @@ -1559,7 +1561,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream) } else { snprintf(os->full_path, sizeof(os->full_path), "%s%s", c->dirname, os->initfile); } - + ret = flush_dynbuf(c, os, &range_length); if (ret < 0) break; @@ -1643,7 +1645,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream) return ret; } -static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) +static int dash_write_packet_internal(AVFormatContext *s, AVPacket *pkt) { DASHContext *c = s->priv_data; AVStream *st = s->streams[pkt->stream_index]; @@ -1789,11 +1791,47 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) return ret; } +static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) +{ + DASHContext *c = s->priv_data; + if (!c->skip_estiamte_pkt_duration) + return dash_write_packet_internal(s, pkt); + + AVStream *st = s->streams[pkt->stream_index]; + OutputStream *os = &c->streams[pkt->stream_index]; + int ret = 0; + + if (os->prev_pkt) { + if (!os->prev_pkt->duration && pkt->dts >= os->prev_pkt->dts) + os->prev_pkt->duration = pkt->dts - os->prev_pkt->dts; + ret = dash_write_packet_internal(s, os->prev_pkt); + av_packet_unref(os->prev_pkt); + if (av_packet_ref(os->prev_pkt, pkt)) { + av_log(s, AV_LOG_ERROR, "Failed to set up a reference to current packet, lost one packet for muxing.\n"); + av_packet_free(&os->prev_pkt); + } + } else { + os->prev_pkt = av_packet_clone(pkt); + } + return ret; +} + static int dash_write_trailer(AVFormatContext *s) { DASHContext *c = s->priv_data; int i; + if (c->skip_estiamte_pkt_duration) { + for (i = 0; i < s->nb_streams; i++) { + OutputStream *os = &c->streams[i]; + if (os->prev_pkt) { + // write last packet + dash_write_packet_internal(s, os->prev_pkt); + av_packet_free(&os->prev_pkt); + } + } + } + if (s->nb_streams > 0) { OutputStream *os = &c->streams[0]; // If no segments have been written so far, try to do a crude @@ -1888,6 +1926,8 @@ static const AVOption options[] = { { "ignore_io_errors", "Ignore IO errors during open and write. Useful for long-duration runs with network output", OFFSET(ignore_io_errors), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, { "lhls", "Enable Low-latency HLS(Experimental). Adds #EXT-X-PREFETCH tag with current segment's URI", OFFSET(lhls), 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}, + { "skip_estimate_pkt_duration", "Skip estimate packet duration, buffer previous packet for calculating its duration.", OFFSET(skip_estiamte_pkt_duration), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, + { NULL }, };