[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