diff --git a/doc/muxers.texi b/doc/muxers.texi index 3f013516b1..b0dc7e6442 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -741,6 +741,10 @@ Reset timestamps at the begin of each segment, so that each segment will start with near-zero timestamps. It is meant to ease the playback of the generated segments. May not work with some combinations of muxers/codecs. It is set to @code{0} by default. + +@item initial_offset @var{offset} +Specify timestamp offset to apply to the output packet timestamps. The +argument must be a time duration specification, and defaults to 0. @end table @subsection Examples diff --git a/libavformat/segment.c b/libavformat/segment.c index dbcfe898cf..756161fd96 100644 --- a/libavformat/segment.c +++ b/libavformat/segment.c @@ -43,6 +43,7 @@ typedef struct SegmentListEntry { int index; double start_time, end_time; int64_t start_pts; + int64_t offset_pts; char filename[1024]; struct SegmentListEntry *next; } SegmentListEntry; @@ -91,6 +92,7 @@ typedef struct { int write_header_trailer; /**< Set by a private option. */ int reset_timestamps; ///< reset timestamps at the begin of each segment + int64_t initial_offset; ///< initial timestamps offset, expressed in microseconds char *reference_stream_specifier; ///< reference stream specifier int reference_stream_index; @@ -644,7 +646,7 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) SegmentContext *seg = s->priv_data; AVFormatContext *oc = seg->avf; AVStream *st = s->streams[pkt->stream_index]; - int64_t end_pts = INT64_MAX; + int64_t end_pts = INT64_MAX, offset; int start_frame = INT_MAX; int ret; @@ -694,7 +696,7 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) seg->is_first_pkt = 0; } - if (seg->reset_timestamps) { + /* todo: reindent */ av_log(s, AV_LOG_DEBUG, "stream:%d start_pts_time:%s pts:%s pts_time:%s dts:%s dts_time:%s", pkt->stream_index, av_ts2timestr(seg->cur_entry.start_pts, &AV_TIME_BASE_Q), @@ -702,15 +704,16 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base)); /* compute new timestamps */ + offset = av_rescale_q(seg->initial_offset - (seg->reset_timestamps ? seg->cur_entry.start_pts : 0), + AV_TIME_BASE_Q, st->time_base); if (pkt->pts != AV_NOPTS_VALUE) - pkt->pts -= av_rescale_q(seg->cur_entry.start_pts, AV_TIME_BASE_Q, st->time_base); + pkt->pts += offset; if (pkt->dts != AV_NOPTS_VALUE) - pkt->dts -= av_rescale_q(seg->cur_entry.start_pts, AV_TIME_BASE_Q, st->time_base); + pkt->dts += offset; av_log(s, AV_LOG_DEBUG, " -> pts:%s pts_time:%s dts:%s dts_time:%s\n", av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base), av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base)); - } ret = ff_write_chained(oc, pkt->stream_index, pkt, s); @@ -793,6 +796,7 @@ static const AVOption options[] = { { "individual_header_trailer", "write header/trailer to each segment", OFFSET(individual_header_trailer), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, E }, { "write_header_trailer", "write a header to the first segment and a trailer to the last one", OFFSET(write_header_trailer), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, E }, { "reset_timestamps", "reset timestamps at the begin of each segment", OFFSET(reset_timestamps), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, E }, + { "initial_offset", "set initial timestamp offset", OFFSET(initial_offset), AV_OPT_TYPE_DURATION, {.i64 = 0}, -INT64_MAX, INT64_MAX, E }, { NULL }, }; diff --git a/libavformat/version.h b/libavformat/version.h index fd00994134..55e5f4c137 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #define LIBAVFORMAT_VERSION_MAJOR 55 #define LIBAVFORMAT_VERSION_MINOR 12 -#define LIBAVFORMAT_VERSION_MICRO 100 +#define LIBAVFORMAT_VERSION_MICRO 101 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \