mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
hopefully better bitrate controll
Originally committed as revision 334 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
1cb0edb40b
commit
9cdd6a24ad
64
ffmpeg.c
64
ffmpeg.c
@ -75,7 +75,13 @@ static int frame_width = 160;
|
|||||||
static int frame_height = 128;
|
static int frame_height = 128;
|
||||||
static int frame_rate = 25 * FRAME_RATE_BASE;
|
static int frame_rate = 25 * FRAME_RATE_BASE;
|
||||||
static int video_bit_rate = 200000;
|
static int video_bit_rate = 200000;
|
||||||
|
static int video_bit_rate_tolerance = 200000;
|
||||||
static int video_qscale = 0;
|
static int video_qscale = 0;
|
||||||
|
static int video_qmin = 3;
|
||||||
|
static int video_qmax = 15;
|
||||||
|
static int video_qdiff = 3;
|
||||||
|
static float video_qblur = 0.5;
|
||||||
|
static float video_qcomp = 0.5;
|
||||||
static int video_disable = 0;
|
static int video_disable = 0;
|
||||||
static int video_codec_id = CODEC_ID_NONE;
|
static int video_codec_id = CODEC_ID_NONE;
|
||||||
static int same_quality = 0;
|
static int same_quality = 0;
|
||||||
@ -1149,6 +1155,11 @@ void opt_video_bitrate(const char *arg)
|
|||||||
video_bit_rate = atoi(arg) * 1000;
|
video_bit_rate = atoi(arg) * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void opt_video_bitrate_tolerance(const char *arg)
|
||||||
|
{
|
||||||
|
video_bit_rate_tolerance = atoi(arg) * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
void opt_frame_rate(const char *arg)
|
void opt_frame_rate(const char *arg)
|
||||||
{
|
{
|
||||||
frame_rate = (int)(strtod(arg, 0) * FRAME_RATE_BASE);
|
frame_rate = (int)(strtod(arg, 0) * FRAME_RATE_BASE);
|
||||||
@ -1182,6 +1193,45 @@ void opt_qscale(const char *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void opt_qmin(const char *arg)
|
||||||
|
{
|
||||||
|
video_qmin = atoi(arg);
|
||||||
|
if (video_qmin < 0 ||
|
||||||
|
video_qmin > 31) {
|
||||||
|
fprintf(stderr, "qmin must be >= 1 and <= 31\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void opt_qmax(const char *arg)
|
||||||
|
{
|
||||||
|
video_qmax = atoi(arg);
|
||||||
|
if (video_qmax < 0 ||
|
||||||
|
video_qmax > 31) {
|
||||||
|
fprintf(stderr, "qmax must be >= 1 and <= 31\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void opt_qdiff(const char *arg)
|
||||||
|
{
|
||||||
|
video_qdiff = atoi(arg);
|
||||||
|
if (video_qdiff < 0 ||
|
||||||
|
video_qdiff > 31) {
|
||||||
|
fprintf(stderr, "qdiff must be >= 1 and <= 31\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void opt_qblur(const char *arg)
|
||||||
|
{
|
||||||
|
video_qblur = atof(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void opt_qcomp(const char *arg)
|
||||||
|
{
|
||||||
|
video_qcomp = atof(arg);
|
||||||
|
}
|
||||||
|
|
||||||
void opt_audio_bitrate(const char *arg)
|
void opt_audio_bitrate(const char *arg)
|
||||||
{
|
{
|
||||||
@ -1611,6 +1661,7 @@ void opt_output_file(const char *filename)
|
|||||||
video_enc->codec_type = CODEC_TYPE_VIDEO;
|
video_enc->codec_type = CODEC_TYPE_VIDEO;
|
||||||
|
|
||||||
video_enc->bit_rate = video_bit_rate;
|
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 = frame_rate;
|
||||||
|
|
||||||
video_enc->width = frame_width;
|
video_enc->width = frame_width;
|
||||||
@ -1623,6 +1674,13 @@ void opt_output_file(const char *filename)
|
|||||||
video_enc->flags |= CODEC_FLAG_QSCALE;
|
video_enc->flags |= CODEC_FLAG_QSCALE;
|
||||||
video_enc->quality = video_qscale;
|
video_enc->quality = video_qscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
video_enc->qmin= video_qmin;
|
||||||
|
video_enc->qmax= video_qmax;
|
||||||
|
video_enc->max_qdiff= video_qdiff;
|
||||||
|
video_enc->qblur= video_qblur;
|
||||||
|
video_enc->qcompress= video_qcomp;
|
||||||
|
|
||||||
if (do_psnr)
|
if (do_psnr)
|
||||||
video_enc->get_psnr = 1;
|
video_enc->get_psnr = 1;
|
||||||
else
|
else
|
||||||
@ -1948,6 +2006,12 @@ const OptionDef options[] = {
|
|||||||
{ "intra", OPT_BOOL | OPT_EXPERT, {(void*)&intra_only}, "use only intra frames"},
|
{ "intra", OPT_BOOL | OPT_EXPERT, {(void*)&intra_only}, "use only intra frames"},
|
||||||
{ "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" },
|
{ "vn", OPT_BOOL, {(void*)&video_disable}, "disable video" },
|
||||||
{ "qscale", HAS_ARG | OPT_EXPERT, {(void*)opt_qscale}, "use fixed video quantiser scale (VBR)", "q" },
|
{ "qscale", HAS_ARG | OPT_EXPERT, {(void*)opt_qscale}, "use fixed video quantiser scale (VBR)", "q" },
|
||||||
|
{ "qmin", HAS_ARG | OPT_EXPERT, {(void*)opt_qmin}, "min video quantiser scale (VBR)", "q" },
|
||||||
|
{ "qmax", HAS_ARG | OPT_EXPERT, {(void*)opt_qmax}, "max video quantiser scale (VBR)", "q" },
|
||||||
|
{ "qdiff", HAS_ARG | OPT_EXPERT, {(void*)opt_qdiff}, "max difference between the quantiser scale (VBR)", "q" },
|
||||||
|
{ "qblur", HAS_ARG | OPT_EXPERT, {(void*)opt_qblur}, "video quantiser scale blur (VBR)", "blur" },
|
||||||
|
{ "qcomp", HAS_ARG | OPT_EXPERT, {(void*)opt_qcomp}, "video quantiser scale compression (VBR)", "compression" },
|
||||||
|
{ "bt", HAS_ARG, {(void*)opt_video_bitrate_tolerance}, "set video bitrate tolerance (in kbit/s)", "tolerance" },
|
||||||
#ifdef CONFIG_GRAB
|
#ifdef CONFIG_GRAB
|
||||||
{ "vd", HAS_ARG | OPT_EXPERT, {(void*)opt_video_device}, "set video device", "device" },
|
{ "vd", HAS_ARG | OPT_EXPERT, {(void*)opt_video_device}, "set video device", "device" },
|
||||||
#endif
|
#endif
|
||||||
|
@ -72,6 +72,7 @@ extern int motion_estimation_method;
|
|||||||
|
|
||||||
typedef struct AVCodecContext {
|
typedef struct AVCodecContext {
|
||||||
int bit_rate;
|
int bit_rate;
|
||||||
|
int bit_rate_tolerance; /* amount of +- bits (>0)*/
|
||||||
int flags;
|
int flags;
|
||||||
int sub_id; /* some codecs needs additionnal format info. It is
|
int sub_id; /* some codecs needs additionnal format info. It is
|
||||||
stored there */
|
stored there */
|
||||||
@ -101,6 +102,12 @@ typedef struct AVCodecContext {
|
|||||||
a key frame (intra, or seekable) */
|
a key frame (intra, or seekable) */
|
||||||
int quality; /* quality of the previous encoded frame
|
int quality; /* quality of the previous encoded frame
|
||||||
(between 1 (good) and 31 (bad)) */
|
(between 1 (good) and 31 (bad)) */
|
||||||
|
float qcompress; /* amount of qscale change between easy & hard scenes (0.0-1.0)*/
|
||||||
|
float qblur; /* amount of qscale smoothing over time (0.0-1.0) */
|
||||||
|
int qmin; /* min qscale */
|
||||||
|
int qmax; /* max qscale */
|
||||||
|
int max_qdiff; /* max qscale difference between frames */
|
||||||
|
|
||||||
struct AVCodec *codec;
|
struct AVCodec *codec;
|
||||||
void *priv_data;
|
void *priv_data;
|
||||||
|
|
||||||
|
@ -460,6 +460,7 @@ int estimate_motion(MpegEncContext * s,
|
|||||||
varc = (varc >> 8) - (sum * sum);
|
varc = (varc >> 8) - (sum * sum);
|
||||||
s->mb_var[s->mb_width * mb_y + mb_x] = varc;
|
s->mb_var[s->mb_width * mb_y + mb_x] = varc;
|
||||||
s->avg_mb_var += varc;
|
s->avg_mb_var += varc;
|
||||||
|
s->mc_mb_var += vard;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
printf("varc=%4d avg_var=%4d (sum=%4d) vard=%4d mx=%2d my=%2d\n",
|
printf("varc=%4d avg_var=%4d (sum=%4d) vard=%4d mx=%2d my=%2d\n",
|
||||||
|
@ -276,6 +276,7 @@ int MPV_encode_init(AVCodecContext *avctx)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
s->bit_rate = avctx->bit_rate;
|
s->bit_rate = avctx->bit_rate;
|
||||||
|
s->bit_rate_tolerance = avctx->bit_rate_tolerance;
|
||||||
s->frame_rate = avctx->frame_rate;
|
s->frame_rate = avctx->frame_rate;
|
||||||
s->width = avctx->width;
|
s->width = avctx->width;
|
||||||
s->height = avctx->height;
|
s->height = avctx->height;
|
||||||
@ -284,6 +285,11 @@ int MPV_encode_init(AVCodecContext *avctx)
|
|||||||
s->rtp_payload_size = avctx->rtp_payload_size;
|
s->rtp_payload_size = avctx->rtp_payload_size;
|
||||||
if (avctx->rtp_callback)
|
if (avctx->rtp_callback)
|
||||||
s->rtp_callback = avctx->rtp_callback;
|
s->rtp_callback = avctx->rtp_callback;
|
||||||
|
s->qmin= avctx->qmin;
|
||||||
|
s->qmax= avctx->qmax;
|
||||||
|
s->max_qdiff= avctx->max_qdiff;
|
||||||
|
s->qcompress= avctx->qcompress;
|
||||||
|
s->qblur= avctx->qblur;
|
||||||
s->avctx = avctx;
|
s->avctx = avctx;
|
||||||
|
|
||||||
if (s->gop_size <= 1) {
|
if (s->gop_size <= 1) {
|
||||||
@ -520,7 +526,9 @@ int MPV_encode_picture(AVCodecContext *avctx,
|
|||||||
mjpeg_picture_trailer(s);
|
mjpeg_picture_trailer(s);
|
||||||
|
|
||||||
flush_put_bits(&s->pb);
|
flush_put_bits(&s->pb);
|
||||||
s->total_bits += (pbBufPtr(&s->pb) - s->pb.buf) * 8;
|
s->last_frame_bits= s->frame_bits;
|
||||||
|
s->frame_bits = (pbBufPtr(&s->pb) - s->pb.buf) * 8;
|
||||||
|
s->total_bits += s->frame_bits;
|
||||||
|
|
||||||
avctx->quality = s->qscale;
|
avctx->quality = s->qscale;
|
||||||
if (avctx->get_psnr) {
|
if (avctx->get_psnr) {
|
||||||
@ -1040,6 +1048,36 @@ static void encode_picture(MpegEncContext *s, int picture_number)
|
|||||||
int i, motion_x, motion_y;
|
int i, motion_x, motion_y;
|
||||||
|
|
||||||
s->picture_number = picture_number;
|
s->picture_number = picture_number;
|
||||||
|
|
||||||
|
s->last_mc_mb_var = s->mc_mb_var;
|
||||||
|
/* Reset the average MB variance */
|
||||||
|
s->avg_mb_var = 0;
|
||||||
|
s->mc_mb_var = 0;
|
||||||
|
|
||||||
|
/* Estimate motion for every MB */
|
||||||
|
for(mb_y=0; mb_y < s->mb_height; mb_y++) {
|
||||||
|
for(mb_x=0; mb_x < s->mb_width; mb_x++) {
|
||||||
|
int xy= mb_y * s->mb_width + mb_x;
|
||||||
|
s->mb_x = mb_x;
|
||||||
|
s->mb_y = mb_y;
|
||||||
|
|
||||||
|
/* compute motion vector and macro block type (intra or non intra) */
|
||||||
|
motion_x = 0;
|
||||||
|
motion_y = 0;
|
||||||
|
if (s->pict_type == P_TYPE) {
|
||||||
|
s->mb_intra = estimate_motion(s, mb_x, mb_y,
|
||||||
|
&motion_x,
|
||||||
|
&motion_y);
|
||||||
|
} else {
|
||||||
|
s->mb_intra = 1;
|
||||||
|
}
|
||||||
|
/* Store MB type and MV */
|
||||||
|
s->mb_type[xy] = s->mb_intra;
|
||||||
|
s->mv_table[0][xy] = motion_x;
|
||||||
|
s->mv_table[1][xy] = motion_y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!s->fixed_qscale)
|
if (!s->fixed_qscale)
|
||||||
s->qscale = rate_estimate_qscale(s);
|
s->qscale = rate_estimate_qscale(s);
|
||||||
|
|
||||||
@ -1095,32 +1133,6 @@ static void encode_picture(MpegEncContext *s, int picture_number)
|
|||||||
s->gob_index = 4;
|
s->gob_index = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset the average MB variance */
|
|
||||||
s->avg_mb_var = 0;
|
|
||||||
|
|
||||||
/* Estimate motion for every MB */
|
|
||||||
for(mb_y=0; mb_y < s->mb_height; mb_y++) {
|
|
||||||
for(mb_x=0; mb_x < s->mb_width; mb_x++) {
|
|
||||||
s->mb_x = mb_x;
|
|
||||||
s->mb_y = mb_y;
|
|
||||||
|
|
||||||
/* compute motion vector and macro block type (intra or non intra) */
|
|
||||||
motion_x = 0;
|
|
||||||
motion_y = 0;
|
|
||||||
if (s->pict_type == P_TYPE) {
|
|
||||||
s->mb_intra = estimate_motion(s, mb_x, mb_y,
|
|
||||||
&motion_x,
|
|
||||||
&motion_y);
|
|
||||||
} else {
|
|
||||||
s->mb_intra = 1;
|
|
||||||
}
|
|
||||||
/* Store MB type and MV */
|
|
||||||
s->mb_type[mb_y * s->mb_width + mb_x] = s->mb_intra;
|
|
||||||
s->mv_table[0][mb_y * s->mb_width + mb_x] = motion_x;
|
|
||||||
s->mv_table[1][mb_y * s->mb_width + mb_x] = motion_y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s->avg_mb_var = s->avg_mb_var / s->mb_num;
|
s->avg_mb_var = s->avg_mb_var / s->mb_num;
|
||||||
|
|
||||||
s->block_wrap[0]=
|
s->block_wrap[0]=
|
||||||
@ -1542,6 +1554,22 @@ static void dct_unquantize_h263_c(MpegEncContext *s,
|
|||||||
|
|
||||||
static void rate_control_init(MpegEncContext *s)
|
static void rate_control_init(MpegEncContext *s)
|
||||||
{
|
{
|
||||||
|
#if 1
|
||||||
|
emms_c();
|
||||||
|
|
||||||
|
//initial values, they dont really matter as they will be totally different within a few frames
|
||||||
|
s->i_pred.coeff= s->p_pred.coeff= 7.0;
|
||||||
|
s->i_pred.count= s->p_pred.count= 1.0;
|
||||||
|
|
||||||
|
s->i_pred.decay= s->p_pred.decay= 0.4;
|
||||||
|
|
||||||
|
// use more bits at the beginning, otherwise high motion at the begin will look like shit
|
||||||
|
s->qsum=100;
|
||||||
|
s->qcount=100;
|
||||||
|
|
||||||
|
s->short_term_qsum=0.001;
|
||||||
|
s->short_term_qcount=0.001;
|
||||||
|
#else
|
||||||
s->wanted_bits = 0;
|
s->wanted_bits = 0;
|
||||||
|
|
||||||
if (s->intra_only) {
|
if (s->intra_only) {
|
||||||
@ -1557,19 +1585,117 @@ static void rate_control_init(MpegEncContext *s)
|
|||||||
printf("I_frame_size=%d P_frame_size=%d\n",
|
printf("I_frame_size=%d P_frame_size=%d\n",
|
||||||
s->I_frame_bits, s->P_frame_bits);
|
s->I_frame_bits, s->P_frame_bits);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static double predict(Predictor *p, double q, double var)
|
||||||
|
{
|
||||||
|
return p->coeff*var / (q*p->count);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_predictor(Predictor *p, double q, double var, double size)
|
||||||
|
{
|
||||||
|
double new_coeff= size*q / (var + 1);
|
||||||
|
if(var<1000) return;
|
||||||
|
/*{
|
||||||
|
int pred= predict(p, q, var);
|
||||||
|
int error= abs(pred-size);
|
||||||
|
static double sum=0;
|
||||||
|
static int count=0;
|
||||||
|
if(count>5) sum+=error;
|
||||||
|
count++;
|
||||||
|
if(256*256*256*64%count==0){
|
||||||
|
printf("%d %f %f\n", count, sum/count, p->coeff);
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
p->count*= p->decay;
|
||||||
|
p->coeff*= p->decay;
|
||||||
|
p->count++;
|
||||||
|
p->coeff+= new_coeff;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* This heuristic is rather poor, but at least we do not have to
|
|
||||||
* change the qscale at every macroblock.
|
|
||||||
*/
|
|
||||||
static int rate_estimate_qscale(MpegEncContext *s)
|
static int rate_estimate_qscale(MpegEncContext *s)
|
||||||
{
|
{
|
||||||
|
#if 1
|
||||||
|
int qmin= s->qmin;
|
||||||
|
int qmax= s->qmax;
|
||||||
|
int rate_q=5;
|
||||||
|
float q;
|
||||||
|
int qscale;
|
||||||
|
float br_compensation;
|
||||||
|
double diff;
|
||||||
|
double short_term_q;
|
||||||
|
double long_term_q;
|
||||||
|
int last_qscale= s->qscale;
|
||||||
|
double fps;
|
||||||
|
INT64 wanted_bits;
|
||||||
|
emms_c();
|
||||||
|
|
||||||
|
fps= (double)s->frame_rate / FRAME_RATE_BASE;
|
||||||
|
wanted_bits= s->bit_rate*(double)s->picture_number/fps;
|
||||||
|
|
||||||
|
|
||||||
|
if(s->picture_number>2){
|
||||||
|
/* update predictors */
|
||||||
|
if(s->last_pict_type == I_TYPE){
|
||||||
|
//FIXME
|
||||||
|
}else{ //P Frame
|
||||||
|
//printf("%d %d %d %f\n", s->qscale, s->last_mc_mb_var, s->frame_bits, s->p_pred.coeff);
|
||||||
|
update_predictor(&s->p_pred, s->qscale, s->last_mc_mb_var, s->frame_bits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(s->pict_type == I_TYPE){
|
||||||
|
//FIXME
|
||||||
|
rate_q= s->qsum/s->qcount;
|
||||||
|
}else{ //P Frame
|
||||||
|
int i;
|
||||||
|
int diff, best_diff=1000000000;
|
||||||
|
for(i=1; i<=31; i++){
|
||||||
|
diff= predict(&s->p_pred, i, s->mc_mb_var) - (double)s->bit_rate/fps;
|
||||||
|
if(diff<0) diff= -diff;
|
||||||
|
if(diff<best_diff){
|
||||||
|
best_diff= diff;
|
||||||
|
rate_q= i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s->short_term_qsum*=s->qblur;
|
||||||
|
s->short_term_qcount*=s->qblur;
|
||||||
|
|
||||||
|
s->short_term_qsum+= rate_q;
|
||||||
|
s->short_term_qcount++;
|
||||||
|
short_term_q= s->short_term_qsum/s->short_term_qcount;
|
||||||
|
|
||||||
|
long_term_q= s->qsum/s->qcount*s->total_bits/wanted_bits;
|
||||||
|
|
||||||
|
// q= (long_term_q - short_term_q)*s->qcompress + short_term_q;
|
||||||
|
q= 1/((1/long_term_q - 1/short_term_q)*s->qcompress + 1/short_term_q);
|
||||||
|
|
||||||
|
diff= s->total_bits - wanted_bits;
|
||||||
|
br_compensation= (s->bit_rate_tolerance - diff)/s->bit_rate_tolerance;
|
||||||
|
q/=br_compensation;
|
||||||
|
|
||||||
|
qscale= (int)(q + 0.5);
|
||||||
|
if (qscale<qmin) qscale=qmin;
|
||||||
|
else if(qscale>qmax) qscale=qmax;
|
||||||
|
|
||||||
|
if (qscale<last_qscale-s->max_qdiff) qscale=last_qscale-s->max_qdiff;
|
||||||
|
else if(qscale>last_qscale+s->max_qdiff) qscale=last_qscale+s->max_qdiff;
|
||||||
|
|
||||||
|
s->qsum+= qscale;
|
||||||
|
s->qcount++;
|
||||||
|
|
||||||
|
s->last_pict_type= s->pict_type;
|
||||||
|
//printf("q:%d diff:%d comp:%f rate_q:%d st_q:%d fvar:%d last_size:%d\n", qscale, (int)diff, br_compensation,
|
||||||
|
// rate_q, (int)short_term_q, s->mc_mb_var, s->frame_bits);
|
||||||
|
//printf("%d %d\n", s->bit_rate, (int)fps);
|
||||||
|
return qscale;
|
||||||
|
#else
|
||||||
INT64 diff, total_bits = s->total_bits;
|
INT64 diff, total_bits = s->total_bits;
|
||||||
float q;
|
float q;
|
||||||
int qscale, qmin;
|
int qscale;
|
||||||
|
|
||||||
if (s->pict_type == I_TYPE) {
|
if (s->pict_type == I_TYPE) {
|
||||||
s->wanted_bits += s->I_frame_bits;
|
s->wanted_bits += s->I_frame_bits;
|
||||||
} else {
|
} else {
|
||||||
@ -1600,6 +1726,7 @@ static int rate_estimate_qscale(MpegEncContext *s)
|
|||||||
(int)diff, q);
|
(int)diff, q);
|
||||||
#endif
|
#endif
|
||||||
return qscale;
|
return qscale;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
AVCodec mpeg1video_encoder = {
|
AVCodec mpeg1video_encoder = {
|
||||||
|
@ -34,6 +34,12 @@ enum OutputFormat {
|
|||||||
#define QMAT_SHIFT_MMX 19
|
#define QMAT_SHIFT_MMX 19
|
||||||
#define QMAT_SHIFT 25
|
#define QMAT_SHIFT 25
|
||||||
|
|
||||||
|
typedef struct Predictor{
|
||||||
|
double coeff;
|
||||||
|
double count;
|
||||||
|
double decay;
|
||||||
|
} Predictor;
|
||||||
|
|
||||||
typedef struct MpegEncContext {
|
typedef struct MpegEncContext {
|
||||||
struct AVCodecContext *avctx;
|
struct AVCodecContext *avctx;
|
||||||
/* the following parameters must be initialized before encoding */
|
/* the following parameters must be initialized before encoding */
|
||||||
@ -42,6 +48,7 @@ typedef struct MpegEncContext {
|
|||||||
int frame_rate; /* number of frames per second */
|
int frame_rate; /* number of frames per second */
|
||||||
int intra_only; /* if true, only intra pictures are generated */
|
int intra_only; /* if true, only intra pictures are generated */
|
||||||
int bit_rate; /* wanted bit rate */
|
int bit_rate; /* wanted bit rate */
|
||||||
|
int bit_rate_tolerance; /* amount of +- bits (>0)*/
|
||||||
enum OutputFormat out_format; /* output format */
|
enum OutputFormat out_format; /* output format */
|
||||||
int h263_plus; /* h263 plus headers */
|
int h263_plus; /* h263 plus headers */
|
||||||
int h263_rv10; /* use RV10 variation for H263 */
|
int h263_rv10; /* use RV10 variation for H263 */
|
||||||
@ -49,6 +56,11 @@ typedef struct MpegEncContext {
|
|||||||
int h263_msmpeg4; /* generate MSMPEG4 compatible stream */
|
int h263_msmpeg4; /* generate MSMPEG4 compatible stream */
|
||||||
int h263_intel; /* use I263 intel h263 header */
|
int h263_intel; /* use I263 intel h263 header */
|
||||||
int fixed_qscale; /* fixed qscale if non zero */
|
int fixed_qscale; /* fixed qscale if non zero */
|
||||||
|
float qcompress; /* amount of qscale change between easy & hard scenes (0.0-1.0) */
|
||||||
|
float qblur; /* amount of qscale smoothing over time (0.0-1.0) */
|
||||||
|
int qmin; /* min qscale */
|
||||||
|
int qmax; /* max qscale */
|
||||||
|
int max_qdiff; /* max qscale difference between frames */
|
||||||
int encoding; /* true if we are encoding (vs decoding) */
|
int encoding; /* true if we are encoding (vs decoding) */
|
||||||
/* the following fields are managed internally by the encoder */
|
/* the following fields are managed internally by the encoder */
|
||||||
|
|
||||||
@ -85,6 +97,7 @@ typedef struct MpegEncContext {
|
|||||||
int qscale;
|
int qscale;
|
||||||
int pict_type;
|
int pict_type;
|
||||||
int last_non_b_pict_type; /* used for mpeg4 gmc b-frames */
|
int last_non_b_pict_type; /* used for mpeg4 gmc b-frames */
|
||||||
|
int last_pict_type; /* used for bit rate stuff (needs that to update the right predictor) */
|
||||||
int frame_rate_index;
|
int frame_rate_index;
|
||||||
/* motion compensation */
|
/* motion compensation */
|
||||||
int unrestricted_mv;
|
int unrestricted_mv;
|
||||||
@ -146,8 +159,18 @@ typedef struct MpegEncContext {
|
|||||||
int I_frame_bits; /* wanted number of bits per I frame */
|
int I_frame_bits; /* wanted number of bits per I frame */
|
||||||
int P_frame_bits; /* same for P frame */
|
int P_frame_bits; /* same for P frame */
|
||||||
int avg_mb_var; /* average MB variance for current frame */
|
int avg_mb_var; /* average MB variance for current frame */
|
||||||
|
int mc_mb_var; /* motion compensated MB variance for current frame */
|
||||||
|
int last_mc_mb_var; /* motion compensated MB variance for last frame */
|
||||||
INT64 wanted_bits;
|
INT64 wanted_bits;
|
||||||
INT64 total_bits;
|
INT64 total_bits;
|
||||||
|
int frame_bits; /* bits used for the current frame */
|
||||||
|
int last_frame_bits; /* bits used for the last frame */
|
||||||
|
Predictor i_pred;
|
||||||
|
Predictor p_pred;
|
||||||
|
double qsum; /* sum of qscales */
|
||||||
|
double qcount; /* count of qscales */
|
||||||
|
double short_term_qsum; /* sum of recent qscales */
|
||||||
|
double short_term_qcount; /* count of recent qscales */
|
||||||
|
|
||||||
/* H.263 specific */
|
/* H.263 specific */
|
||||||
int gob_number;
|
int gob_number;
|
||||||
|
Loading…
Reference in New Issue
Block a user