Skip to content

Commit 1565a9a

Browse files
committed
avformat/utils: factor rfps calculation out
Signed-off-by: Michael Niedermayer <[email protected]>
1 parent dc1b0a5 commit 1565a9a

File tree

2 files changed

+102
-67
lines changed

2 files changed

+102
-67
lines changed

libavformat/internal.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,4 +371,14 @@ int ff_generate_avci_extradata(AVStream *st);
371371
*/
372372
int ff_alloc_extradata(AVCodecContext *avctx, int size);
373373

374+
/**
375+
* add frame for rfps calculation.
376+
*
377+
* @param dts timestamp of the i-th frame
378+
* @return 0 if OK, AVERROR_xxx on error
379+
*/
380+
int ff_rfps_add_frame(AVFormatContext *ic, AVStream *st, int64_t dts);
381+
382+
void ff_rfps_calculate(AVFormatContext *ic);
383+
374384
#endif /* AVFORMAT_INTERNAL_H */

libavformat/utils.c

Lines changed: 92 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -2701,6 +2701,94 @@ int ff_alloc_extradata(AVCodecContext *avctx, int size)
27012701
return ret;
27022702
}
27032703

2704+
int ff_rfps_add_frame(AVFormatContext *ic, AVStream *st, int64_t ts)
2705+
{
2706+
int i, j;
2707+
int64_t last = st->info->last_dts;
2708+
2709+
if( ts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && ts > last
2710+
&& ts - (uint64_t)last < INT64_MAX){
2711+
double dts= (is_relative(ts) ? ts - RELATIVE_TS_BASE : ts) * av_q2d(st->time_base);
2712+
int64_t duration= ts - last;
2713+
2714+
if (!st->info->duration_error)
2715+
st->info->duration_error = av_mallocz(sizeof(st->info->duration_error[0])*2);
2716+
if (!st->info->duration_error)
2717+
return AVERROR(ENOMEM);
2718+
2719+
// if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
2720+
// av_log(NULL, AV_LOG_ERROR, "%f\n", dts);
2721+
for (i=0; i<MAX_STD_TIMEBASES; i++) {
2722+
int framerate= get_std_framerate(i);
2723+
double sdts= dts*framerate/(1001*12);
2724+
for(j=0; j<2; j++){
2725+
int64_t ticks= llrint(sdts+j*0.5);
2726+
double error= sdts - ticks + j*0.5;
2727+
st->info->duration_error[j][0][i] += error;
2728+
st->info->duration_error[j][1][i] += error*error;
2729+
}
2730+
}
2731+
st->info->duration_count++;
2732+
// ignore the first 4 values, they might have some random jitter
2733+
if (st->info->duration_count > 3 && is_relative(ts) == is_relative(last))
2734+
st->info->duration_gcd = av_gcd(st->info->duration_gcd, duration);
2735+
}
2736+
if (ts != AV_NOPTS_VALUE)
2737+
st->info->last_dts = ts;
2738+
2739+
return 0;
2740+
}
2741+
2742+
void ff_rfps_calculate(AVFormatContext *ic)
2743+
{
2744+
int i, j;
2745+
2746+
for (i = 0; i<ic->nb_streams; i++) {
2747+
AVStream *st = ic->streams[i];
2748+
2749+
if (st->codec->codec_type != AVMEDIA_TYPE_VIDEO)
2750+
continue;
2751+
// the check for tb_unreliable() is not completely correct, since this is not about handling
2752+
// a unreliable/inexact time base, but a time base that is finer than necessary, as e.g.
2753+
// ipmovie.c produces.
2754+
if (tb_unreliable(st->codec) && st->info->duration_count > 15 && st->info->duration_gcd > FFMAX(1, st->time_base.den/(500LL*st->time_base.num)) && !st->r_frame_rate.num)
2755+
av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, st->time_base.den, st->time_base.num * st->info->duration_gcd, INT_MAX);
2756+
if (st->info->duration_count>1 && !st->r_frame_rate.num
2757+
&& tb_unreliable(st->codec)) {
2758+
int num = 0;
2759+
double best_error= 0.01;
2760+
2761+
for (j=0; j<MAX_STD_TIMEBASES; j++) {
2762+
int k;
2763+
2764+
if(st->info->codec_info_duration && st->info->codec_info_duration*av_q2d(st->time_base) < (1001*12.0)/get_std_framerate(j))
2765+
continue;
2766+
if(!st->info->codec_info_duration && 1.0 < (1001*12.0)/get_std_framerate(j))
2767+
continue;
2768+
for(k=0; k<2; k++){
2769+
int n= st->info->duration_count;
2770+
double a= st->info->duration_error[k][0][j] / n;
2771+
double error= st->info->duration_error[k][1][j]/n - a*a;
2772+
2773+
if(error < best_error && best_error> 0.000000001){
2774+
best_error= error;
2775+
num = get_std_framerate(j);
2776+
}
2777+
if(error < 0.02)
2778+
av_log(NULL, AV_LOG_DEBUG, "rfps: %f %f\n", get_std_framerate(j) / 12.0/1001, error);
2779+
}
2780+
}
2781+
// do not increase frame rate by more than 1 % in order to match a standard rate.
2782+
if (num && (!st->r_frame_rate.num || (double)num/(12*1001) < 1.01 * av_q2d(st->r_frame_rate)))
2783+
av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, num, 12*1001, INT_MAX);
2784+
}
2785+
2786+
av_freep(&st->info->duration_error);
2787+
st->info->last_dts = AV_NOPTS_VALUE;
2788+
st->info->duration_count = 0;
2789+
}
2790+
}
2791+
27042792
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
27052793
{
27062794
int i, count, ret = 0, j;
@@ -2918,39 +3006,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
29183006
}
29193007
}
29203008
#if FF_API_R_FRAME_RATE
2921-
{
2922-
int64_t last = st->info->last_dts;
2923-
2924-
if( pkt->dts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && pkt->dts > last
2925-
&& pkt->dts - (uint64_t)last < INT64_MAX){
2926-
double dts= (is_relative(pkt->dts) ? pkt->dts - RELATIVE_TS_BASE : pkt->dts) * av_q2d(st->time_base);
2927-
int64_t duration= pkt->dts - last;
2928-
2929-
if (!st->info->duration_error)
2930-
st->info->duration_error = av_mallocz(sizeof(st->info->duration_error[0])*2);
2931-
if (!st->info->duration_error)
2932-
return AVERROR(ENOMEM);
2933-
2934-
// if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
2935-
// av_log(NULL, AV_LOG_ERROR, "%f\n", dts);
2936-
for (i=0; i<MAX_STD_TIMEBASES; i++) {
2937-
int framerate= get_std_framerate(i);
2938-
double sdts= dts*framerate/(1001*12);
2939-
for(j=0; j<2; j++){
2940-
int64_t ticks= llrint(sdts+j*0.5);
2941-
double error= sdts - ticks + j*0.5;
2942-
st->info->duration_error[j][0][i] += error;
2943-
st->info->duration_error[j][1][i] += error*error;
2944-
}
2945-
}
2946-
st->info->duration_count++;
2947-
// ignore the first 4 values, they might have some random jitter
2948-
if (st->info->duration_count > 3 && is_relative(pkt->dts) == is_relative(last))
2949-
st->info->duration_gcd = av_gcd(st->info->duration_gcd, duration);
2950-
}
2951-
if (pkt->dts != AV_NOPTS_VALUE)
2952-
st->info->last_dts = pkt->dts;
2953-
}
3009+
ff_rfps_add_frame(ic, st, pkt->dts);
29543010
#endif
29553011
if(st->parser && st->parser->parser->split && !st->codec->extradata){
29563012
int i= st->parser->parser->split(st->codec, pkt->data, pkt->size);
@@ -3006,6 +3062,9 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
30063062
st = ic->streams[i];
30073063
avcodec_close(st->codec);
30083064
}
3065+
3066+
ff_rfps_calculate(ic);
3067+
30093068
for(i=0;i<ic->nb_streams;i++) {
30103069
st = ic->streams[i];
30113070
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
@@ -3044,40 +3103,6 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
30443103
best_fps, 12*1001, INT_MAX);
30453104
}
30463105
}
3047-
// the check for tb_unreliable() is not completely correct, since this is not about handling
3048-
// a unreliable/inexact time base, but a time base that is finer than necessary, as e.g.
3049-
// ipmovie.c produces.
3050-
if (tb_unreliable(st->codec) && st->info->duration_count > 15 && st->info->duration_gcd > FFMAX(1, st->time_base.den/(500LL*st->time_base.num)) && !st->r_frame_rate.num)
3051-
av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, st->time_base.den, st->time_base.num * st->info->duration_gcd, INT_MAX);
3052-
if (st->info->duration_count>1 && !st->r_frame_rate.num
3053-
&& tb_unreliable(st->codec)) {
3054-
int num = 0;
3055-
double best_error= 0.01;
3056-
3057-
for (j=0; j<MAX_STD_TIMEBASES; j++) {
3058-
int k;
3059-
3060-
if(st->info->codec_info_duration && st->info->codec_info_duration*av_q2d(st->time_base) < (1001*12.0)/get_std_framerate(j))
3061-
continue;
3062-
if(!st->info->codec_info_duration && 1.0 < (1001*12.0)/get_std_framerate(j))
3063-
continue;
3064-
for(k=0; k<2; k++){
3065-
int n= st->info->duration_count;
3066-
double a= st->info->duration_error[k][0][j] / n;
3067-
double error= st->info->duration_error[k][1][j]/n - a*a;
3068-
3069-
if(error < best_error && best_error> 0.000000001){
3070-
best_error= error;
3071-
num = get_std_framerate(j);
3072-
}
3073-
if(error < 0.02)
3074-
av_log(NULL, AV_LOG_DEBUG, "rfps: %f %f\n", get_std_framerate(j) / 12.0/1001, error);
3075-
}
3076-
}
3077-
// do not increase frame rate by more than 1 % in order to match a standard rate.
3078-
if (num && (!st->r_frame_rate.num || (double)num/(12*1001) < 1.01 * av_q2d(st->r_frame_rate)))
3079-
av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, num, 12*1001, INT_MAX);
3080-
}
30813106

30823107
if (!st->r_frame_rate.num){
30833108
if( st->codec->time_base.den * (int64_t)st->time_base.num

0 commit comments

Comments
 (0)