diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2011-09-16 20:40:08 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2011-09-16 21:29:58 +0200 |
commit | 5c5306df962bbbaf6a3339850aa43771fc4add19 (patch) | |
tree | 3163071b84f94fde85a9d75f6a11771a0e1eeb7e /libavformat | |
parent | e3fc0e8280221639be9b02b27ab8fee2dd2b1b29 (diff) | |
download | ffmpeg-5c5306df962bbbaf6a3339850aa43771fc4add19.tar.gz |
lavf/utils: rewrite real fps calculation code.
The new code is free of biasing to the first timestamps
Fixes fraps.fps.test.zip
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat')
-rw-r--r-- | libavformat/avformat.h | 2 | ||||
-rw-r--r-- | libavformat/utils.c | 44 |
2 files changed, 28 insertions, 18 deletions
diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 4315710e31..40ba81b01e 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -646,7 +646,7 @@ typedef struct AVStream { int64_t last_dts; int64_t duration_gcd; int duration_count; - double duration_error[MAX_STD_TIMEBASES]; + double duration_error[2][2][MAX_STD_TIMEBASES]; int64_t codec_info_duration; } *info; diff --git a/libavformat/utils.c b/libavformat/utils.c index 49d79e1eef..86212aa15b 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -2431,17 +2431,19 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) int64_t duration= pkt->dts - last; if(pkt->dts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && duration>0){ - double dur= duration * av_q2d(st->time_base); + double dts= pkt->dts * av_q2d(st->time_base); // if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO) // av_log(NULL, AV_LOG_ERROR, "%f\n", dur); - if (st->info->duration_count < 2) - memset(st->info->duration_error, 0, sizeof(st->info->duration_error)); - for (i=1; i<FF_ARRAY_ELEMS(st->info->duration_error); i++) { + for (i=1; i<FF_ARRAY_ELEMS(st->info->duration_error[0][0]); i++) { int framerate= get_std_framerate(i); - int ticks= lrintf(dur*framerate/(1001*12)); - double error= dur - ticks*1001*12/(double)framerate; - st->info->duration_error[i] += error*error; + double sdts= dts*framerate/(1001*12); + for(j=0; j<2; j++){ + int ticks= lrintf(sdts+j*0.5); + double error= sdts - ticks + j*0.5; + st->info->duration_error[j][0][i] += error; + st->info->duration_error[j][1][i] += error*error; + } } st->info->duration_count++; // ignore the first 4 values, they might have some random jitter @@ -2505,16 +2507,24 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) //FIXME we should not special-case MPEG-2, but this needs testing with non-MPEG-2 ... st->time_base.num*duration_sum[i]/st->info->duration_count*101LL > st->time_base.den*/){ int num = 0; - double best_error= 2*av_q2d(st->time_base); - best_error = best_error*best_error*st->info->duration_count*1000*12*30; - - for (j=1; j<FF_ARRAY_ELEMS(st->info->duration_error); j++) { - double error = st->info->duration_error[j] * get_std_framerate(j); -// if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO) -// av_log(NULL, AV_LOG_ERROR, "%f %f\n", get_std_framerate(j) / 12.0/1001, error); - if(error < best_error){ - best_error= error; - num = get_std_framerate(j); + double best_error= 0.01; + + for (j=1; j<FF_ARRAY_ELEMS(st->info->duration_error[0][0]); j++) { + int k; + + if(st->info->codec_info_duration && st->info->codec_info_duration*av_q2d(st->time_base) < (1001*12.0)/get_std_framerate(j)) + continue; + for(k=0; k<2; k++){ + int n= st->info->duration_count; + double a= st->info->duration_error[k][0][j] / n; + double error= st->info->duration_error[k][1][j]/n - a*a; + + if(error < best_error && best_error> 0.000000001){ + best_error= error; + num = get_std_framerate(j); + } + if(error < 0.02) + av_log(NULL, AV_LOG_DEBUG, "rfps: %f %f\n", get_std_framerate(j) / 12.0/1001, error); } } // do not increase frame rate by more than 1 % in order to match a standard rate. |