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;
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);
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;
/* 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);
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
}
{
AVFormatContext *ic;
AVFormatParameters params, *ap = ¶ms;
- int err, i, ret, rfps;
+ int err, i, ret, rfps, rfps_base;
if (!strcmp(filename, "-"))
filename = "pipe:";
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;
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;
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;
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;
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:
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++;
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();
(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;
(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;
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;
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);
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;
} 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);
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 */
#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];\
FF_COMMON_FRAME
} AVFrame;
+#define DEFAULT_FRAME_RATE_BASE 1001000
/**
* main external api structure.
/* 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.
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);
/**
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;
}
/* 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)
{
/* 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;
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 */
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;
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;
/* 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);
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 */
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)
{ 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] = {
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){
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;
/* 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)
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));
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);
}
}
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;
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){
{
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
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;
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),
}
}
+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;
+ l *= b;
+ h *= b;
+
+ l += (h%c)<<32;
+
+ return ((h/c)<<32) + l/c;
+}
+
static int raw_encode_init(AVCodecContext *s)
{
return 0;
init_put_bits(&pb, s->avctx->extradata, s->avctx->extradata_size, NULL, NULL);
- put_bits(&pb, 5, s->frame_rate / FRAME_RATE_BASE); //yes 29.97 -> 29
+ put_bits(&pb, 5, s->avctx->frame_rate / s->avctx->frame_rate_base); //yes 29.97 -> 29
put_bits(&pb, 11, FFMIN(s->bit_rate/1024, 2047));
put_bits(&pb, 1, w->mspel_bit=1);
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;
typedef struct AVFormatParameters {
int frame_rate;
+ int frame_rate_base;
int sample_rate;
int channels;
int width;
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() */
#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,
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;
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);
}
/* stream list */
for(i=0;i<n;i++) {
- int gcd;
-
list2 = start_tag(pb, "LIST");
put_tag(pb, "strl");
put_le16(pb, 0); /* language */
put_le32(pb, 0); /* initial frame */
- gcd= av_gcd(stream->frame_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 */
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;
/* list of streams */
for(i=0;i<s->nb_streams;i++) {
- int gcd;
-
st = s->streams[i];
fst = av_mallocz(sizeof(FFMStream));
if (!fst)
/* 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);
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;
/* read each stream */
for(i=0;i<s->nb_streams;i++) {
char rc_eq_buf[128];
- int rate, scale;
st = av_mallocz(sizeof(AVStream));
if (!st)
/* 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);
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)
} 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... */
/* 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);
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;
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;
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;
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)
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)
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 */
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;
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:
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;
}
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) {
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
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;
/* 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;
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;
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);
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;
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;
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)
/* 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");
(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 */
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);
#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 {
for(i=0;i<ic->nb_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;
+ }
}
}
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;
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
{
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)
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. */
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",