[FFmpeg-devel] [PATCH v2 2/3] avformat/movenc: creating producer reference time (PRFT) box
Jeyapal, Karthick
kjeyapal at akamai.com
Tue May 29 07:58:35 EEST 2018
Pushed Patchset.
Regards,
Karthick
On 5/7/18 3:27 PM, vdixit at akamai.com wrote:
> From: Vishwanath Dixit <vdixit at akamai.com>
>
> 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.
> + at 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
> + at 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..7e616e8 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_get_formatted_ntp_time(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_get_formatted_ntp_time(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)
More information about the ffmpeg-devel
mailing list