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 <michaelni@gmx.at>
pull/293/head
Fred Rothganger 11 years ago committed by Michael Niedermayer
parent 581957cd86
commit 3f3229cd10
  1. 3
      doc/APIchanges
  2. 7
      libavformat/avformat.h
  3. 1
      libavformat/options_table.h
  4. 2
      libavformat/rtpenc.c
  5. 10
      libavformat/rtsp.c
  6. 3
      libavformat/rtspenc.c
  7. 3
      libavformat/sapenc.c
  8. 2
      libavformat/version.h

@ -15,6 +15,9 @@ libavutil: 2012-10-22
API changes, most recent first: 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 2014-xx-xx - xxxxxx - lavd 55.11.100 - avdevice.h
Add av_input_audio_device_next(). Add av_input_audio_device_next().
Add av_input_video_device_next(). Add av_input_video_device_next().

@ -1275,7 +1275,12 @@ typedef struct AVFormatContext {
* Start time of the stream in real world time, in microseconds * 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 * since the Unix epoch (00:00 1st January 1970). That is, pts=0 in the
* stream was captured at this real world time. * 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; int64_t start_time_realtime;

@ -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"}, {"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"}, {"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}, {"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}, {"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}, {"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}, {"chunk_duration", "microseconds for each chunk", OFFSET(max_chunk_duration), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX-1, E},

@ -119,7 +119,7 @@ static int rtp_write_header(AVFormatContext *s1)
s->ssrc = av_get_random_seed(); s->ssrc = av_get_random_seed();
s->first_packet = 1; s->first_packet = 1;
s->first_rtcp_ntp_time = ff_ntp_time(); 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. */ /* Round the NTP time to whole milliseconds. */
s->first_rtcp_ntp_time = (s1->start_time_realtime / 1000) * 1000 + s->first_rtcp_ntp_time = (s1->start_time_realtime / 1000) * 1000 +
NTP_OFFSET_US; NTP_OFFSET_US;

@ -2071,6 +2071,16 @@ redo:
st2->time_base); 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) { if (ret == -RTCP_BYE) {
rt->nb_byes++; rt->nb_byes++;

@ -51,7 +51,8 @@ int ff_rtsp_setup_output_streams(AVFormatContext *s, const char *addr)
char *sdp; char *sdp;
AVFormatContext sdp_ctx, *ctx_array[1]; 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 */ /* Announce the stream */
sdp = av_mallocz(SDP_MAX_SIZE); sdp = av_mallocz(SDP_MAX_SIZE);

@ -140,7 +140,8 @@ static int sap_write_header(AVFormatContext *s)
goto fail; 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++) { for (i = 0; i < s->nb_streams; i++) {
URLContext *fd; URLContext *fd;

@ -31,7 +31,7 @@
#define LIBAVFORMAT_VERSION_MAJOR 55 #define LIBAVFORMAT_VERSION_MAJOR 55
#define LIBAVFORMAT_VERSION_MINOR 34 #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, \ #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
LIBAVFORMAT_VERSION_MINOR, \ LIBAVFORMAT_VERSION_MINOR, \

Loading…
Cancel
Save