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

Michael Niedermayer michaelni
Tue Sep 23 04:24:46 CEST 2008


On Mon, Sep 22, 2008 at 11:36:54PM +0200, Stefano Sabatini wrote:
> On date Monday 2008-09-22 02:16:28 +0200, Michael Niedermayer encoded:
> > On Sun, Sep 21, 2008 at 11:21:23PM +0200, Stefano Sabatini wrote:
> > > On date Sunday 2008-09-21 22:16:56 +0200, Michael Niedermayer encoded:
> > > > On Sun, Sep 21, 2008 at 06:52:23PM +0200, Stefano Sabatini wrote:
> > > > > On date Sunday 2008-09-21 14:09:56 +0200, Michael Niedermayer encoded:
> > > > > > On Sun, Sep 21, 2008 at 12:52:57PM +0200, Stefano Sabatini wrote:
> > > > > [...]
> > > > > > > Index: libavutil/rational.c
> > > > > > > ===================================================================
> > > > > > > --- libavutil/rational.c	(revision 15372)
> > > > > > > +++ libavutil/rational.c	(working copy)
> > > > > > > @@ -101,3 +101,81 @@
> > > > > > >  
> > > > > > >      return a;
> > > > > > >  }
> > > > > > > +
> > > > > > > +int av_is_nearest_q(AVRational q, AVRational q1, AVRational q2)
> > > > > > > +{
> > > > > > > +    if (av_cmp_q(q1, q) * av_cmp_q(q, q2) > 0) {
> > > > > > > +        /* q1 and q2 on the opposite sides of q */
> > > > > > > +        /* N/D is q, A/B is the median between q1 and q2, A/B > N/D <=> A*D/B > N */
> > > > > > 
> > > > > > > +        int64_t x = av_rescale(q1.num * (int64_t)q2.den + q2.num * (int64_t)q1.den, q.den, 2 * (int64_t)q1.den * q2.den);
> > > > > > 
> > > > > > the rounding is not correct
> > > > > 
> > > > > I see that the type of rounding choosen may change the result of the
> > > > > comparation if the result isn't exact, but I can't currently figure
> > > > > out which is the correct one to apply.
> > > > > 
> > > > > Can you suggest which should I use?
> > > > 
> > > > to test A*D/B > N
> > > > the left side should be rounded toward inf
> > > 
> > > Sorry to insist on this, what if we have:
> > > 
> > > X = A*D/B
> > > X'= rnd(A*D/B, up), X' > X
> > > X < N but X' > N
> > > 
> > > Is this possible at all?
> > 
> > you have a real number r and a integer n
> > r' = rnd(r) = the smallest element x of Z that is x >= r
> > 
> > if we assume that there exists a r and n for which r < n and r' > n
> > then by the definition above r' is the smallest element of Z that is >= r
> > but n < r' and n > r
> > thus proof by contradiction
> >
> > > > > > > +        if (((x > q.num ? 1 : x < q.num ? -1 : 0) * av_cmp_q(q2, q1)) > 0)
> > > > > > > +            return 1;
> > > > > > > +    }
> > > > > > 
> > > > > > > +    /* q1 and q2 on the same side of q */
> > > > > > > +    else if (av_cmp_q(q, q1) * av_cmp_q(q1, q2) > 0)
> > > > > > 
> > > > > > i dont see why these special cases would be needed
> > > > > 
> > > > > The first condition:
> > > > > cmp(M, q) * cmp(q2, q1) == 1 
> > > > > 
> > > > > catches both the conditions:
> > > > > q1 ... q ... M ... q2
> > > > > M > q && q2 > q1
> > > > > and 
> > > > > q2 ... M ... q ... q1
> > > > > M < q && q2 < q1
> > > > > 
> > > > > (x > q.num ? 1 : x < q.num ? -1 : 0) corresponds to cmp(M, q).
> > > > > 
> > > > > The second condition:
> > > > > cmp(q, q1) * cmp(q1, q2) ==  1
> > > > > cathes both the conditions:
> > > > > q2 ... q1 ... q
> > > > > q > q1 && q1 > q2
> > > > > and 
> > > > > q ... q1 ... q2
> > > > > q < q1 && q1 < q2
> > > > > 
> > > > > I can't see how to simplify this...
> > > > 
> > > > what is the problem with the code for the first case handling the second?
> > > 
> > > Uh?
> > > 
> > > 1 if (q1 and q2 on opposite sides of q)
> > > 2    if (q1 nearest than q2)  // opposite sides context
> > > 3       return 1;
> > > 4 else // q1 and q2 are on the same side of q
> > > 5    if (q1 nearest than q2) // same side context)
> > > 6       return 1;
> > > 7 return 0;
> > > 
> > > Checks at points 1, 2 and 5 test different things, so I don't see how
> > > it would be possible to reuse the code of one test for another
> > > one. You we could make them parametric, but I'm not sure that would
> > > simplify the code, rather it would make it more obfuscated.
> > > 
> > > But I feel like I'm misunderstanding your point...
> > 
> > you have 2 point q1 and q2, the point exactly between them seperate
> > the 2 areas where q1 and q2 are closer.
> > Thus the code that finds out on whoch side of this seperating line q is
> > is sufficient and does not need a second special case to handly the case
> > of q1 and q2 being of the same side of q
> 
> Wow, thanks so much for the explanations Michael!
> 
> Now the code really looks simple and beatiful :-).
> 
> Regards.
> -- 
> FFmpeg = Frightening Friendly MultiPurpose Evil God

> Index: libavutil/rational.h
> ===================================================================
> --- libavutil/rational.h	(revision 15372)
> +++ libavutil/rational.h	(working copy)
> @@ -113,4 +113,17 @@
>   */
>  AVRational av_d2q(double d, int max) av_const;
>  
> +/**
> + * @return 1 if \q1 is nearer to \p than \p q2, 0 if \p q1 and \p q2
> + * have the same distance, -1 otherwise.
> + */
> +int av_near_cmp_q(AVRational q, AVRational q1, AVRational q2);

av_nearer_q()


> +
> +/**
> + * 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, const AVRational* q_list);
> +
>  #endif /* AVUTIL_RATIONAL_H */






> Index: libavutil/rational.c
> ===================================================================
> --- libavutil/rational.c	(revision 15372)
> +++ libavutil/rational.c	(working copy)
> @@ -101,3 +101,67 @@
>  
>      return a;
>  }
> +
> +int av_near_cmp_q(AVRational q, AVRational q1, AVRational q2)
> +{
> +    /* N/D is q, A/B is the median between q1 and q2, A/B > N/D <=> A*D/B > N */
> +    int64_t x = av_rescale_rnd(q1.num * (int64_t)q2.den + q2.num * (int64_t)q1.den, q.den, 2 * (int64_t)q1.den * q2.den, AV_ROUND_UP);
> +
> +    return (x > q.num ? 1 : x < q.num ? -1 : 0) * av_cmp_q(q2, q1);

I think only one of the 2 checks is correct for AV_ROUND_UP, the other would
be correct for AV_ROUND_DOWN.

example:
q=1/1
q1= 0/1
q2= 1/2

x= 1
x == q.num



[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Old school: Use the lowest level language in which you can solve the problem
            conveniently.
New school: Use the highest level language in which the latest supercomputer
            can solve the problem without the user falling asleep waiting.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20080923/54e92e22/attachment.pgp>



More information about the ffmpeg-devel mailing list