diff options
author | Martin Vignali <martin.vignali@gmail.com> | 2016-02-28 23:36:42 +0300 |
---|---|---|
committer | Stefano Sabatini <stefasab@gmail.com> | 2016-03-15 19:44:13 +0300 |
commit | 69638517d15912f5411cb5ebd0513c31beed2798 (patch) | |
tree | e4e5a39e6091f81796ae9c2551e93882ce5a8126 | |
parent | 7eedad946c30e36b06e476f5686c4ccb7de6dd06 (diff) |
lavf/segment: add increment_tc option
For example you can split a file, keeping a continuous timecode between
each segment:
ffmpeg -i src.mov -timecode 10:00:00:00 -vcodec copy -f segment \
-segment_time 2 -reset_timestamps 1 -increment_tc 1 target_%03d.mov
Signed-off-by: Stefano Sabatini <stefasab@gmail.com>
-rw-r--r-- | doc/muxers.texi | 6 | ||||
-rw-r--r-- | libavformat/segment.c | 32 | ||||
-rw-r--r-- | libavformat/version.h | 2 |
3 files changed, 39 insertions, 1 deletions
diff --git a/doc/muxers.texi b/doc/muxers.texi index ef7f333897..c36c72c67c 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -1045,6 +1045,12 @@ implementation for HLS segmentation. The segment muxer supports the following options: @table @option +@item increment_tc @var{1|0} +if set to @code{1}, increment timecode between each segment +If this is selected, the input need to have +a timecode in the first video stream. Default value is +@code{0}. + @item reference_stream @var{specifier} Set the reference stream, as specified by the string @var{specifier}. If @var{specifier} is set to @code{auto}, the reference is chosen diff --git a/libavformat/segment.c b/libavformat/segment.c index dd3b092139..6335c89921 100644 --- a/libavformat/segment.c +++ b/libavformat/segment.c @@ -41,6 +41,7 @@ #include "libavutil/parseutils.h" #include "libavutil/mathematics.h" #include "libavutil/time.h" +#include "libavutil/timecode.h" #include "libavutil/time_internal.h" #include "libavutil/timestamp.h" @@ -95,6 +96,7 @@ typedef struct SegmentContext { char *time_str; ///< segment duration specification string int64_t time; ///< segment duration int use_strftime; ///< flag to expand filename with strftime + int increment_tc; ///< flag to increment timecode if found char *times_str; ///< segment times specification string int64_t *times; ///< list of segment interval specification @@ -337,6 +339,12 @@ static int segment_end(AVFormatContext *s, int write_trailer, int is_last) SegmentContext *seg = s->priv_data; AVFormatContext *oc = seg->avf; int ret = 0; + AVTimecode tc; + AVRational rate; + AVDictionaryEntry *tcr; + char buf[AV_TIMECODE_STR_SIZE]; + int i; + int err; av_write_frame(oc, NULL); /* Flush any buffered data (fragmented mp4) */ if (write_trailer) @@ -390,6 +398,29 @@ static int segment_end(AVFormatContext *s, int write_trailer, int is_last) seg->avf->filename, seg->segment_count); seg->segment_count++; + if (seg->increment_tc) { + tcr = av_dict_get(s->metadata, "timecode", NULL, 0); + if (tcr) { + /* search the first video stream */ + for (i = 0; i < s->nb_streams; i++) { + if (s->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + rate = s->streams[i]->avg_frame_rate;/* Get fps from the video stream */ + err = av_timecode_init_from_string(&tc, rate, tcr->value, s); + if (err < 0) { + av_log(s, AV_LOG_WARNING, "Could not increment timecode, error occured during timecode creation."); + break; + } + tc.start += (int)((seg->cur_entry.end_time - seg->cur_entry.start_time) * av_q2d(rate));/* increment timecode */ + av_dict_set(&s->metadata, "timecode", + av_timecode_make_string(&tc, buf, 0), 0); + break; + } + } + } else { + av_log(s, AV_LOG_WARNING, "Could not increment timecode, no timecode metadata found"); + } + } + end: ff_format_io_close(oc, &oc->pb); @@ -948,6 +979,7 @@ static const AVOption options[] = { { "segment_start_number", "set the sequence number of the first segment", OFFSET(segment_idx), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E }, { "segment_wrap_number", "set the number of wrap before the first segment", OFFSET(segment_idx_wrap_nb), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E }, { "strftime", "set filename expansion with strftime at segment creation", OFFSET(use_strftime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E }, + { "increment_tc", "increment timecode between each segment", OFFSET(increment_tc), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, E }, { "break_non_keyframes", "allow breaking segments on non-keyframes", OFFSET(break_non_keyframes), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E }, { "individual_header_trailer", "write header/trailer to each segment", OFFSET(individual_header_trailer), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, E }, diff --git a/libavformat/version.h b/libavformat/version.h index 8088178b87..ae1d5896ea 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #define LIBAVFORMAT_VERSION_MAJOR 57 #define LIBAVFORMAT_VERSION_MINOR 28 -#define LIBAVFORMAT_VERSION_MICRO 101 +#define LIBAVFORMAT_VERSION_MICRO 102 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ |