Commit 14bea432 authored by Michael Niedermayer's avatar Michael Niedermayer
Browse files

per context frame_rate_base, this should finally fix frame_rate related av sync issues

Originally committed as revision 1666 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 586bc755
......@@ -90,7 +90,8 @@ static int frame_topBand = 0;
static int frame_bottomBand = 0;
static int frame_leftBand = 0;
static int frame_rightBand = 0;
static int frame_rate = 25 * FRAME_RATE_BASE;
static int frame_rate = 25;
static int frame_rate_base = 1;
static int video_bit_rate = 200*1000;
static int video_bit_rate_tolerance = 4000*1000;
static int video_qscale = 0;
......@@ -746,7 +747,7 @@ static void do_video_stats(AVFormatContext *os, AVOutputStream *ost,
if (ti1 < 0.01)
ti1 = 0.01;
bitrate = (double)(frame_size * 8) * enc->frame_rate / FRAME_RATE_BASE / 1000.0;
bitrate = (double)(frame_size * 8) * enc->frame_rate / enc->frame_rate_base / 1000.0;
avg_bitrate = (double)(total_size * 8) / ti1 / 1000.0;
fprintf(fvstats, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ",
(double)total_size / 1024, ti1, bitrate, avg_bitrate);
......@@ -974,6 +975,7 @@ static int av_encode(AVFormatContext **output_files,
break;
case CODEC_TYPE_VIDEO:
codec->frame_rate = icodec->frame_rate;
codec->frame_rate_base = icodec->frame_rate_base;
codec->width = icodec->width;
codec->height = icodec->height;
break;
......@@ -1361,7 +1363,7 @@ static int av_encode(AVFormatContext **output_files,
/* frame rate emulation */
if (ist->st->codec.rate_emu) {
int64_t pts = ((int64_t) ist->frame * FRAME_RATE_BASE * 1000000) / (ist->st->codec.frame_rate);
int64_t pts = av_rescale((int64_t) ist->frame * ist->st->codec.frame_rate_base, 1000000, ist->st->codec.frame_rate);
int64_t now = av_gettime() - ist->start;
if (pts > now)
usleep(pts - now);
......@@ -1673,7 +1675,9 @@ static void opt_debug(const char *arg)
static void opt_frame_rate(const char *arg)
{
frame_rate = (int)(strtod(arg, 0) * FRAME_RATE_BASE);
frame_rate_base = DEFAULT_FRAME_RATE_BASE; //FIXME not optimal
frame_rate = (int)(strtod(arg, 0) * frame_rate_base + 0.5);
//FIXME parse fractions
}
......@@ -2051,7 +2055,7 @@ static void opt_input_file(const char *filename)
{
AVFormatContext *ic;
AVFormatParameters params, *ap = &params;
int err, i, ret, rfps;
int err, i, ret, rfps, rfps_base;
if (!strcmp(filename, "-"))
filename = "pipe:";
......@@ -2061,6 +2065,7 @@ static void opt_input_file(const char *filename)
ap->sample_rate = audio_sample_rate;
ap->channels = audio_channels;
ap->frame_rate = frame_rate;
ap->frame_rate_base = frame_rate_base;
ap->width = frame_width;
ap->height = frame_height;
ap->image_format = image_format;
......@@ -2092,7 +2097,8 @@ static void opt_input_file(const char *filename)
case CODEC_TYPE_VIDEO:
frame_height = enc->height;
frame_width = enc->width;
rfps = ic->streams[i]->r_frame_rate;
rfps = ic->streams[i]->r_frame_rate;
rfps_base = ic->streams[i]->r_frame_rate_base;
enc->workaround_bugs = workaround_bugs;
enc->error_resilience = error_resilience;
enc->error_concealment = error_concealment;
......@@ -2106,13 +2112,15 @@ static void opt_input_file(const char *filename)
if(bitexact)
enc->flags|= CODEC_FLAG_BITEXACT;
if (enc->frame_rate != rfps) {
assert(enc->frame_rate_base == rfps_base); // should be true for now
if (enc->frame_rate != rfps) {
fprintf(stderr,"\nSeems that stream %d comes from film source: %2.2f->%2.2f\n",
i, (float)enc->frame_rate / FRAME_RATE_BASE,
(float)rfps / FRAME_RATE_BASE);
i, (float)enc->frame_rate / enc->frame_rate_base,
(float)rfps / rfps_base);
}
/* update the current frame rate to match the stream frame rate */
frame_rate = rfps;
frame_rate = rfps;
frame_rate_base = rfps_base;
enc->rate_emu = rate_emu;
break;
......@@ -2241,6 +2249,7 @@ static void opt_output_file(const char *filename)
video_enc->bit_rate = video_bit_rate;
video_enc->bit_rate_tolerance = video_bit_rate_tolerance;
video_enc->frame_rate = frame_rate;
video_enc->frame_rate_base = frame_rate_base;
video_enc->width = frame_width;
video_enc->height = frame_height;
......@@ -2492,8 +2501,12 @@ static void prepare_grab(void)
vp->width = enc->width;
if (enc->height > vp->height)
vp->height = enc->height;
if (enc->frame_rate > vp->frame_rate)
vp->frame_rate = enc->frame_rate;
assert(enc->frame_rate_base == DEFAULT_FRAME_RATE_BASE);
if (enc->frame_rate > vp->frame_rate){
vp->frame_rate = enc->frame_rate;
vp->frame_rate_base = enc->frame_rate_base;
}
has_video = 1;
break;
default:
......@@ -2517,7 +2530,8 @@ static void prepare_grab(void)
exit(1);
}
/* by now video grab has one stream */
ic->streams[0]->r_frame_rate = vp->frame_rate;
ic->streams[0]->r_frame_rate = vp->frame_rate;
ic->streams[0]->r_frame_rate_base = vp->frame_rate_base;
input_files[nb_input_files] = ic;
dump_format(ic, nb_input_files, "", 0);
nb_input_files++;
......
......@@ -1725,7 +1725,7 @@ static void compute_stats(HTTPContext *c)
case CODEC_TYPE_VIDEO:
type = "video";
sprintf(parameters, "%dx%d, q=%d-%d, fps=%d", st->codec.width, st->codec.height,
st->codec.qmin, st->codec.qmax, st->codec.frame_rate / FRAME_RATE_BASE);
st->codec.qmin, st->codec.qmax, st->codec.frame_rate / st->codec.frame_rate_base);
break;
default:
av_abort();
......@@ -1950,7 +1950,7 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt)
(int64_t)s->pts_num * st->codec.sample_rate);
break;
case CODEC_TYPE_VIDEO:
st->pts_incr = (int64_t)s->pts_den * FRAME_RATE_BASE;
st->pts_incr = (int64_t)s->pts_den * st->codec.frame_rate_base;
av_frac_init(&st->pts, st->pts.val, 0,
(int64_t)s->pts_num * st->codec.frame_rate);
break;
......@@ -2018,7 +2018,7 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt)
(int64_t)s->pts_num * st->codec.sample_rate);
break;
case CODEC_TYPE_VIDEO:
st->pts_incr = (int64_t)s->pts_den * FRAME_RATE_BASE;
st->pts_incr = (int64_t)s->pts_den * st->codec.frame_rate_base;
av_frac_init(&st->pts, st->pts.val, 0,
(int64_t)s->pts_num * st->codec.frame_rate);
break;
......@@ -3219,6 +3219,7 @@ static int add_av_stream(FFStream *feed, AVStream *st)
if (av1->width == av->width &&
av1->height == av->height &&
av1->frame_rate == av->frame_rate &&
av1->frame_rate_base == av->frame_rate_base &&
av1->gop_size == av->gop_size)
goto found;
break;
......@@ -3406,6 +3407,7 @@ static void build_feed_streams(void)
matches = 0;
} else if (ccf->codec_type == CODEC_TYPE_VIDEO) {
if (CHECK_CODEC(frame_rate) ||
CHECK_CODEC(frame_rate_base) ||
CHECK_CODEC(width) ||
CHECK_CODEC(height)) {
printf("Codec width, height and framerate do not match for stream %d\n", i);
......@@ -3553,8 +3555,10 @@ static void add_codec(FFStream *stream, AVCodecContext *av)
case CODEC_TYPE_VIDEO:
if (av->bit_rate == 0)
av->bit_rate = 64000;
if (av->frame_rate == 0)
av->frame_rate = 5 * FRAME_RATE_BASE;
if (av->frame_rate == 0){
av->frame_rate = 5;
av->frame_rate_base = 1;
}
if (av->width == 0 || av->height == 0) {
av->width = 160;
av->height = 128;
......@@ -4017,7 +4021,8 @@ static int parse_ffconfig(const char *filename)
} else if (!strcasecmp(cmd, "VideoFrameRate")) {
get_arg(arg, sizeof(arg), &p);
if (stream) {
video_enc.frame_rate = (int)(strtod(arg, NULL) * FRAME_RATE_BASE);
video_enc.frame_rate_base= DEFAULT_FRAME_RATE_BASE;
video_enc.frame_rate = (int)(strtod(arg, NULL) * video_enc.frame_rate_base);
}
} else if (!strcasecmp(cmd, "VideoGopSize")) {
get_arg(arg, sizeof(arg), &p);
......
......@@ -192,7 +192,8 @@ void video_encode_example(const char *filename)
c->width = 352;
c->height = 288;
/* frames per second */
c->frame_rate = 25 * FRAME_RATE_BASE;
c->frame_rate = 25;
c->frame_rate_base= 1;
c->gop_size = 10; /* emit one intra frame every ten frames */
/* open it */
......
......@@ -186,8 +186,6 @@ static const int Motion_Est_QTab[] = { ME_ZERO, ME_PHODS, ME_LOG,
#define CODEC_CAP_PARSE_ONLY 0x0004
#define CODEC_CAP_TRUNCATED 0x0008
#define FRAME_RATE_BASE 10010
#define FF_COMMON_FRAME \
uint8_t *data[4];\
int linesize[4];\
......@@ -321,6 +319,7 @@ typedef struct AVFrame {
FF_COMMON_FRAME
} AVFrame;
#define DEFAULT_FRAME_RATE_BASE 1001000
/**
* main external api structure.
......@@ -375,13 +374,21 @@ typedef struct AVCodecContext {
/* video only */
/**
* frames per sec multiplied by FRAME_RATE_BASE.
* frames per sec multiplied by frame_rate_base.
* for variable fps this is the precission, so if the timestamps
* can be specified in msec precssion then this is 1000*FRAME_RATE_BASE
* can be specified in msec precssion then this is 1000*frame_rate_base
* - encoding: MUST be set by user
* - decoding: set by lavc. 0 or the frame_rate if available
*/
int frame_rate;
/**
* frame_rate_base.
* for variable fps this is 1
* - encoding: set by user.
* - decoding: set by lavc.
*/
int frame_rate_base;
/**
* width / height.
......@@ -1258,6 +1265,20 @@ void avcodec_register_all(void);
void avcodec_flush_buffers(AVCodecContext *avctx);
/* misc usefull functions */
/**
* reduce a fraction.
* this is usefull for framerate calculations
* @param max the maximum allowed for dst_nom & dst_den
* @return 1 if exact, 0 otherwise
*/
int av_reduce(int *dst_nom, int *dst_den, int64_t nom, int64_t den, int64_t max);
/**
* rescale a 64bit integer.
* a simple a*b/c isnt possible as it can overflow
*/
int64_t av_rescale(int64_t a, int b, int c);
/**
......
......@@ -341,7 +341,7 @@ void free_vlc(VLC *vlc)
av_free(vlc->table);
}
int ff_gcd(int a, int b){
int64_t ff_gcd(int64_t a, int64_t b){
if(b) return ff_gcd(b, a%b);
else return a;
}
......
......@@ -876,7 +876,7 @@ static inline int clip(int a, int amin, int amax)
/* math */
extern const uint8_t ff_sqrt_tab[128];
int ff_gcd(int a, int b);
int64_t ff_gcd(int64_t a, int64_t b);
static inline int ff_sqrt(int a)
{
......
......@@ -537,16 +537,17 @@ static int dvvideo_decode_frame(AVCodecContext *avctx,
/* init size */
width = 720;
if (dsf) {
avctx->frame_rate = 25 * FRAME_RATE_BASE;
avctx->frame_rate = 25;
packet_size = PAL_FRAME_SIZE;
height = 576;
nb_dif_segs = 12;
} else {
avctx->frame_rate = 30 * FRAME_RATE_BASE;
avctx->frame_rate = 30;
packet_size = NTSC_FRAME_SIZE;
height = 480;
nb_dif_segs = 10;
}
avctx->frame_rate_base= 1;
/* NOTE: we only accept several full frames */
if (buf_size < packet_size)
return -1;
......
......@@ -164,8 +164,8 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number)
s->gob_number = 0;
put_bits(&s->pb, 22, 0x20); /* PSC */
put_bits(&s->pb, 8, (((int64_t)s->picture_number * 30 * FRAME_RATE_BASE) /
s->frame_rate) & 0xff);
put_bits(&s->pb, 8, (((int64_t)s->picture_number * 30 * s->avctx->frame_rate_base) /
s->avctx->frame_rate) & 0xff);
put_bits(&s->pb, 1, 1); /* marker */
put_bits(&s->pb, 1, 0); /* h263 id */
......@@ -1587,16 +1587,16 @@ void ff_set_mpeg4_time(MpegEncContext * s, int picture_number){
int time_div, time_mod;
if(s->pict_type==I_TYPE){ //we will encode a vol header
s->time_increment_resolution= s->frame_rate/ff_gcd(s->frame_rate, FRAME_RATE_BASE);
if(s->time_increment_resolution>=256*256) s->time_increment_resolution= 256*128;
int dummy;
av_reduce(&s->time_increment_resolution, &dummy, s->avctx->frame_rate, s->avctx->frame_rate_base, (1<<16)-1);
s->time_increment_bits = av_log2(s->time_increment_resolution - 1) + 1;
}
if(s->current_picture.pts)
s->time= (s->current_picture.pts*s->time_increment_resolution + 500*1000)/(1000*1000);
else
s->time= picture_number*(int64_t)FRAME_RATE_BASE*s->time_increment_resolution/s->frame_rate;
s->time= av_rescale(picture_number*(int64_t)s->avctx->frame_rate_base, s->time_increment_resolution, s->avctx->frame_rate);
time_div= s->time/s->time_increment_resolution;
time_mod= s->time%s->time_increment_resolution;
......
......@@ -203,8 +203,10 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s)
int i, dmin, d;
s->frame_rate_index = 0;
dmin = 0x7fffffff;
for(i=1;i<9;i++) {
d = abs(s->frame_rate - frame_rate_tab[i]);
for(i=1;i<14;i++) {
if(s->avctx->strict_std_compliance >= 0 && i>=9) break;
d = abs(MPEG1_FRAME_RATE_BASE*(int64_t)s->avctx->frame_rate/s->avctx->frame_rate_base - frame_rate_tab[i]);
if (d < dmin) {
dmin = d;
s->frame_rate_index = i;
......@@ -248,22 +250,22 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s)
/* time code : we must convert from the real frame rate to a
fake mpeg frame rate in case of low frame rate */
fps = frame_rate_tab[s->frame_rate_index];
time_code = (int64_t)s->fake_picture_number * FRAME_RATE_BASE;
time_code = (int64_t)s->fake_picture_number * MPEG1_FRAME_RATE_BASE;
s->gop_picture_number = s->fake_picture_number;
put_bits(&s->pb, 5, (uint32_t)((time_code / (fps * 3600)) % 24));
put_bits(&s->pb, 6, (uint32_t)((time_code / (fps * 60)) % 60));
put_bits(&s->pb, 1, 1);
put_bits(&s->pb, 6, (uint32_t)((time_code / fps) % 60));
put_bits(&s->pb, 6, (uint32_t)((time_code % fps) / FRAME_RATE_BASE));
put_bits(&s->pb, 6, (uint32_t)((time_code % fps) / MPEG1_FRAME_RATE_BASE));
put_bits(&s->pb, 1, 1); /* closed gop */
put_bits(&s->pb, 1, 0); /* broken link */
}
if (s->frame_rate < (24 * FRAME_RATE_BASE) && s->picture_number > 0) {
if (s->avctx->frame_rate < (24 * s->avctx->frame_rate_base) && s->picture_number > 0) {
/* insert empty P pictures to slow down to the desired
frame rate. Each fake pictures takes about 20 bytes */
fps = frame_rate_tab[s->frame_rate_index];
n = (((int64_t)s->picture_number * fps) / s->frame_rate) - 1;
n = av_rescale((int64_t)s->picture_number * s->avctx->frame_rate_base, fps, s->avctx->frame_rate) / MPEG1_FRAME_RATE_BASE - 1;
while (s->fake_picture_number < n) {
mpeg1_skip_picture(s, s->fake_picture_number -
s->gop_picture_number);
......@@ -1638,8 +1640,13 @@ static void mpeg_decode_sequence_extension(MpegEncContext *s)
s->low_delay = get_bits1(&s->gb);
frame_rate_ext_n = get_bits(&s->gb, 2);
frame_rate_ext_d = get_bits(&s->gb, 5);
if (frame_rate_ext_d >= 1)
s->frame_rate = (s->frame_rate * frame_rate_ext_n) / frame_rate_ext_d;
av_reduce(
&s->avctx->frame_rate,
&s->avctx->frame_rate_base,
frame_rate_tab[s->frame_rate_index] * (frame_rate_ext_n+1),
MPEG1_FRAME_RATE_BASE * (frame_rate_ext_d+1),
1<<30);
dprintf("sequence extension\n");
s->mpeg2 = 1;
s->avctx->sub_id = 2; /* indicates mpeg2 found */
......@@ -1990,13 +1997,13 @@ static int mpeg1_decode_sequence(AVCodecContext *avctx,
s->avctx = avctx;
avctx->width = width;
avctx->height = height;
if (s->frame_rate_index >= 9) {
/* at least give a valid frame rate (some old mpeg1 have this) */
avctx->frame_rate = 25 * FRAME_RATE_BASE;
} else {
avctx->frame_rate = frame_rate_tab[s->frame_rate_index];
}
s->frame_rate = avctx->frame_rate;
av_reduce(
&avctx->frame_rate,
&avctx->frame_rate_base,
frame_rate_tab[s->frame_rate_index],
MPEG1_FRAME_RATE_BASE, //FIXME store in allready reduced form
1<<30
);
avctx->bit_rate = s->bit_rate;
if (MPV_common_init(s) < 0)
......
......@@ -385,16 +385,28 @@ static const uint8_t mbMotionVectorTable[17][2] = {
{ 0xc, 10 },
};
static const int frame_rate_tab[9] = {
0,
24000 * FRAME_RATE_BASE / 1001,
24000 * FRAME_RATE_BASE / 1000,
25000 * FRAME_RATE_BASE / 1000,
30000 * FRAME_RATE_BASE / 1001,
30000 * FRAME_RATE_BASE / 1000,
50000 * FRAME_RATE_BASE / 1000,
60000 * FRAME_RATE_BASE / 1001,
60000 * FRAME_RATE_BASE / 1000,
#define MPEG1_FRAME_RATE_BASE 1001
static const int frame_rate_tab[16] = {
0,
24000,
24024,
25025,
30000,
30030,
50050,
60000,
60060,
// Xing's 15fps: (9)
15015,
// libmpeg3's "Unofficial economy rates": (10-13)
5005,
10010,
12012,
15015,
// random, just to avoid segfault !never encode these
25025,
25025,
};
static const uint8_t non_linear_qscale[32] = {
......
......@@ -504,7 +504,6 @@ int MPV_encode_init(AVCodecContext *avctx)
s->bit_rate = avctx->bit_rate;
s->bit_rate_tolerance = avctx->bit_rate_tolerance;
s->frame_rate = avctx->frame_rate;
s->width = avctx->width;
s->height = avctx->height;
if(avctx->gop_size > 600){
......@@ -557,7 +556,8 @@ int MPV_encode_init(AVCodecContext *avctx)
switch(avctx->codec->id) {
case CODEC_ID_MPEG1VIDEO:
s->out_format = FMT_MPEG1;
avctx->delay=0; //FIXME not sure, should check the spec
s->low_delay= 0; //s->max_b_frames ? 0 : 1;
avctx->delay= s->low_delay ? 0 : (s->max_b_frames + 1);
break;
case CODEC_ID_MJPEG:
s->out_format = FMT_MJPEG;
......
......@@ -192,7 +192,6 @@ typedef struct MpegEncContext {
/* the following parameters must be initialized before encoding */
int width, height;///< picture size. must be a multiple of 16
int gop_size;
int frame_rate; ///< number of frames per second
int intra_only; ///< if true, only intra pictures are generated
int bit_rate; ///< wanted bit rate
int bit_rate_tolerance; ///< amount of +- bits (>0)
......
......@@ -435,7 +435,7 @@ void msmpeg4_encode_picture_header(MpegEncContext * s, int picture_number)
void msmpeg4_encode_ext_header(MpegEncContext * s)
{
put_bits(&s->pb, 5, s->frame_rate / FRAME_RATE_BASE); //yes 29.97 -> 29
put_bits(&s->pb, 5, s->avctx->frame_rate / s->avctx->frame_rate_base); //yes 29.97 -> 29
put_bits(&s->pb, 11, FFMIN(s->bit_rate/1024, 2047));
......
......@@ -164,7 +164,7 @@ int ff_rate_control_init(MpegEncContext *s)
bits= rce.i_tex_bits + rce.p_tex_bits;
q= get_qscale(s, &rce, rcc->pass1_wanted_bits/rcc->pass1_rc_eq_output_sum, i);
rcc->pass1_wanted_bits+= s->bit_rate/(s->frame_rate / (double)FRAME_RATE_BASE);
rcc->pass1_wanted_bits+= s->bit_rate/(s->avctx->frame_rate / (double)s->avctx->frame_rate_base);
}
}
......@@ -197,7 +197,7 @@ static inline double bits2qp(RateControlEntry *rce, double bits){
static void update_rc_buffer(MpegEncContext *s, int frame_size){
RateControlContext *rcc= &s->rc_context;
const double fps= (double)s->frame_rate / FRAME_RATE_BASE;
const double fps= (double)s->avctx->frame_rate / (double)s->avctx->frame_rate_base;
const double buffer_size= s->avctx->rc_buffer_size;
const double min_rate= s->avctx->rc_min_rate/fps;
const double max_rate= s->avctx->rc_max_rate/fps;
......@@ -571,7 +571,7 @@ float ff_rate_estimate_qscale(MpegEncContext *s)
get_qminmax(&qmin, &qmax, s, pict_type);
fps= (double)s->frame_rate / FRAME_RATE_BASE;
fps= (double)s->avctx->frame_rate / (double)s->avctx->frame_rate_base;
//printf("input_pic_num:%d pic_num:%d frame_rate:%d\n", s->input_picture_number, s->picture_number, s->frame_rate);
/* update predictors */
if(picture_number>2){
......@@ -698,7 +698,7 @@ static int init_pass2(MpegEncContext *s)
{
RateControlContext *rcc= &s->rc_context;
int i;
double fps= (double)s->frame_rate / FRAME_RATE_BASE;
double fps= (double)s->avctx->frame_rate / (double)s->avctx->frame_rate_base;
double complexity[5]={0,0,0,0,0}; // aproximate bits at quant=1
double avg_quantizer[5];
uint64_t const_bits[5]={0,0,0,0,0}; // quantizer idependant bits
......
......@@ -236,7 +236,8 @@ void avcodec_get_context_defaults(AVCodecContext *s){
s->error_concealment= 3;
s->error_resilience= 1;
s->workaround_bugs= FF_BUG_AUTODETECT;
s->frame_rate = 25 * FRAME_RATE_BASE;
s->frame_rate_base= 1;
s->frame_rate = 25;
s->gop_size= 50;
s->me_method= ME_EPZS;
s->get_buffer= avcodec_default_get_buffer;
......@@ -463,7 +464,7 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
snprintf(buf + strlen(buf), buf_size - strlen(buf),
", %dx%d, %0.2f fps",
enc->width, enc->height,
(float)enc->frame_rate / FRAME_RATE_BASE);
(float)enc->frame_rate / enc->frame_rate_base);
}
if (encode) {
snprintf(buf + strlen(buf), buf_size - strlen(buf),
......@@ -588,6 +589,65 @@ void avcodec_flush_buffers(AVCodecContext *avctx)
}
}
int av_reduce(int *dst_nom, int *dst_den, int64_t nom, int64_t den, int64_t max){
int exact=1, sign=0;
int64_t gcd, larger;
assert(den != 0);
if(den < 0){
den= -den;
nom= -nom;
}
if(nom < 0){
nom= -nom;
sign= 1;
}
for(;;){ //note is executed 1 or 2 times
gcd = ff_gcd(nom, den);
nom /= gcd;
den /= gcd;
larger= FFMAX(nom, den);
if(larger > max){
int64_t div= (larger + max - 1) / max;
nom = (nom + div/2)/div;
den = (den + div/2)/div;
exact=0;
}else
break;
}
if(sign) nom= -nom;
*dst_nom = nom;
*dst_den = den;
return exact;
}
int64_t av_rescale(int64_t a, int b, int c){
uint64_t h, l;
assert(c > 0);
assert(b >=0);
if(a<0) return -av_rescale(-a, b, c);
h= a>>32;
if(h==0) return a*b/c;
l= a&0xFFFFFFFF;