--- doc/muxers.texi | 12 ++++++++++++ libavformat/segment.c | 38 +++++++++++++++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 3 deletions(-)
diff --git a/doc/muxers.texi b/doc/muxers.texi index 3e9476c..fcb121b 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -985,6 +985,15 @@ total packets size in the segment, in bytes. Note that this only expresses the size of the packets payload, unregarding the container size overhead. +@item chapter_n +number of the chapter, starting from 0, it is set to NAN if +there are no chapters. This variable is only updated when a new +reference stream packet is processed. + +@item chapter_id +id number of the chapter, starting from 0, it is set to NAN if +there are no chapters + @item packet_pos packet position, NAN if unspecified @@ -998,6 +1007,9 @@ packet time, expressed in seconds For example to cut a file when a size of 10Mi bytes is reached, use the expression @code{gt(segment_packets_size,10Mi)}. +To cut then input at each chapter start, use the expression +@code{gt(chapter_n,segment_n)}. + @item segment_time @var{time} Set segment duration to @var{time}, the value must be a duration specification. A value of 0 means that it will try to split the diff --git a/libavformat/segment.c b/libavformat/segment.c index 0cf5360..947a0c6 100644 --- a/libavformat/segment.c +++ b/libavformat/segment.c @@ -69,6 +69,9 @@ static const char *const var_names[] = { "segment_ref_packets_n", ///< segment reference stream frame count "segment_packets_size", ///< total packets size + "chapter_n", ///< chapter number + "chapter_id", ///< chapter id + "packet_pos", ///< packet position in the file "packet_n", ///< packet count "packet_t", ///< packet time @@ -82,6 +85,9 @@ enum var_name { VAR_SEGMENT_REF_PACKETS_N, VAR_SEGMENT_PACKETS_SIZE, + VAR_CHAPTER_N, + VAR_CHAPTER_ID, + VAR_PACKET_POS, VAR_PACKET_N, VAR_PACKET_T, @@ -146,6 +152,9 @@ typedef struct SegmentContext { SegmentListEntry cur_entry; SegmentListEntry *segment_list_entries; SegmentListEntry *segment_list_entries_end; + + int chapter_index; ///< index used to keep track of the current chapter + double next_chapter_start; } SegmentContext; static void print_csv_escaped_str(AVIOContext *ctx, const char *str) @@ -655,6 +664,14 @@ static int seg_write_header(AVFormatContext *s) seg->time = -1; } + seg->chapter_index = -1; + if (s->nb_chapters) { + AVChapter *chapter = s->chapters[0]; + seg->next_chapter_start = chapter->start * av_q2d(chapter->time_base); + } + seg->var_values[VAR_CHAPTER_N] = NAN; + seg->var_values[VAR_CHAPTER_ID] = NAN; + if (seg->segment_expr) { ret = av_expr_parse(&seg->segment_pexpr, seg->segment_expr, var_names, NULL, NULL, NULL, NULL, 0, s); @@ -766,6 +783,8 @@ fail: return ret; } +#define TS2T(ts, tb) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts) * av_q2d(tb)) + static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) { SegmentContext *seg = s->priv_data; @@ -773,6 +792,7 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) int64_t end_pts = INT64_MAX, offset; int start_frame = INT_MAX; int ret; + double ts = TS2T(pkt->pts, st->time_base); struct tm ti; int64_t usecs; int64_t wrapped_val; @@ -780,7 +800,18 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) if (!seg->avf) return AVERROR(EINVAL); -#define TS2T(ts, tb) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts) * av_q2d(tb)) + /* update chapter index */ + if (pkt->stream_index == seg->reference_stream_index && + s->nb_chapters && ts >= seg->next_chapter_start) { + seg->chapter_index++; + seg->var_values[VAR_CHAPTER_N] = seg->chapter_index; + seg->var_values[VAR_CHAPTER_ID] = s->chapters[seg->chapter_index]->id; + seg->next_chapter_start = + seg->chapter_index >= s->nb_chapters-1 ? FLT_MAX : // last chapter + s->chapters[seg->chapter_index+1]->start * + av_q2d(s->chapters[seg->chapter_index+1]->time_base); + } + seg->var_values[VAR_SEGMENT_PACKETS_SIZE] += pkt->size; seg->var_values[VAR_SEGMENT_PACKETS_N] += 1; @@ -818,11 +849,12 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) } } - av_dlog(s, "packet stream:%d pts:%s pts_time:%s duration_time:%s is_key:%d frame:%d\n", + av_dlog(s, "packet stream:%d pts:%s pts_time:%s duration_time:%s is_key:%d frame:%d chapter:%d\n", pkt->stream_index, av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base), av_ts2timestr(pkt->duration, &st->time_base), pkt->flags & AV_PKT_FLAG_KEY, - pkt->stream_index == seg->reference_stream_index ? seg->frame_count : -1); + pkt->stream_index == seg->reference_stream_index ? seg->frame_count : -1, + seg->chapter_index); if (pkt->stream_index == seg->reference_stream_index && pkt->flags & AV_PKT_FLAG_KEY && -- 1.8.3.2 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel