[FFmpeg-devel] [PATCH] -force_key_frames option
Stefano Sabatini
stefano.sabatini-lala
Sat Oct 16 12:08:59 CEST 2010
On date Tuesday 2010-10-12 22:42:34 +0200, Nicolas George encoded:
> Le primidi 21 vend?miaire, an CCXIX, Nicolas George a ?crit?:
> > The attached patch implements a -forcekkey_frames option, similar to the one
> > I submitted to MPlayer last week.
>
> The attached patch implements it in a simpler way, using the change on
> AVOutputStream allocation that was just approved (but not yet applied).
>
> It works as expected and the regression tests still succeed.
>
> Regards,
>
> --
> Nicolas George
> Changelog | 1 +
> ffmpeg.c | 41 +++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 42 insertions(+), 0 deletions(-)
>
> diff --git a/Changelog b/Changelog
> index 607571e..ea45643 100644
> --- a/Changelog
> +++ b/Changelog
> @@ -46,6 +46,7 @@ version <next>:
> - RTP depacketization of the X-QT QuickTime format
> - SAP (Session Announcement Protocol, RFC 2974) muxer
> - cropdetect filter
> +- forced_key_frames option
*ffmpeg* option, also maybe -forced_key_frame is more useful (check
how it is done in the rest of the file).
> version 0.6:
> diff --git a/ffmpeg.c b/ffmpeg.c
> index 149f0a7..70674d4 100644
> --- a/ffmpeg.c
> +++ b/ffmpeg.c
> @@ -230,6 +230,7 @@ static int nb_frames_drop = 0;
> static int input_sync;
> static uint64_t limit_filesize = 0;
> static int force_fps = 0;
> +static char *forced_key_frames = NULL;
>
> static int pgmyuv_compatibility_hack=0;
> static float dts_delta_threshold = 10;
> @@ -290,6 +291,11 @@ typedef struct AVOutputStream {
> int original_leftBand;
> int original_rightBand;
>
> + /* forced key frames */
> + int64_t *forced_kf_pts;
> + int forced_kf_count;
> + int forced_kf_index;
> +
> /* audio only */
> int audio_resample;
> ReSampleContext *resample; /* for audio resampling */
> @@ -1333,6 +1339,11 @@ static void do_video_out(AVFormatContext *s,
> big_picture.pts= ost->sync_opts;
> // big_picture.pts= av_rescale(ost->sync_opts, AV_TIME_BASE*(int64_t)enc->time_base.num, enc->time_base.den);
> //av_log(NULL, AV_LOG_DEBUG, "%"PRId64" -> encoder\n", ost->sync_opts);
> + if (ost->forced_kf_index < ost->forced_kf_count &&
> + big_picture.pts >= ost->forced_kf_pts[ost->forced_kf_index]) {
> + big_picture.pict_type = FF_I_TYPE;
> + ost->forced_kf_index++;
> + }
> ret = avcodec_encode_video(enc,
> bit_buffer, bit_buffer_size,
> &big_picture);
> @@ -1978,6 +1989,29 @@ static int copy_chapters(int infile, int outfile)
> return 0;
> }
>
> +static void parse_forced_key_frames(char *kf, AVOutputStream *ost,
> + AVCodecContext *codec)
> +{
> + char *p;
> + int n = 1, i;
> + int64_t t;
> +
> + 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) {
> + av_log(NULL, AV_LOG_FATAL, "Could not allocate forced key frames array.\n");
> + ffmpeg_exit(1);
> + }
> + for (i = 0; i < n; i++) {
> + p = i ? strchr(p, ',') + 1 : kf;
> + t = parse_time_or_die("forced_key_frames", p, 1);
> + ost->forced_kf_pts[i] = av_rescale_q(t, AV_TIME_BASE_Q, codec->time_base);
> + }
> +}
> +
> /*
> * The following code is the main loop of the file converter
> */
> @@ -2730,6 +2764,7 @@ static int transcode(AVFormatContext **output_files,
> av_fifo_free(ost->fifo); /* works even if fifo is not
> initialized but set to zero */
> av_free(ost->pict_tmp.data[0]);
> + av_free(ost->forced_kf_pts);
> if (ost->video_resample)
> sws_freeContext(ost->img_resample_ctx);
> if (ost->resample)
> @@ -3542,6 +3577,9 @@ static void new_video_stream(AVFormatContext *oc, int file_idx)
> video_enc->flags |= CODEC_FLAG_PASS2;
> }
> }
> +
> + if (forced_key_frames)
> + parse_forced_key_frames(forced_key_frames, ost, video_enc);
> }
> if (video_language) {
> av_metadata_set2(&st->metadata, "language", video_language, 0);
> @@ -3551,6 +3589,7 @@ static void new_video_stream(AVFormatContext *oc, int file_idx)
> /* reset some key parameters */
> video_disable = 0;
> av_freep(&video_codec_name);
> + av_freep(&forced_key_frames);
> video_stream_copy = 0;
> frame_pix_fmt = PIX_FMT_NONE;
> }
> @@ -3868,6 +3907,7 @@ static void opt_output_file(const char *filename)
> set_context_opts(oc, avformat_opts, AV_OPT_FLAG_ENCODING_PARAM, NULL);
>
> nb_streamid_map = 0;
> + av_freep(&forced_key_frames);
> }
>
> /* same option as mencoder */
> @@ -4318,6 +4358,7 @@ static const OptionDef options[] = {
> { "qphist", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, { (void *)&qp_hist }, "show QP histogram" },
> { "force_fps", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&force_fps}, "force the selected framerate, disable the best supported framerate selection" },
> { "streamid", OPT_FUNC2 | HAS_ARG | OPT_EXPERT, {(void*)opt_streamid}, "set the value of an outfile streamid", "streamIndex:value" },
> + { "forced_key_frames", OPT_STRING | HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void *)&forced_key_frames}, "force key frames at specified timestamps" },
Missing ffmpeg-doc.texi docs.
BTW can you explain a scenario where using this option would be useful?
Thanks, regards.
--
FFmpeg = Fabulous and Fantastic Maxi Philosophical Exuberant Geek
More information about the ffmpeg-devel
mailing list