From 3f3229cd109f5cdf1f1d6fe26f2864e32e029b53 Mon Sep 17 00:00:00 2001 From: Fred Rothganger Date: Tue, 11 Mar 2014 17:58:34 -0600 Subject: [PATCH] avformat: extracting NTP timestamp from RTCP For muxing, it accepts both 0 and AV_NOPTS_VALUE. For demuxing, it will present AV_NOPTS_VALUE when start_time_realtime is unknown. Signed-off-by: Michael Niedermayer --- doc/APIchanges | 3 +++ libavformat/avformat.h | 7 ++++++- libavformat/options_table.h | 1 + libavformat/rtpenc.c | 2 +- libavformat/rtsp.c | 10 ++++++++++ libavformat/rtspenc.c | 3 ++- libavformat/sapenc.c | 3 ++- libavformat/version.h | 2 +- 8 files changed, 26 insertions(+), 5 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index b28f96d26a..93e3112b03 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,9 @@ libavutil: 2012-10-22 API changes, most recent first: +2014-03-11 - xxxxxxx - lavf 55.34.101 - avformat.h + Set AVFormatContext.start_time_realtime when demuxing. + 2014-xx-xx - xxxxxx - lavd 55.11.100 - avdevice.h Add av_input_audio_device_next(). Add av_input_video_device_next(). diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 4f7b6ba3fe..9130ee5f5e 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -1275,7 +1275,12 @@ typedef struct AVFormatContext { * Start time of the stream in real world time, in microseconds * since the Unix epoch (00:00 1st January 1970). That is, pts=0 in the * stream was captured at this real world time. - * Muxing only, set by the caller before avformat_write_header(). + * - muxing: Set by the caller before avformat_write_header(). If set to + * either 0 or AV_NOPTS_VALUE, then the current wall-time will + * be used. + * - demuxing: Set by libavformat. AV_NOPTS_VALUE if unknown. Note that + * the value may become known after some number of frames + * have been received. */ int64_t start_time_realtime; diff --git a/libavformat/options_table.h b/libavformat/options_table.h index c80309cdbb..9e31190747 100644 --- a/libavformat/options_table.h +++ b/libavformat/options_table.h @@ -57,6 +57,7 @@ static const AVOption avformat_options[] = { {"fdebug", "print specific debug info", OFFSET(debug), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, 0, INT_MAX, E|D, "fdebug"}, {"ts", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_FDEBUG_TS }, INT_MIN, INT_MAX, E|D, "fdebug"}, {"max_delay", "maximum muxing or demuxing delay in microseconds", OFFSET(max_delay), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, INT_MAX, E|D}, +{"start_time_realtime", "wall-clock time when stream begins (PTS==0)", OFFSET(start_time_realtime), AV_OPT_TYPE_INT64, {.i64 = AV_NOPTS_VALUE}, INT64_MIN, INT64_MAX, E}, {"fpsprobesize", "number of frames used to probe fps", OFFSET(fps_probe_size), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX-1, D}, {"audio_preload", "microseconds by which audio packets should be interleaved earlier", OFFSET(audio_preload), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX-1, E}, {"chunk_duration", "microseconds for each chunk", OFFSET(max_chunk_duration), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX-1, E}, diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c index f0100083b8..457fef0cfc 100644 --- a/libavformat/rtpenc.c +++ b/libavformat/rtpenc.c @@ -119,7 +119,7 @@ static int rtp_write_header(AVFormatContext *s1) s->ssrc = av_get_random_seed(); s->first_packet = 1; s->first_rtcp_ntp_time = ff_ntp_time(); - if (s1->start_time_realtime) + if (s1->start_time_realtime != 0 && s1->start_time_realtime != AV_NOPTS_VALUE) /* Round the NTP time to whole milliseconds. */ s->first_rtcp_ntp_time = (s1->start_time_realtime / 1000) * 1000 + NTP_OFFSET_US; diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index d89af626da..fcf9eca0d4 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -2071,6 +2071,16 @@ redo: st2->time_base); } } + // Make real NTP start time available in AVFormatContext + if (s->start_time_realtime == AV_NOPTS_VALUE) { + s->start_time_realtime = av_rescale (rtpctx->first_rtcp_ntp_time - (NTP_OFFSET << 32), 1000000, 1LL << 32); + if (rtpctx->st) { + s->start_time_realtime -= + av_rescale (rtpctx->rtcp_ts_offset, + (uint64_t) rtpctx->st->time_base.num * 1000000, + rtpctx->st->time_base.den); + } + } } if (ret == -RTCP_BYE) { rt->nb_byes++; diff --git a/libavformat/rtspenc.c b/libavformat/rtspenc.c index d76ae872eb..cc6e729e8c 100644 --- a/libavformat/rtspenc.c +++ b/libavformat/rtspenc.c @@ -51,7 +51,8 @@ int ff_rtsp_setup_output_streams(AVFormatContext *s, const char *addr) char *sdp; AVFormatContext sdp_ctx, *ctx_array[1]; - s->start_time_realtime = av_gettime(); + if (s->start_time_realtime == 0 || s->start_time_realtime == AV_NOPTS_VALUE) + s->start_time_realtime = av_gettime(); /* Announce the stream */ sdp = av_mallocz(SDP_MAX_SIZE); diff --git a/libavformat/sapenc.c b/libavformat/sapenc.c index 9fc78a83af..738e8b8f91 100644 --- a/libavformat/sapenc.c +++ b/libavformat/sapenc.c @@ -140,7 +140,8 @@ static int sap_write_header(AVFormatContext *s) goto fail; } - s->start_time_realtime = av_gettime(); + if (s->start_time_realtime == 0 || s->start_time_realtime == AV_NOPTS_VALUE) + s->start_time_realtime = av_gettime(); for (i = 0; i < s->nb_streams; i++) { URLContext *fd; diff --git a/libavformat/version.h b/libavformat/version.h index f9fc9d8302..e0d3fc8ba8 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #define LIBAVFORMAT_VERSION_MAJOR 55 #define LIBAVFORMAT_VERSION_MINOR 34 -#define LIBAVFORMAT_VERSION_MICRO 100 +#define LIBAVFORMAT_VERSION_MICRO 101 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \