[FFmpeg-devel] [PATCH v2] lavf/movenc: suggest video_track_timescale for invalid timescale
Mark Thompson
sw at jkqxz.net
Wed Oct 12 15:44:52 EEST 2016
On 12/10/16 11:04, Carl Eugen Hoyos wrote:
> 2016-10-11 21:06 GMT+02:00 Josh de Kock <josh at itanimul.li>:
>> Fixes ticket #5882.
>
> I don't object but I don't think it is correct.
>
>> While it doesn't automatically set the timescale
>> for the user as that would destroy data without prompt, it will tell
>> the user how they could set the timescale (as this is mostly likely
>> what they want).
>>
>> Signed-off-by: Josh de Kock <josh at itanimul.li>
>> ---
>>
>>> Would it be useful to print the max duration?
>> I'm not entirely sure, open to suggestions though.
>>
>> libavformat/movenc.c | 9 +++++++--
>> 1 file changed, 7 insertions(+), 2 deletions(-)
>>
>> diff --git a/libavformat/movenc.c b/libavformat/movenc.c
>> index d7c7158..6bada25 100644
>> --- a/libavformat/movenc.c
>> +++ b/libavformat/movenc.c
>> @@ -5677,11 +5677,16 @@ static int mov_write_header(AVFormatContext *s)
>> ret = AVERROR(EINVAL);
>> goto error;
>> }
>> - if (track->mode == MODE_MOV && track->timescale > 100000)
>> + if (track->mode == MODE_MOV && track->timescale > 100000) {
>> + /* NOTE: forcing setting the suggested timescale manually means ffmpeg won't destroy
>> + * timestamps without explicit instruction. */
>
>> + unsigned int suggested = (unsigned int)av_rescale(st->time_base.den, 1000, st->time_base.num);
>
> If we go this way (I am not completely convinced about it), we definitely need
> a heuristic that suggests 24000 for 10000000/417083 fps and 30000 if applicable.
How about the approach in the test program below? This makes the whole timebase
fraction; the suggested timescale would then be the denominator of that. (It is
currently just a program linked with lavu, I could make it into a patch if
someone else thinks this might actually be a good idea. It would need better
error handling and some thoughts about overflow, too.)
It shows that we can do significantly better in the 417083/10000000 case than
any of the currently-suggested approaches (divide by 1000, guess 1/24 or
1001/24000):
$ ./a.out 417083 10000000 100000
3715/89071
$ bc -l
417083/10000000
.04170830000000000000
3715/89071
.04170830012012888594
417/10000
.04170000000000000000
1/24
.04166666666666666666
1001/24000
.04170833333333333333
(The suggested timescale value would be 89071.)
---
#include <stdio.h>
#include "libavutil/rational.h"
AVRational av_rational_reduce(AVRational qi, int max_den)
{
AVRational qc = qi;
AVRational q0 = { 0, 1 };
AVRational q1 = { 1, 0 };
AVRational q2;
int a, t, k;
if (qc.den <= max_den)
return qc;
while (1) {
a = qc.num / qc.den;
q2.num = q0.num + a * q1.num;
q2.den = q0.den + a * q1.den;
if (q2.den > max_den)
break;
q0 = q1;
q1 = q2;
t = qc.num;
qc.num = qc.den;
qc.den = t - a * qc.den;
}
k = (max_den - q0.den) / q1.den;
q2.num = q0.num + k * q1.num;
q2.den = q0.den + k * q1.den;
if (av_nearer_q(qi, q1, q2) >= 0)
return q1;
else
return q2;
}
int main(int argc, char **argv)
{
AVRational ri, ro;
int max;
sscanf(argv[1], "%d", &ri.num);
sscanf(argv[2], "%d", &ri.den);
sscanf(argv[3], "%d", &max);
ro = av_rational_reduce(ri, max);
printf("%d/%d\n", ro.num, ro.den);
return 0;
}
More information about the ffmpeg-devel
mailing list