[FFmpeg-devel] [PATCH] Implement in lavc a flag which makes avcodec_open() to choose the best framerate

Stefano Sabatini stefano.sabatini-lala
Fri Sep 19 00:29:03 CEST 2008


On date Sunday 2008-09-14 23:54:26 +0200, Stefano Sabatini encoded:
> On date Thursday 2008-09-11 23:44:18 +0200, Stefano Sabatini encoded:
> > On date Thursday 2008-09-11 05:52:01 +0200, Michael Niedermayer encoded:
> > > On Sun, Aug 31, 2008 at 08:58:53PM +0200, Stefano Sabatini wrote:
> [...]
> > > maybe returning an index into the list would be more flexible.
> > > Its easy to convert a index to the AVRational not easy though
> > > the other way around.
> > 
> > Yes my only doubt is about the name:
> > is av_find_nearest_q_idx OK?
> [...]
> > Index: libavutil/rational.h
> > ===================================================================
> > --- libavutil/rational.h	(revision 15295)
> > +++ libavutil/rational.h	(working copy)
> > @@ -113,4 +113,11 @@
> >   */
> >  AVRational av_d2q(double d, int max) av_const;
> >  
> > +/**
> > + * Finds the nearest value in \p q_list to \p q.
> > + * @param q_list an array of rationals terminated by {0, 0}
> > + * @return the index of the nearest value found in the array
> > + */
> > +int av_find_nearest_q_idx(AVRational q, AVRational* q_list);
> > +
> >  #endif /* AVUTIL_RATIONAL_H */
> > Index: libavutil/rational.c
> > ===================================================================
> > --- libavutil/rational.c	(revision 15295)
> > +++ libavutil/rational.c	(working copy)
> > @@ -101,3 +101,49 @@
> >  
> >      return a;
> >  }
> > +
> > +int av_find_nearest_q_idx(AVRational q, AVRational* q_list)
> > +{
> > +    int i, nearest_q_idx = 0;
> > +    AVRational best_error= (AVRational){INT_MAX, 1};
> > +    for(i=0; q_list[i].den; i++) {
> > +        AVRational error= av_sub_q(q, q_list[i]);
> > +        if(error.num <0) error.num *= -1;
> > +        if(av_cmp_q(error, best_error) < 0) {
> > +            best_error= error;
> > +            nearest_q_idx = i;
> > +        }
> > +    }
> > +    return nearest_q_idx;
> > +}
> > +
> > +#if TEST
> > +int main (void) {
> > +
> > +    AVRational list_q[] = {
> > +        {24000, 1001},
> > +        {   24,    1},
> > +        {   25,    1},
> > +        {30000, 1001},
> > +        {   30,    1},
> > +        {   50,    1},
> > +        {60000, 1001},
> > +        {   60,    1},
> > +        // Xing's 15fps: (9)
> > +        {   15,    1},
> > +        // libmpeg3's "Unofficial economy rates": (10-13)
> > +        {    5,    1},
> > +        {   10,    1},
> > +        {   12,    1},
> > +        {   15,    1},
> > +        {    0,    0},
> > +    };
> > +
> > +    AVRational q = { 42, 1};
> > +    AVRational nearest_q = list_q[av_find_nearest_q_idx(q, list_q)];
> > +#undef printf
> > +    printf ("q=%d/%d(%f), nearest_q=%d/%d(%f),\n",
> > +            q.num, q.den, (double)q.num/q.den,
> > +            nearest_q.num, nearest_q.den, (double)nearest_q.num/nearest_q.den);
> > +}
> > +#endif /* TEST */
> > Index: ffmpeg.c
> > ===================================================================
> > --- ffmpeg.c	(revision 15295)
> > +++ ffmpeg.c	(working copy)
> > @@ -208,6 +208,7 @@
> >  static int nb_frames_drop = 0;
> >  static int input_sync;
> >  static uint64_t limit_filesize = 0; //
> > +static int force_fps = 0;
> >  
> >  static int pgmyuv_compatibility_hack=0;
> >  static float dts_delta_threshold = 10;
> > @@ -3037,23 +3038,10 @@
> >  
> >          set_context_opts(video_enc, avctx_opts[CODEC_TYPE_VIDEO], AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM);
> >  
> > +        if (codec && codec->supported_framerates && !force_fps)
> > +            fps = codec->supported_framerates[av_find_nearest_q_idx(fps, codec->supported_framerates)];
> >          video_enc->time_base.den = fps.num;
> >          video_enc->time_base.num = fps.den;
> > -        if(codec && codec->supported_framerates){
> > -            const AVRational *p= codec->supported_framerates;
> > -            const AVRational *best=NULL;
> > -            AVRational best_error= (AVRational){INT_MAX, 1};
> > -            for(; p->den!=0; p++){
> > -                AVRational error= av_sub_q(fps, *p);
> > -                if(error.num <0) error.num *= -1;
> > -                if(av_cmp_q(error, best_error) < 0){
> > -                    best_error= error;
> > -                    best= p;
> > -                }
> > -            }
> > -            video_enc->time_base.den= best->num;
> > -            video_enc->time_base.num= best->den;
> > -        }
> >  
> >          video_enc->width = frame_width + frame_padright + frame_padleft;
> >          video_enc->height = frame_height + frame_padtop + frame_padbottom;
> > @@ -3852,6 +3840,7 @@
> >      { "vtag", HAS_ARG | OPT_EXPERT | OPT_VIDEO, {(void*)opt_video_tag}, "force video tag/fourcc", "fourcc/tag" },
> >      { "newvideo", OPT_VIDEO, {(void*)opt_new_video_stream}, "add a new video stream to the current output stream" },
> >      { "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" },
> >  
> >      /* audio options */
> >      { "ab", OPT_FUNC2 | HAS_ARG | OPT_AUDIO, {(void*)opt_bitrate}, "set bitrate (in bits/s)", "bitrate" },
> 
> Ping? (As I already wrote I'll remove the test and split the patch
> before to commit).

I'll apply it in the weekend if no one has objections or better ideas
for the av_find_nearest_q_idx() function name.

Regards.
-- 
FFmpeg = Funny and Foolish Mythic Portentous EniGma




More information about the ffmpeg-devel mailing list