# HG changeset patch # User michaelni # Date 1047482179 0 # Node ID 25062c9b1f8621116e2950b4fcf0fbaa5cad2903 # Parent 0068a69029118c8bb0cc912afd817d3413b9ccd3 per context frame_rate_base, this should finally fix frame_rate related av sync issues diff -r 0068a6902911 -r 25062c9b1f86 asf.c --- a/asf.c Wed Mar 12 01:35:47 2003 +0000 +++ b/asf.c Wed Mar 12 15:16:19 2003 +0000 @@ -621,8 +621,7 @@ duration = (codec->frame_number * codec->frame_size * int64_t_C(10000000)) / codec->sample_rate; } else { - duration = codec->frame_number * - ((int64_t_C(10000000) * FRAME_RATE_BASE) / codec->frame_rate); + duration = av_rescale(codec->frame_number * codec->frame_rate_base, 10000000, codec->frame_rate); } if (duration > asf->duration) asf->duration = duration; diff -r 0068a6902911 -r 25062c9b1f86 avformat.h --- a/avformat.h Wed Mar 12 01:35:47 2003 +0000 +++ b/avformat.h Wed Mar 12 15:16:19 2003 +0000 @@ -77,6 +77,7 @@ typedef struct AVFormatParameters { int frame_rate; + int frame_rate_base; int sample_rate; int channels; int width; @@ -159,6 +160,7 @@ int id; /* format specific stream id */ AVCodecContext codec; /* codec context */ int r_frame_rate; /* real frame rate of the stream */ + int r_frame_rate_base;/* real frame rate base of the stream */ uint64_t time_length; /* real length of the stream in miliseconds */ void *priv_data; /* internal data used in av_find_stream_info() */ @@ -332,8 +334,6 @@ #define MKTAG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24)) #define MKBETAG(a,b,c,d) (d | (c << 8) | (b << 16) | (a << 24)) -int av_gcd(int a, int b); - void av_register_input_format(AVInputFormat *format); void av_register_output_format(AVOutputFormat *format); AVOutputFormat *guess_stream_format(const char *short_name, diff -r 0068a6902911 -r 25062c9b1f86 avidec.c --- a/avidec.c Wed Mar 12 01:35:47 2003 +0000 +++ b/avidec.c Wed Mar 12 15:16:19 2003 +0000 @@ -133,12 +133,16 @@ scale= get_le32(pb); /* scale */ rate= get_le32(pb); /* rate */ - if(scale && rate) - st->codec.frame_rate= (rate * (uint64_t)FRAME_RATE_BASE + scale/2) / scale; - else if(frame_period) - st->codec.frame_rate = (1000000LL * FRAME_RATE_BASE + frame_period/2) / frame_period; - else - st->codec.frame_rate = 25 * FRAME_RATE_BASE; + if(scale && rate){ + st->codec.frame_rate = rate; + st->codec.frame_rate_base= scale; + }else if(frame_period){ + st->codec.frame_rate = 1000000; + st->codec.frame_rate_base= frame_period; + }else{ + st->codec.frame_rate = 25; + st->codec.frame_rate_base = 1; + } url_fskip(pb, size - 7 * 4); break; diff -r 0068a6902911 -r 25062c9b1f86 avienc.c --- a/avienc.c Wed Mar 12 01:35:47 2003 +0000 +++ b/avienc.c Wed Mar 12 15:16:19 2003 +0000 @@ -218,7 +218,7 @@ nb_frames = 0; if(video_enc){ - put_le32(pb, (uint32_t)(int64_t_C(1000000) * FRAME_RATE_BASE / video_enc->frame_rate)); + put_le32(pb, (uint32_t)(int64_t_C(1000000) * video_enc->frame_rate_base / video_enc->frame_rate)); } else { put_le32(pb, 0); } @@ -244,8 +244,6 @@ /* stream list */ for(i=0;iframe_rate, FRAME_RATE_BASE); - - put_le32(pb, FRAME_RATE_BASE / gcd); /* scale */ - put_le32(pb, stream->frame_rate / gcd); /* rate */ + put_le32(pb, stream->frame_rate_base); /* scale */ + put_le32(pb, stream->frame_rate); /* rate */ put_le32(pb, 0); /* start */ avi->frames_hdr_strm[i] = url_ftell(pb); /* remember this offset to fill later */ diff -r 0068a6902911 -r 25062c9b1f86 dv1394.c --- a/dv1394.c Wed Mar 12 01:35:47 2003 +0000 +++ b/dv1394.c Wed Mar 12 15:16:19 2003 +0000 @@ -138,7 +138,8 @@ vst->codec.codec_id = CODEC_ID_DVVIDEO; vst->codec.width = dv->width; vst->codec.height = dv->height; - vst->codec.frame_rate = dv->frame_rate * FRAME_RATE_BASE; + vst->codec.frame_rate = dv->frame_rate; + vst->codec.frame_rate_base = 1; vst->codec.bit_rate = 25000000; /* Consumer DV is 25Mbps */ ast->codec.codec_type = CODEC_TYPE_AUDIO; diff -r 0068a6902911 -r 25062c9b1f86 ffm.c --- a/ffm.c Wed Mar 12 01:35:47 2003 +0000 +++ b/ffm.c Wed Mar 12 15:16:19 2003 +0000 @@ -140,8 +140,6 @@ /* list of streams */ for(i=0;inb_streams;i++) { - int gcd; - st = s->streams[i]; fst = av_mallocz(sizeof(FFMStream)); if (!fst) @@ -158,9 +156,8 @@ /* specific info */ switch(codec->codec_type) { case CODEC_TYPE_VIDEO: - gcd= av_gcd(FRAME_RATE_BASE, codec->frame_rate); - put_be32(pb, FRAME_RATE_BASE / gcd); - put_be32(pb, codec->frame_rate / gcd); + put_be32(pb, codec->frame_rate_base); + put_be32(pb, codec->frame_rate); put_be16(pb, codec->width); put_be16(pb, codec->height); put_be16(pb, codec->gop_size); @@ -229,7 +226,7 @@ if (st->codec.codec_type == CODEC_TYPE_AUDIO) { duration = ((float)st->codec.frame_size / st->codec.sample_rate * 1000000.0); } else { - duration = (1000000.0 * FRAME_RATE_BASE / (float)st->codec.frame_rate); + duration = (1000000.0 * st->codec.frame_rate_base / (float)st->codec.frame_rate); } pts = fst->pts; @@ -394,7 +391,6 @@ /* read each stream */ for(i=0;inb_streams;i++) { char rc_eq_buf[128]; - int rate, scale; st = av_mallocz(sizeof(AVStream)); if (!st) @@ -416,9 +412,8 @@ /* specific info */ switch(codec->codec_type) { case CODEC_TYPE_VIDEO: - scale= get_be32(pb); - rate= get_be32(pb); - codec->frame_rate = (rate * (int64_t)FRAME_RATE_BASE) / scale; + codec->frame_rate_base = get_be32(pb); + codec->frame_rate = get_be32(pb); codec->width = get_be16(pb); codec->height = get_be16(pb); codec->gop_size = get_be16(pb); diff -r 0068a6902911 -r 25062c9b1f86 gif.c --- a/gif.c Wed Mar 12 01:35:47 2003 +0000 +++ b/gif.c Wed Mar 12 15:16:19 2003 +0000 @@ -296,7 +296,7 @@ GIFContext *gif = s->priv_data; ByteIOContext *pb = &s->pb; AVCodecContext *enc, *video_enc; - int i, width, height, rate; + int i, width, height/*, rate*/; /* XXX: do we reject audio streams or just ignore them ? if(s->nb_streams > 1) @@ -318,7 +318,7 @@ } else { width = video_enc->width; height = video_enc->height; - rate = video_enc->frame_rate; +// rate = video_enc->frame_rate; } /* XXX: is it allowed ? seems to work so far... */ @@ -351,7 +351,7 @@ /* XXX: should use delay, in order to be more accurate */ /* instead of using the same rounded value each time */ /* XXX: don't even remember if I really use it for now */ - jiffies = (70*FRAME_RATE_BASE/enc->frame_rate) - 1; + jiffies = (70*enc->frame_rate_base/enc->frame_rate) - 1; put_le16(pb, jiffies); diff -r 0068a6902911 -r 25062c9b1f86 gifdec.c --- a/gifdec.c Wed Mar 12 01:35:47 2003 +0000 +++ b/gifdec.c Wed Mar 12 15:16:19 2003 +0000 @@ -535,7 +535,8 @@ st->codec.codec_type = CODEC_TYPE_VIDEO; st->codec.codec_id = CODEC_ID_RAWVIDEO; - st->codec.frame_rate = 5 * FRAME_RATE_BASE; + st->codec.frame_rate = 5; + st->codec.frame_rate_base = 1; /* XXX: check if screen size is always valid */ st->codec.width = s->screen_width; st->codec.height = s->screen_height; diff -r 0068a6902911 -r 25062c9b1f86 grab.c --- a/grab.c Wed Mar 12 01:35:47 2003 +0000 +++ b/grab.c Wed Mar 12 15:16:19 2003 +0000 @@ -31,6 +31,7 @@ int use_mmap; int width, height; int frame_rate; + int frame_rate_base; int64_t time_frame; int frame_size; struct video_capability video_cap; @@ -59,7 +60,7 @@ AVStream *st; int width, height; int video_fd, frame_size; - int ret, frame_rate; + int ret, frame_rate, frame_rate_base; int desired_palette; struct video_audio audio; const char *video_device; @@ -69,7 +70,8 @@ width = ap->width; height = ap->height; - frame_rate = ap->frame_rate; + frame_rate = ap->frame_rate; + frame_rate_base = ap->frame_rate_base; st = av_new_stream(s1, 0); if (!st) @@ -77,7 +79,8 @@ s->width = width; s->height = height; - s->frame_rate = frame_rate; + s->frame_rate = frame_rate; + s->frame_rate_base = frame_rate_base; video_device = ap->device; if (!video_device) @@ -240,7 +243,8 @@ st->codec.codec_id = CODEC_ID_RAWVIDEO; st->codec.width = width; st->codec.height = height; - st->codec.frame_rate = frame_rate; + st->codec.frame_rate = frame_rate; + st->codec.frame_rate_base = frame_rate_base; av_set_pts_info(s1, 48, 1, 1000000); /* 48 bits pts in us */ @@ -283,7 +287,7 @@ VideoData *s = s1->priv_data; int64_t curtime, delay; struct timespec ts; - int64_t per_frame = (int64_t_C(1000000) * FRAME_RATE_BASE) / s->frame_rate; + int64_t per_frame = (int64_t_C(1000000) * s->frame_rate_base) / s->frame_rate; /* Calculate the time of the next frame */ s->time_frame += per_frame; diff -r 0068a6902911 -r 25062c9b1f86 img.c --- a/img.c Wed Mar 12 01:35:47 2003 +0000 +++ b/img.c Wed Mar 12 15:16:19 2003 +0000 @@ -124,10 +124,13 @@ st->codec.pix_fmt = s->pix_fmt; s->img_size = avpicture_get_size(s->pix_fmt, s->width, s->height); - if (!ap || !ap->frame_rate) - st->codec.frame_rate = 25 * FRAME_RATE_BASE; - else - st->codec.frame_rate = ap->frame_rate; + if (!ap || !ap->frame_rate){ + st->codec.frame_rate = 25; + st->codec.frame_rate_base = 1; + }else{ + st->codec.frame_rate = ap->frame_rate; + st->codec.frame_rate_base = ap->frame_rate_base; + } return 0; fail1: @@ -182,7 +185,7 @@ av_free_packet(pkt); return -EIO; /* signal EOF */ } else { - pkt->pts = ((int64_t)s->img_number * s1->pts_den * FRAME_RATE_BASE) / (s1->streams[0]->codec.frame_rate * s1->pts_num); + pkt->pts = av_rescale((int64_t)s->img_number * s1->streams[0]->codec.frame_rate_base, s1->pts_den, s1->streams[0]->codec.frame_rate) / s1->pts_num; s->img_number++; return 0; } diff -r 0068a6902911 -r 25062c9b1f86 mov.c --- a/mov.c Wed Mar 12 01:35:47 2003 +0000 +++ b/mov.c Wed Mar 12 15:16:19 2003 +0000 @@ -686,7 +686,8 @@ get_be16(pb); /* depth */ get_be16(pb); /* colortable id */ - st->codec.frame_rate = 25 * FRAME_RATE_BASE; + st->codec.frame_rate = 25; + st->codec.frame_rate_base = 1; size -= (16+8*4+2+32+2*2); while (size >= 8) { @@ -932,9 +933,8 @@ sample_duration = get_be32(pb); if (!i && st->codec.codec_type==CODEC_TYPE_VIDEO) { - st->codec.frame_rate = FRAME_RATE_BASE * c->streams[c->total_streams]->time_scale; - if (sample_duration) - st->codec.frame_rate /= sample_duration; + st->codec.frame_rate_base = sample_duration ? sample_duration : 1; + st->codec.frame_rate = c->streams[c->total_streams]->time_scale; #ifdef DEBUG printf("VIDEO FRAME RATE= %i (sd= %i)\n", st->codec.frame_rate, sample_duration); #endif diff -r 0068a6902911 -r 25062c9b1f86 raw.c --- a/raw.c Wed Mar 12 01:35:47 2003 +0000 +++ b/raw.c Wed Mar 12 15:16:19 2003 +0000 @@ -61,7 +61,8 @@ st->codec.channels = ap->channels; break; case CODEC_TYPE_VIDEO: - st->codec.frame_rate = ap->frame_rate; + st->codec.frame_rate = ap->frame_rate; + st->codec.frame_rate_base = ap->frame_rate_base; st->codec.width = ap->width; st->codec.height = ap->height; break; @@ -151,9 +152,11 @@ /* for mpeg4 specify it too (most mpeg4 streams dont have the fixed_vop_rate set ...)*/ if (st->codec.codec_id == CODEC_ID_MJPEG || st->codec.codec_id == CODEC_ID_MPEG4) { if (ap) { - st->codec.frame_rate = ap->frame_rate; + st->codec.frame_rate = ap->frame_rate; + st->codec.frame_rate_base = ap->frame_rate_base; } else { - st->codec.frame_rate = 25 * FRAME_RATE_BASE; + st->codec.frame_rate = 25; + st->codec.frame_rate_base = 1; } } return 0; diff -r 0068a6902911 -r 25062c9b1f86 rm.c --- a/rm.c Wed Mar 12 01:35:47 2003 +0000 +++ b/rm.c Wed Mar 12 15:16:19 2003 +0000 @@ -306,7 +306,7 @@ break; case CODEC_TYPE_VIDEO: rm->video_stream = stream; - stream->frame_rate = (float)codec->frame_rate / (float)FRAME_RATE_BASE; + stream->frame_rate = (float)codec->frame_rate / (float)codec->frame_rate_base; /* XXX: dummy values */ stream->packet_max_size = 4096; stream->nb_packets = 0; @@ -582,7 +582,8 @@ goto fail1; st->codec.width = get_be16(pb); st->codec.height = get_be16(pb); - st->codec.frame_rate = get_be16(pb) * FRAME_RATE_BASE; + st->codec.frame_rate_base= 1; + st->codec.frame_rate = get_be16(pb) * st->codec.frame_rate_base; st->codec.codec_type = CODEC_TYPE_VIDEO; get_be32(pb); get_be16(pb); diff -r 0068a6902911 -r 25062c9b1f86 rtp.c --- a/rtp.c Wed Mar 12 01:35:47 2003 +0000 +++ b/rtp.c Wed Mar 12 15:16:19 2003 +0000 @@ -560,9 +560,8 @@ q += len; /* 90 KHz time stamp */ - /* XXX: overflow */ s->timestamp = s->base_timestamp + - (s->cur_timestamp * 90000LL * FRAME_RATE_BASE) / st->codec.frame_rate; + av_rescale((int64_t)s->cur_timestamp * st->codec.frame_rate_base, 90000, st->codec.frame_rate); rtp_send_data(s1, s->buf, q - s->buf); buf1 += len; @@ -586,9 +585,8 @@ len = size; /* 90 KHz time stamp */ - /* XXX: overflow */ s->timestamp = s->base_timestamp + - (s->cur_timestamp * 90000LL * FRAME_RATE_BASE) / st->codec.frame_rate; + av_rescale((int64_t)s->cur_timestamp * st->codec.frame_rate_base, 90000, st->codec.frame_rate); rtp_send_data(s1, buf1, len); buf1 += len; diff -r 0068a6902911 -r 25062c9b1f86 swf.c --- a/swf.c Wed Mar 12 01:35:47 2003 +0000 +++ b/swf.c Wed Mar 12 15:16:19 2003 +0000 @@ -194,7 +194,7 @@ AVCodecContext *enc, *audio_enc, *video_enc; PutBitContext p; uint8_t buf1[256]; - int i, width, height, rate; + int i, width, height, rate, rate_base; swf = av_malloc(sizeof(SWFContext)); if (!swf) @@ -215,11 +215,13 @@ /* currenty, cannot work correctly if audio only */ width = 320; height = 200; - rate = 10 * FRAME_RATE_BASE; + rate = 10; + rate_base= 1; } else { width = video_enc->width; height = video_enc->height; rate = video_enc->frame_rate; + rate_base = video_enc->frame_rate_base; } put_tag(pb, "FWS"); @@ -228,9 +230,9 @@ (will be patched if not streamed) */ put_swf_rect(pb, 0, width, 0, height); - put_le16(pb, (rate * 256) / FRAME_RATE_BASE); /* frame rate */ + put_le16(pb, (rate * 256) / rate_base); /* frame rate */ swf->duration_pos = url_ftell(pb); - put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / FRAME_RATE_BASE)); /* frame count */ + put_le16(pb, (uint16_t)(DUMMY_DURATION * (int64_t)rate / rate_base)); /* frame count */ /* define a shape with the jpeg inside */ @@ -305,7 +307,7 @@ put_swf_tag(s, TAG_STREAMHEAD); put_byte(&s->pb, 0); put_byte(&s->pb, v); - put_le16(&s->pb, (audio_enc->sample_rate * FRAME_RATE_BASE) / rate); /* avg samples per frame */ + put_le16(&s->pb, (audio_enc->sample_rate * rate_base) / rate); /* avg samples per frame */ put_swf_end_tag(s); diff -r 0068a6902911 -r 25062c9b1f86 utils.c --- a/utils.c Wed Mar 12 01:35:47 2003 +0000 +++ b/utils.c Wed Mar 12 15:16:19 2003 +0000 @@ -614,10 +614,12 @@ #endif /* stop after 40 frames */ if (st->codec_info_nb_real_frames >= 40) { - st->r_frame_rate = (st->codec.frame_rate * - st->codec_info_nb_real_frames) / - (st->codec_info_nb_real_frames + - (st->codec_info_nb_repeat_frames >> 1)); + av_reduce( + &st->r_frame_rate, + &st->r_frame_rate_base, + (int64_t)st->codec.frame_rate * st->codec_info_nb_real_frames, + st->codec_info_nb_real_frames + (st->codec_info_nb_repeat_frames >> 1), + 1<<30); goto close_codec; } } else { @@ -645,8 +647,10 @@ for(i=0;inb_streams;i++) { st = ic->streams[i]; if (st->codec.codec_type == CODEC_TYPE_VIDEO) { - if (!st->r_frame_rate) - st->r_frame_rate = st->codec.frame_rate; + if (!st->r_frame_rate){ + st->r_frame_rate = st->codec.frame_rate; + st->r_frame_rate_base = st->codec.frame_rate_base; + } } } @@ -820,7 +824,7 @@ break; case CODEC_TYPE_VIDEO: av_frac_add(&st->pts, - (int64_t)s->pts_den * FRAME_RATE_BASE); + (int64_t)s->pts_den * st->codec.frame_rate_base); break; default: break; @@ -1316,11 +1320,6 @@ f->num = num; } -int av_gcd(int a, int b){ - if(b) return av_gcd(b, a%b); - else return a; -} - /** * register a new image format * @param img_fmt Image format descriptor diff -r 0068a6902911 -r 25062c9b1f86 yuv4mpeg.c --- a/yuv4mpeg.c Wed Mar 12 01:35:47 2003 +0000 +++ b/yuv4mpeg.c Wed Mar 12 15:16:19 2003 +0000 @@ -26,7 +26,7 @@ { AVStream *st; int width, height; - int raten, rated, aspectn, aspectd, fps, fps1, n; + int raten, rated, aspectn, aspectd, fps, fps1, n, gcd; char buf[Y4M_LINE_MAX+1]; if (s->nb_streams != 1) @@ -35,9 +35,13 @@ st = s->streams[0]; width = st->codec.width; height = st->codec.height; - + +#if 1 + //this is identical to the code below for exact fps + av_reduce(&raten, &rated, st->codec.frame_rate, st->codec.frame_rate_base, (1UL<<31)-1); +#else fps = st->codec.frame_rate; - fps1 = (((float)fps / FRAME_RATE_BASE) * 1000); + fps1 = (((float)fps / st->codec.frame_rate_base) * 1000); /* Sorry about this messy code, but mpeg2enc is very picky about * the framerates it accepts. */ @@ -75,13 +79,17 @@ rated = 1; break; default: - raten = fps1; /* this setting should work, but often doesn't */ - rated = 1000; + raten = st->codec.frame_rate; /* this setting should work, but often doesn't */ + rated = st->codec.frame_rate_base; + gcd= av_gcd(raten, rated); + raten /= gcd; + rated /= gcd; break; } +#endif aspectn = 1; - aspectd = 1; /* ffmpeg always uses a 1:1 aspect ratio */ + aspectd = 1; /* ffmpeg always uses a 1:1 aspect ratio */ //FIXME not true anymore /* construct stream header, if this is the first frame */ n = snprintf(buf, sizeof(buf), "%s W%d H%d F%d:%d I%s A%d:%d\n",