lavf/segment: add initial_offset option

Should address trac ticket #2224.
This commit is contained in:
Stefano Sabatini 2013-07-05 14:28:38 +02:00
parent b3ac8a2a60
commit 19ea08a11a
3 changed files with 14 additions and 6 deletions

View File

@ -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 will start with near-zero timestamps. It is meant to ease the playback
of the generated segments. May not work with some combinations of of the generated segments. May not work with some combinations of
muxers/codecs. It is set to @code{0} by default. 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 @end table
@subsection Examples @subsection Examples

View File

@ -43,6 +43,7 @@ typedef struct SegmentListEntry {
int index; int index;
double start_time, end_time; double start_time, end_time;
int64_t start_pts; int64_t start_pts;
int64_t offset_pts;
char filename[1024]; char filename[1024];
struct SegmentListEntry *next; struct SegmentListEntry *next;
} SegmentListEntry; } SegmentListEntry;
@ -91,6 +92,7 @@ typedef struct {
int write_header_trailer; /**< Set by a private option. */ int write_header_trailer; /**< Set by a private option. */
int reset_timestamps; ///< reset timestamps at the begin of each segment 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 char *reference_stream_specifier; ///< reference stream specifier
int reference_stream_index; int reference_stream_index;
@ -644,7 +646,7 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt)
SegmentContext *seg = s->priv_data; SegmentContext *seg = s->priv_data;
AVFormatContext *oc = seg->avf; AVFormatContext *oc = seg->avf;
AVStream *st = s->streams[pkt->stream_index]; 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 start_frame = INT_MAX;
int ret; int ret;
@ -694,7 +696,7 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt)
seg->is_first_pkt = 0; 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", 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, pkt->stream_index,
av_ts2timestr(seg->cur_entry.start_pts, &AV_TIME_BASE_Q), 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)); av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base));
/* compute new timestamps */ /* 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) 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) 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_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->pts), av_ts2timestr(pkt->pts, &st->time_base),
av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base)); av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base));
}
ret = ff_write_chained(oc, pkt->stream_index, pkt, s); 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 }, { "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 }, { "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 }, { "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 }, { NULL },
}; };

View File

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