Commit beb5d8f0 authored by Nicolas George's avatar Nicolas George

ffmpeg: accept "chapters" as forced key frames.

Allow to force a key frame at the beginning of each chapter.
parent 93815219
...@@ -555,9 +555,17 @@ Deprecated see -bsf ...@@ -555,9 +555,17 @@ Deprecated see -bsf
@item -force_key_frames[:@var{stream_specifier}] @var{time}[,@var{time}...] (@emph{output,per-stream}) @item -force_key_frames[:@var{stream_specifier}] @var{time}[,@var{time}...] (@emph{output,per-stream})
Force key frames at the specified timestamps, more precisely at the first Force key frames at the specified timestamps, more precisely at the first
frames after each specified time. frames after each specified time.
If one of the times is "@code{chapters}[@var{delta}]", it is expanded into
the time of the beginning of all chapters in the file, shifted by
@var{delta}, expressed as a time in seconds.
This option can be useful to ensure that a seek point is present at a 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. 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 key frames 0.1 second
before the beginning of every chapter:
@example
-force_key_frames 0:05:00,chapters-0.1
@end example
@item -copyinkf[:@var{stream_specifier}] (@emph{output,per-stream}) @item -copyinkf[:@var{stream_specifier}] (@emph{output,per-stream})
When doing stream copy, copy also non-key frames found at the When doing stream copy, copy also non-key frames found at the
......
...@@ -1931,19 +1931,25 @@ static InputStream *get_input_stream(OutputStream *ost) ...@@ -1931,19 +1931,25 @@ static InputStream *get_input_stream(OutputStream *ost)
return NULL; return NULL;
} }
static int compare_int64(const void *a, const void *b)
{
int64_t va = *(int64_t *)a, vb = *(int64_t *)b;
return va < vb ? -1 : va > vb ? +1 : 0;
}
static void parse_forced_key_frames(char *kf, OutputStream *ost, static void parse_forced_key_frames(char *kf, OutputStream *ost,
AVCodecContext *avctx) AVCodecContext *avctx)
{ {
char *p; char *p;
int n = 1, i; int n = 1, i, size, index = 0;
int64_t t; int64_t t, *pts;
for (p = kf; *p; p++) for (p = kf; *p; p++)
if (*p == ',') if (*p == ',')
n++; n++;
ost->forced_kf_count = n; size = n;
ost->forced_kf_pts = av_malloc(sizeof(*ost->forced_kf_pts) * n); pts = av_malloc(sizeof(*pts) * size);
if (!ost->forced_kf_pts) { if (!pts) {
av_log(NULL, AV_LOG_FATAL, "Could not allocate forced key frames array.\n"); av_log(NULL, AV_LOG_FATAL, "Could not allocate forced key frames array.\n");
exit(1); exit(1);
} }
...@@ -1955,11 +1961,43 @@ static void parse_forced_key_frames(char *kf, OutputStream *ost, ...@@ -1955,11 +1961,43 @@ static void parse_forced_key_frames(char *kf, OutputStream *ost,
if (next) if (next)
*next++ = 0; *next++ = 0;
t = parse_time_or_die("force_key_frames", p, 1); if (!memcmp(p, "chapters", 8)) {
ost->forced_kf_pts[i] = av_rescale_q(t, AV_TIME_BASE_Q, avctx->time_base);
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; 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) static void report_new_stream(int input_index, AVPacket *pkt)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment