From patchwork Tue Apr 24 09:16:57 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Dixit, Vishwanath" X-Patchwork-Id: 8624 Delivered-To: ffmpegpatchwork@gmail.com Received: by 2002:a02:155:0:0:0:0:0 with SMTP id c82-v6csp1622219jad; Tue, 24 Apr 2018 02:17:29 -0700 (PDT) X-Google-Smtp-Source: AIpwx49waqpRFCBeLoo1+0pdzMhF1NqgDq8Q5UgO8xtvkf+0YUkdAVC1dAhEeDrUDmU7pz+iwFiW X-Received: by 2002:adf:da4b:: with SMTP id r11-v6mr9740939wrl.154.1524561449521; Tue, 24 Apr 2018 02:17:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524561449; cv=none; d=google.com; s=arc-20160816; b=YKXLSDNvuaK1ao7PcQmMVQQe1rMr31KpCht+9H7PkVKmmtoW+zlWm3lelyqvw+q5rc cX6O+asZFiJ4Ue5nQcG+pQZMDMXed232FZJSM280AqcXj+GnSe5Pfb8h0WdvPjAePKZK zwJ3uPHggWyTa4Ch/YS/y/yc4LPMAzQKNcMghoUxRU6WKpruXni8LjArewlR5SRslxp/ DAfhA17oIJC8JcnZ/bKE/uAvcRD3Zv5kuykMJ4wrR5YO0w/7iu3fY6pSqtb34nXSEgDp jsGtVxMoki3GNjXXCudabK1jM0QDnxBNh5R0yQ/0rDp19O4e+GLBfLQ3ixsyxLoLso0t +/xw== 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=QbSnZBtChGXHGPv0udv2gbuvqgFtJTqPE+buuxtsPYY=; b=CpgdgfuajjdCdcijYWBWbk0kQMn9fh42dMpzeApia6Yh2jw8GHv3S9Z3pCR0zZDMg0 P66rA7kb1E6PftAJUuHki4Xy7beEvLgtR/i9T3h4UM/lEkkCF/OPf0y5EAFevV0Rn68s u9F7erwXsza+gYPKwpn0hT+UxU+KJkEh3eor0ykQ/PizA8PFdGtFn/zg3bGFmZzamVjc FAPoCnUM0q0ToHpQsndICdMFeF7TgoTjQRXdl8uUrrJvmek16IbMi/GQq1nJu3OWAExv OYcrKdmwC0U+VZ8PG3KNt6ul9VRKFpfiOdwTC09o+ptYYLLi2s9s/Y2gppnTwWilFZUB aZAg== 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=zhZLqrXH; 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 s62si6636462wmf.190.2018.04.24.02.17.29; Tue, 24 Apr 2018 02:17:29 -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=zhZLqrXH; 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 4DE7B689F78; Tue, 24 Apr 2018 12:16:48 +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 E2E24689CB7 for ; Tue, 24 Apr 2018 12:16:40 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=smtpservice.net; s=m78bu0.a1-4.dyn; x=1524562335; h=Feedback-ID: X-Smtpcorp-Track:Message-Id:Date:Subject:To:From:Reply-To:Sender: List-Unsubscribe; bh=xCgaTWwRj2p3iENftn4vXx4ks/5B+oObVHPUYNPURgw=; b=zhZLqrXH KCDg4zIlRZ7GcUwr5FvypUm2sLvfv3/5QGK29f7vSBhzLL/Xc9dtbt79JupIp9KNo56m+/3+inKnh jBHzowvgZ4jXuFXvXW6mRDXu5xD10xhWGTOJjGJvO+/iUsQg0YBeD/aulkSazhTWRm2SfO/p1DKtI aegX1nXaG5hY8bBZZaegEg4WYcvL1iVpdB5PRHr+bB8/bWPGY7GMAu8m1nhNeLalf/aVvB2L4yIr5 /Iirptpw5HkKb8dY3C0T6nygPFAf9AHbQoYzmjkb4w+eMu9suGYchGTt95DZmVII1EQbhEnSPp17s KPVWUNAH8RCcPtJISBA9SF82rg==; From: vdixit@akamai.com To: ffmpeg-devel@ffmpeg.org Date: Tue, 24 Apr 2018 14:46:57 +0530 Message-Id: <1524561418-4419-2-git-send-email-vdixit@akamai.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1524561418-4419-1-git-send-email-vdixit@akamai.com> References: <1524561418-4419-1-git-send-email-vdixit@akamai.com> X-Smtpcorp-Track: 1fjI4QDIIcZvJb.3rYTszXIs Feedback-ID: 337386m:337386asVRLGB:337386sh_P-PdPnh:SMTPCORP X-Report-Abuse: Please forward a copy of this message, including all headers, to Subject: [FFmpeg-devel] [PATCH 2/3] avformat/movenc: creating producer reference time (PRFT) box 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 producer reference time box supplies relative wall-clock times at which movie fragments, or files containing movie fragments (such as segments) were produced. The box is mainly useful in live streaming use cases. A media player can parse the box and utilize the time fields to measure and improve the latency during real time playout. --- doc/muxers.texi | 10 ++++++++++ libavformat/movenc.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ libavformat/movenc.h | 9 +++++++++ 3 files changed, 69 insertions(+) diff --git a/doc/muxers.texi b/doc/muxers.texi index 6f03bba..db81901 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -1329,6 +1329,16 @@ be negative. This enables the initial sample to have DTS/CTS of zero, and reduces the need for edit lists for some cases such as video tracks with B-frames. Additionally, eases conformance with the DASH-IF interoperability guidelines. +@item -write_prft +Write producer time reference box (PRFT) with a specified time source for the +NTP field in the PRFT box. Set value as @samp{wallclock} to specify timesource +as wallclock time and @samp{pts} to specify timesource as input packets' PTS +values. + +Setting value to @samp{pts} is applicable only for a live encoding use case, +where PTS values are set as as wallclock time at the source. For example, an +encoding use case with decklink capture source where @option{video_pts} and +@option{audio_pts} are set to @samp{abs_wallclock}. @end table @subsection Example diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 0b44fd6..14e397a 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -98,6 +98,9 @@ static const AVOption options[] = { { "encryption_kid", "The media encryption key identifier (hex)", offsetof(MOVMuxContext, encryption_kid), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_ENCODING_PARAM }, { "use_stream_ids_as_track_ids", "use stream ids as track ids", offsetof(MOVMuxContext, use_stream_ids_as_track_ids), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM}, { "write_tmcd", "force or disable writing tmcd", offsetof(MOVMuxContext, write_tmcd), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM}, + { "write_prft", "Write producer reference time box with specified time source", offsetof(MOVMuxContext, write_prft), AV_OPT_TYPE_INT, {.i64 = MOV_PRFT_NONE}, 0, MOV_PRFT_NB-1, AV_OPT_FLAG_ENCODING_PARAM, "prft"}, + { "wallclock", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = MOV_PRFT_SRC_WALLCLOCK}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, "prft"}, + { "pts", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = MOV_PRFT_SRC_PTS}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, "prft"}, { NULL }, }; @@ -4514,6 +4517,49 @@ static int mov_write_sidx_tags(AVIOContext *pb, MOVMuxContext *mov, return 0; } +static int mov_write_prft_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks) +{ + int64_t pos = avio_tell(pb), pts_us, ntp_ts; + MOVTrack *first_track; + + /* PRFT should be associated with at most one track. So, choosing only the + * first track. */ + if (tracks > 0) + return 0; + first_track = &(mov->tracks[0]); + + if (!first_track->entry) { + av_log(mov->fc, AV_LOG_WARNING, "Unable to write PRFT, no entries in the track\n"); + return 0; + } + + if (first_track->cluster[0].pts == AV_NOPTS_VALUE) { + av_log(mov->fc, AV_LOG_WARNING, "Unable to write PRFT, first PTS is invalid\n"); + return 0; + } + + if (mov->write_prft == MOV_PRFT_SRC_WALLCLOCK) { + ntp_ts = ff_time_ntp_format(ff_ntp_time()); + } else if (mov->write_prft == MOV_PRFT_SRC_PTS) { + pts_us = av_rescale_q(first_track->cluster[0].pts, + first_track->st->time_base, AV_TIME_BASE_Q); + ntp_ts = ff_time_ntp_format(pts_us + NTP_OFFSET_US); + } else { + av_log(mov->fc, AV_LOG_WARNING, "Unsupported PRFT box configuration: %d\n", + mov->write_prft); + return 0; + } + + avio_wb32(pb, 0); // Size place holder + ffio_wfourcc(pb, "prft"); // Type + avio_w8(pb, 1); // Version + avio_wb24(pb, 0); // Flags + avio_wb32(pb, first_track->track_id); // reference track ID + avio_wb64(pb, ntp_ts); // NTP time stamp + avio_wb64(pb, first_track->cluster[0].pts); //media time + return update_size(pb, pos); +} + static int mov_write_moof_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks, int64_t mdat_size) { @@ -4528,6 +4574,9 @@ static int mov_write_moof_tag(AVIOContext *pb, MOVMuxContext *mov, int tracks, if (mov->flags & FF_MOV_FLAG_DASH && !(mov->flags & FF_MOV_FLAG_GLOBAL_SIDX)) mov_write_sidx_tags(pb, mov, tracks, moof_size + 8 + mdat_size); + if (mov->write_prft > MOV_PRFT_NONE && mov->write_prft < MOV_PRFT_NB) + mov_write_prft_tag(pb, mov, tracks); + if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX || !(mov->flags & FF_MOV_FLAG_SKIP_TRAILER) || mov->ism_lookahead) { @@ -5317,6 +5366,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) trk->cluster[trk->entry].size = size; trk->cluster[trk->entry].entries = samples_in_chunk; trk->cluster[trk->entry].dts = pkt->dts; + trk->cluster[trk->entry].pts = pkt->pts; if (!trk->entry && trk->start_dts != AV_NOPTS_VALUE) { if (!trk->frag_discont) { /* First packet of a new fragment. We already wrote the duration diff --git a/libavformat/movenc.h b/libavformat/movenc.h index c9b4072..f2967bf 100644 --- a/libavformat/movenc.h +++ b/libavformat/movenc.h @@ -46,6 +46,7 @@ typedef struct MOVIentry { uint64_t pos; int64_t dts; + int64_t pts; unsigned int size; unsigned int samples_in_chunk; unsigned int chunkNum; ///< Chunk number if the current entry is a chunk start otherwise 0 @@ -169,6 +170,13 @@ typedef enum { MOV_ENC_CENC_AES_CTR, } MOVEncryptionScheme; +typedef enum { + MOV_PRFT_NONE = 0, + MOV_PRFT_SRC_WALLCLOCK, + MOV_PRFT_SRC_PTS, + MOV_PRFT_NB +} MOVPrftBox; + typedef struct MOVMuxContext { const AVClass *av_class; int mode; @@ -224,6 +232,7 @@ typedef struct MOVMuxContext { int use_stream_ids_as_track_ids; int track_ids_ok; int write_tmcd; + MOVPrftBox write_prft; } MOVMuxContext; #define FF_MOV_FLAG_RTP_HINT (1 << 0)