[FFmpeg-devel] [PATCH] lavf/segment: add logic to track chapter, and add segment_n and segment_id variables
Stefano Sabatini
stefasab at gmail.com
Fri Mar 20 14:14:24 CET 2015
---
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.
+ at 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.
+
+ at 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
+ at 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
More information about the ffmpeg-devel
mailing list