[FFmpeg-devel] [PATCH] ffmpeg: accept "chapters" as forced key frames.
Nicolas George
nicolas.george at normalesup.org
Wed Jan 2 19:18:47 CET 2013
Allow to force a key frame at the beginning of each chapter.
Signed-off-by: Nicolas George <nicolas.george at normalesup.org>
---
doc/ffmpeg.texi | 9 ++++++++-
ffmpeg.c | 52 +++++++++++++++++++++++++++++++++++++++++++++-------
2 files changed, 53 insertions(+), 8 deletions(-)
diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
index d0fe327..576ed0c 100644
--- a/doc/ffmpeg.texi
+++ b/doc/ffmpeg.texi
@@ -548,9 +548,16 @@ Deprecated see -bsf
@item -force_key_frames[:@var{stream_specifier}] @var{time}[, at var{time}...] (@emph{output,per-stream})
Force key frames at the specified timestamps, more precisely at the first
frames after each specified time.
+If one of the time is "@code{chapter}[@var{delta}]", it is expanded into the
+time of the beginning of all chapters in the file, shifted by @var{delta}.
This option can be useful to ensure that a seek point is present at a
chapter mark or any other designated place in the output file.
-The timestamps must be specified in ascending order.
+
+For example, to insert a key frame at 5 minutes plus 0.1 second before the
+beginning of each chapter:
+ at example
+-force_key_frames 0:05:00,chapters-0.1
+ at end example
@item -copyinkf[:@var{stream_specifier}] (@emph{output,per-stream})
When doing stream copy, copy also non-key frames found at the
diff --git a/ffmpeg.c b/ffmpeg.c
index 977218f..93150ab 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -1929,19 +1929,25 @@ static InputStream *get_input_stream(OutputStream *ost)
return NULL;
}
+static int compare_int64(const void *a, const void *b)
+{
+ int64_t d = *(int64_t *)a - *(int64_t *)b;
+ return d < 0 ? -1 : d > 0 ? +1 : 0;
+}
+
static void parse_forced_key_frames(char *kf, OutputStream *ost,
AVCodecContext *avctx)
{
char *p;
- int n = 1, i;
- int64_t t;
+ int n = 1, i, size, index = 0;
+ int64_t t, *pts;
for (p = kf; *p; p++)
if (*p == ',')
n++;
- ost->forced_kf_count = n;
- ost->forced_kf_pts = av_malloc(sizeof(*ost->forced_kf_pts) * n);
- if (!ost->forced_kf_pts) {
+ size = n;
+ pts = av_malloc(sizeof(*pts) * size);
+ if (!pts) {
av_log(NULL, AV_LOG_FATAL, "Could not allocate forced key frames array.\n");
exit(1);
}
@@ -1953,11 +1959,43 @@ static void parse_forced_key_frames(char *kf, OutputStream *ost,
if (next)
*next++ = 0;
- t = parse_time_or_die("force_key_frames", p, 1);
- ost->forced_kf_pts[i] = av_rescale_q(t, AV_TIME_BASE_Q, avctx->time_base);
+ if (!memcmp(p, "chapters", 8)) {
+
+ AVFormatContext *avf = output_files[ost->file_index]->ctx;
+ int j;
+
+ if (avf->nb_chapters > INT_MAX - size ||
+ !(pts = av_realloc_f(pts, size += avf->nb_chapters - 1,
+ sizeof(*pts)))) {
+ av_log(NULL, AV_LOG_FATAL,
+ "Could not allocate forced key frames array.\n");
+ exit(1);
+ }
+ t = p[8] ? parse_time_or_die("force_key_frames", p + 8, 1) : 0;
+ t = av_rescale_q(t, AV_TIME_BASE_Q, avctx->time_base);
+
+ for (j = 0; j < avf->nb_chapters; j++) {
+ AVChapter *c = avf->chapters[j];
+ av_assert1(index < size);
+ pts[index++] = av_rescale_q(c->start, c->time_base,
+ avctx->time_base) + t;
+ }
+
+ } else {
+
+ t = parse_time_or_die("force_key_frames", p, 1);
+ av_assert1(index < size);
+ pts[index++] = av_rescale_q(t, AV_TIME_BASE_Q, avctx->time_base);
+
+ }
p = next;
}
+
+ av_assert0(index == size);
+ qsort(pts, size, sizeof(*pts), compare_int64);
+ ost->forced_kf_count = size;
+ ost->forced_kf_pts = pts;
}
static void report_new_stream(int input_index, AVPacket *pkt)
--
1.7.10.4
More information about the ffmpeg-devel
mailing list