diff options
Diffstat (limited to 'src/libffmpeg/libavcodec/mpegvideo.c')
-rw-r--r-- | src/libffmpeg/libavcodec/mpegvideo.c | 2119 |
1 files changed, 1271 insertions, 848 deletions
diff --git a/src/libffmpeg/libavcodec/mpegvideo.c b/src/libffmpeg/libavcodec/mpegvideo.c index 9f572c3d9..63242c9de 100644 --- a/src/libffmpeg/libavcodec/mpegvideo.c +++ b/src/libffmpeg/libavcodec/mpegvideo.c @@ -1,49 +1,42 @@ /* * The simplest mpeg encoder (well, it was the simplest!) - * Copyright (c) 2000,2001 Gerard Lantau. + * Copyright (c) 2000,2001 Fabrice Bellard. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. * - * This program is distributed in the hope that it will be useful, + * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * 4MV & hq encoding stuff by Michael Niedermayer <michaelni@gmx.at> + * 4MV & hq & b-frame encoding stuff by Michael Niedermayer <michaelni@gmx.at> */ -#include <stdlib.h> -#include <stdio.h> -#include <math.h> -#include <string.h> #include "avcodec.h" #include "dsputil.h" #include "mpegvideo.h" -#include "config.h" -#include "xine-utils/xineutils.h" - #ifdef USE_FASTMEMCPY #include "fastmemcpy.h" #endif static void encode_picture(MpegEncContext *s, int picture_number); -static void rate_control_init(MpegEncContext *s); -static int rate_estimate_qscale(MpegEncContext *s); static void dct_unquantize_mpeg1_c(MpegEncContext *s, DCTELEM *block, int n, int qscale); +static void dct_unquantize_mpeg2_c(MpegEncContext *s, + DCTELEM *block, int n, int qscale); static void dct_unquantize_h263_c(MpegEncContext *s, DCTELEM *block, int n, int qscale); static void draw_edges_c(UINT8 *buf, int wrap, int width, int height, int w); -static int dct_quantize_c(MpegEncContext *s, DCTELEM *block, int n, int qscale); +static int dct_quantize_c(MpegEncContext *s, DCTELEM *block, int n, int qscale, int *overflow); -int (*dct_quantize)(MpegEncContext *s, DCTELEM *block, int n, int qscale)= dct_quantize_c; +int (*dct_quantize)(MpegEncContext *s, DCTELEM *block, int n, int qscale, int *overflow)= dct_quantize_c; void (*draw_edges)(UINT8 *buf, int wrap, int width, int height, int w)= draw_edges_c; #define EDGE_WIDTH 16 @@ -53,6 +46,7 @@ void (*draw_edges)(UINT8 *buf, int wrap, int width, int height, int w)= draw_edg //#define DEBUG + /* for jpeg fast DCT */ #define CONST_BITS 14 @@ -75,37 +69,55 @@ static UINT8 h263_chroma_roundtab[16] = { static UINT16 default_mv_penalty[MAX_FCODE+1][MAX_MV*2+1]; static UINT8 default_fcode_tab[MAX_MV*2+1]; -/* default motion estimation */ -int motion_estimation_method = ME_LOG; - extern UINT8 zigzag_end[64]; -static void convert_matrix(int *qmat, UINT16 *qmat16, const UINT16 *quant_matrix, int qscale) +/* default motion estimation */ +int motion_estimation_method = ME_EPZS; + +static void convert_matrix(int (*qmat)[64], uint16_t (*qmat16)[64], uint16_t (*qmat16_bias)[64], + const UINT16 *quant_matrix, int bias) { - int i; + int qscale; - if (av_fdct == jpeg_fdct_ifast) { - for(i=0;i<64;i++) { - /* 16 <= qscale * quant_matrix[i] <= 7905 */ - /* 19952 <= aanscales[i] * qscale * quant_matrix[i] <= 249205026 */ - /* (1<<36)/19952 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= (1<<36)/249205026 */ - /* 3444240 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= 275 */ - - qmat[block_permute_op(i)] = (int)((UINT64_C(1) << (QMAT_SHIFT + 11)) / - (aanscales[i] * qscale * quant_matrix[block_permute_op(i)])); - } - } else { - for(i=0;i<64;i++) { - /* We can safely suppose that 16 <= quant_matrix[i] <= 255 - So 16 <= qscale * quant_matrix[i] <= 7905 - so (1<<19) / 16 >= (1<<19) / (qscale * quant_matrix[i]) >= (1<<19) / 7905 - so 32768 >= (1<<19) / (qscale * quant_matrix[i]) >= 67 - */ - qmat[i] = (1 << QMAT_SHIFT_MMX) / (qscale * quant_matrix[i]); - qmat16[i] = (1 << QMAT_SHIFT_MMX) / (qscale * quant_matrix[block_permute_op(i)]); + for(qscale=1; qscale<32; qscale++){ + int i; + if (av_fdct == fdct_ifast) { + for(i=0;i<64;i++) { + const int j= block_permute_op(i); + /* 16 <= qscale * quant_matrix[i] <= 7905 */ + /* 19952 <= aanscales[i] * qscale * quant_matrix[i] <= 249205026 */ + /* (1<<36)/19952 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= (1<<36)/249205026 */ + /* 3444240 >= (1<<36)/(aanscales[i] * qscale * quant_matrix[i]) >= 275 */ + + qmat[qscale][j] = (int)((UINT64_C(1) << (QMAT_SHIFT + 11)) / + (aanscales[i] * qscale * quant_matrix[j])); + } + } else { + for(i=0;i<64;i++) { + /* We can safely suppose that 16 <= quant_matrix[i] <= 255 + So 16 <= qscale * quant_matrix[i] <= 7905 + so (1<<19) / 16 >= (1<<19) / (qscale * quant_matrix[i]) >= (1<<19) / 7905 + so 32768 >= (1<<19) / (qscale * quant_matrix[i]) >= 67 + */ + qmat [qscale][i] = (1 << QMAT_SHIFT_MMX) / (qscale * quant_matrix[i]); + qmat16[qscale][i] = (1 << QMAT_SHIFT_MMX) / (qscale * quant_matrix[block_permute_op(i)]); + + if(qmat16[qscale][i]==0 || qmat16[qscale][i]==128*256) qmat16[qscale][i]=128*256-1; + + qmat16_bias[qscale][i]= ROUNDED_DIV(bias<<(16-QUANT_BIAS_SHIFT), qmat16[qscale][i]); + } } } } +// move into common.c perhaps +#define CHECKED_ALLOCZ(p, size)\ +{\ + p= av_mallocz(size);\ + if(p==NULL){\ + perror("malloc");\ + goto fail;\ + }\ +} /* init common structure for both encoder and decoder */ int MPV_common_init(MpegEncContext *s) @@ -113,14 +125,19 @@ int MPV_common_init(MpegEncContext *s) int c_size, i; UINT8 *pict; - if (s->out_format == FMT_H263) - s->dct_unquantize = dct_unquantize_h263_c; - else - s->dct_unquantize = dct_unquantize_mpeg1_c; + s->dct_unquantize_h263 = dct_unquantize_h263_c; + s->dct_unquantize_mpeg1 = dct_unquantize_mpeg1_c; + s->dct_unquantize_mpeg2 = dct_unquantize_mpeg2_c; #ifdef HAVE_MMX MPV_common_init_mmx(s); #endif + //setup default unquantizers (mpeg4 might change it later) + if(s->out_format == FMT_H263) + s->dct_unquantize = s->dct_unquantize_h263; + else + s->dct_unquantize = s->dct_unquantize_mpeg1; + s->mb_width = (s->width + 15) / 16; s->mb_height = (s->height + 15) / 16; s->mb_num = s->mb_width * s->mb_height; @@ -135,58 +152,79 @@ int MPV_common_init(MpegEncContext *s) c_size = (w >> shift) * (h >> shift); pict_start = (w >> shift) * (EDGE_WIDTH >> shift) + (EDGE_WIDTH >> shift); - pict = av_mallocz(c_size); - if (pict == NULL) - goto fail; + CHECKED_ALLOCZ(pict, c_size) s->last_picture_base[i] = pict; s->last_picture[i] = pict + pict_start; + if(i>0) memset(s->last_picture_base[i], 128, c_size); - pict = av_mallocz(c_size); - if (pict == NULL) - goto fail; + CHECKED_ALLOCZ(pict, c_size) s->next_picture_base[i] = pict; s->next_picture[i] = pict + pict_start; - - if (s->has_b_frames) { - pict = av_mallocz(c_size); - if (pict == NULL) - goto fail; + if(i>0) memset(s->next_picture_base[i], 128, c_size); + + if (s->has_b_frames || s->codec_id==CODEC_ID_MPEG4) { + /* Note the MPEG4 stuff is here cuz of buggy encoders which dont set the low_delay flag but + do low-delay encoding, so we cant allways distinguish b-frame containing streams from low_delay streams */ + CHECKED_ALLOCZ(pict, c_size) s->aux_picture_base[i] = pict; s->aux_picture[i] = pict + pict_start; + if(i>0) memset(s->aux_picture_base[i], 128, c_size); } } if (s->encoding) { - /* Allocate MB type table */ - s->mb_type = av_mallocz(s->mb_num * sizeof(char)); - if (s->mb_type == NULL) { - perror("malloc"); - goto fail; - } + int j; + int mv_table_size= (s->mb_width+2)*(s->mb_height+2); + + CHECKED_ALLOCZ(s->mb_var , s->mb_num * sizeof(INT16)) + CHECKED_ALLOCZ(s->mc_mb_var, s->mb_num * sizeof(INT16)) + + /* Allocate MV tables */ + CHECKED_ALLOCZ(s->p_mv_table , mv_table_size * 2 * sizeof(INT16)) + CHECKED_ALLOCZ(s->b_forw_mv_table , mv_table_size * 2 * sizeof(INT16)) + CHECKED_ALLOCZ(s->b_back_mv_table , mv_table_size * 2 * sizeof(INT16)) + CHECKED_ALLOCZ(s->b_bidir_forw_mv_table , mv_table_size * 2 * sizeof(INT16)) + CHECKED_ALLOCZ(s->b_bidir_back_mv_table , mv_table_size * 2 * sizeof(INT16)) + CHECKED_ALLOCZ(s->b_direct_forw_mv_table, mv_table_size * 2 * sizeof(INT16)) + CHECKED_ALLOCZ(s->b_direct_back_mv_table, mv_table_size * 2 * sizeof(INT16)) + CHECKED_ALLOCZ(s->b_direct_mv_table , mv_table_size * 2 * sizeof(INT16)) + + CHECKED_ALLOCZ(s->me_scratchpad, s->linesize*16*3*sizeof(uint8_t)) - s->mb_var = av_mallocz(s->mb_num * sizeof(INT16)); - if (s->mb_var == NULL) { - perror("malloc"); - goto fail; + CHECKED_ALLOCZ(s->me_map , ME_MAP_SIZE*sizeof(uint32_t)) + CHECKED_ALLOCZ(s->me_score_map, ME_MAP_SIZE*sizeof(uint16_t)) + + if(s->max_b_frames){ + for(j=0; j<REORDER_BUFFER_SIZE; j++){ + int i; + for(i=0;i<3;i++) { + int w, h, shift; + + w = s->linesize; + h = s->mb_height * 16; + shift = (i == 0) ? 0 : 1; + c_size = (w >> shift) * (h >> shift); + + CHECKED_ALLOCZ(pict, c_size); + s->picture_buffer[j][i] = pict; + } + } } - /* Allocate MV table */ - /* By now we just have one MV per MB */ - s->mv_table[0] = av_mallocz(s->mb_num * sizeof(INT16)); - s->mv_table[1] = av_mallocz(s->mb_num * sizeof(INT16)); - if (s->mv_table[1] == NULL || s->mv_table[0] == NULL) { - perror("malloc"); - goto fail; + + if(s->codec_id==CODEC_ID_MPEG4){ + CHECKED_ALLOCZ(s->tex_pb_buffer, PB_BUFFER_SIZE); + CHECKED_ALLOCZ( s->pb2_buffer, PB_BUFFER_SIZE); } } if (s->out_format == FMT_H263 || s->encoding) { int size; + /* Allocate MB type table */ + CHECKED_ALLOCZ(s->mb_type , s->mb_num * sizeof(UINT8)) + /* MV prediction */ size = (2 * s->mb_width + 2) * (2 * s->mb_height + 2); - s->motion_val = malloc(size * 2 * sizeof(INT16)); - if (s->motion_val == NULL) - goto fail; - memset(s->motion_val, 0, size * 2 * sizeof(INT16)); + CHECKED_ALLOCZ(s->motion_val, size * 2 * sizeof(INT16)); } if (s->h263_pred || s->h263_plus) { @@ -197,43 +235,40 @@ int MPV_common_init(MpegEncContext *s) y_size = (2 * s->mb_width + 2) * (2 * s->mb_height + 2); c_size = (s->mb_width + 2) * (s->mb_height + 2); size = y_size + 2 * c_size; - s->dc_val[0] = malloc(size * sizeof(INT16)); - if (s->dc_val[0] == NULL) - goto fail; + CHECKED_ALLOCZ(s->dc_val[0], size * sizeof(INT16)); s->dc_val[1] = s->dc_val[0] + y_size; s->dc_val[2] = s->dc_val[1] + c_size; for(i=0;i<size;i++) s->dc_val[0][i] = 1024; /* ac values */ - s->ac_val[0] = av_mallocz(size * sizeof(INT16) * 16); - if (s->ac_val[0] == NULL) - goto fail; + CHECKED_ALLOCZ(s->ac_val[0], size * sizeof(INT16) * 16); s->ac_val[1] = s->ac_val[0] + y_size; s->ac_val[2] = s->ac_val[1] + c_size; /* cbp values */ - s->coded_block = av_mallocz(y_size); - if (!s->coded_block) - goto fail; + CHECKED_ALLOCZ(s->coded_block, y_size); /* which mb is a intra block */ - s->mbintra_table = av_mallocz(s->mb_num); - if (!s->mbintra_table) - goto fail; + CHECKED_ALLOCZ(s->mbintra_table, s->mb_num); memset(s->mbintra_table, 1, s->mb_num); + + /* divx501 bitstream reorder buffer */ + CHECKED_ALLOCZ(s->bitstream_buffer, BITSTREAM_BUFFER_SIZE); + + /* cbp, ac_pred, pred_dir */ + CHECKED_ALLOCZ(s->cbp_table , s->mb_num * sizeof(UINT8)) + CHECKED_ALLOCZ(s->pred_dir_table, s->mb_num * sizeof(UINT8)) + + CHECKED_ALLOCZ(s->qscale_table , s->mb_num * sizeof(UINT8)) } /* default structure is frame */ s->picture_structure = PICT_FRAME; /* init macroblock skip table */ - if (!s->encoding) { - s->mbskip_table = av_mallocz(s->mb_num); - if (!s->mbskip_table) - goto fail; - } + CHECKED_ALLOCZ(s->mbskip_table, s->mb_num); - s->block= s->intra_block; + s->block= s->blocks[0]; s->context_initialized = 1; return 0; @@ -242,39 +277,49 @@ int MPV_common_init(MpegEncContext *s) return -1; } + +//extern int sads; + /* init common structure for both encoder and decoder */ void MPV_common_end(MpegEncContext *s) { int i; - if (s->mb_type) - free(s->mb_type); - if (s->mb_var) - free(s->mb_var); - if (s->mv_table[0]) - free(s->mv_table[0]); - if (s->mv_table[1]) - free(s->mv_table[1]); - if (s->motion_val) - free(s->motion_val); - if (s->dc_val[0]) - free(s->dc_val[0]); - if (s->ac_val[0]) - free(s->ac_val[0]); - if (s->coded_block) - free(s->coded_block); - if (s->mbintra_table) - free(s->mbintra_table); - - if (s->mbskip_table) - free(s->mbskip_table); + av_freep(&s->mb_type); + av_freep(&s->mb_var); + av_freep(&s->mc_mb_var); + av_freep(&s->p_mv_table); + av_freep(&s->b_forw_mv_table); + av_freep(&s->b_back_mv_table); + av_freep(&s->b_bidir_forw_mv_table); + av_freep(&s->b_bidir_back_mv_table); + av_freep(&s->b_direct_forw_mv_table); + av_freep(&s->b_direct_back_mv_table); + av_freep(&s->b_direct_mv_table); + av_freep(&s->motion_val); + av_freep(&s->dc_val[0]); + av_freep(&s->ac_val[0]); + av_freep(&s->coded_block); + av_freep(&s->mbintra_table); + av_freep(&s->cbp_table); + av_freep(&s->pred_dir_table); + av_freep(&s->qscale_table); + av_freep(&s->me_scratchpad); + av_freep(&s->me_map); + av_freep(&s->me_score_map); + + av_freep(&s->mbskip_table); + av_freep(&s->bitstream_buffer); + av_freep(&s->tex_pb_buffer); + av_freep(&s->pb2_buffer); for(i=0;i<3;i++) { - if (s->last_picture_base[i]) - free(s->last_picture_base[i]); - if (s->next_picture_base[i]) - free(s->next_picture_base[i]); - if (s->has_b_frames) - free(s->aux_picture_base[i]); + int j; + av_freep(&s->last_picture_base[i]); + av_freep(&s->next_picture_base[i]); + av_freep(&s->aux_picture_base[i]); + for(j=0; j<REORDER_BUFFER_SIZE; j++){ + av_freep(&s->picture_buffer[j][i]); + } } s->context_initialized = 0; } @@ -285,11 +330,17 @@ int MPV_encode_init(AVCodecContext *avctx) MpegEncContext *s = avctx->priv_data; int i; + avctx->pix_fmt = PIX_FMT_YUV420P; + 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){ + fprintf(stderr, "Warning keyframe interval too large! reducing it ...\n"); + avctx->gop_size=600; + } s->gop_size = avctx->gop_size; s->rtp_mode = avctx->rtp_mode; s->rtp_payload_size = avctx->rtp_payload_size; @@ -300,36 +351,56 @@ int MPV_encode_init(AVCodecContext *avctx) s->max_qdiff= avctx->max_qdiff; s->qcompress= avctx->qcompress; s->qblur= avctx->qblur; + s->b_quant_factor= avctx->b_quant_factor; + s->b_quant_offset= avctx->b_quant_offset; s->avctx = avctx; s->aspect_ratio_info= avctx->aspect_ratio_info; s->flags= avctx->flags; - + s->max_b_frames= avctx->max_b_frames; + s->rc_strategy= avctx->rc_strategy; + s->b_frame_strategy= avctx->b_frame_strategy; + s->codec_id= avctx->codec->id; + s->luma_elim_threshold = avctx->luma_elim_threshold; + s->chroma_elim_threshold= avctx->chroma_elim_threshold; + s->strict_std_compliance= avctx->strict_std_compliance; + s->data_partitioning= avctx->flags & CODEC_FLAG_PART; + if (s->gop_size <= 1) { s->intra_only = 1; s->gop_size = 12; } else { s->intra_only = 0; } - s->full_search = motion_estimation_method; - + + /* ME algorithm */ + if (avctx->me_method == 0) + /* For compatibility */ + s->me_method = motion_estimation_method; + else + s->me_method = avctx->me_method; + + /* Fixed QSCALE */ s->fixed_qscale = (avctx->flags & CODEC_FLAG_QSCALE); switch(avctx->codec->id) { case CODEC_ID_MPEG1VIDEO: s->out_format = FMT_MPEG1; + avctx->delay=0; //FIXME not sure, should check the spec break; case CODEC_ID_MJPEG: s->out_format = FMT_MJPEG; s->intra_only = 1; /* force intra only for jpeg */ s->mjpeg_write_tables = 1; /* write all tables */ + s->mjpeg_data_only_frames = 0; /* write all the needed headers */ s->mjpeg_vsample[0] = 2; /* set up default sampling factors */ s->mjpeg_vsample[1] = 1; /* the only currently supported values */ s->mjpeg_vsample[2] = 1; - s->mjpeg_hsample[0] = 2; + s->mjpeg_hsample[0] = 2; s->mjpeg_hsample[1] = 1; s->mjpeg_hsample[2] = 1; if (mjpeg_init(s) < 0) return -1; + avctx->delay=0; break; case CODEC_ID_H263: if (h263_get_picture_format(s->width, s->height) == 7) { @@ -337,6 +408,7 @@ int MPV_encode_init(AVCodecContext *avctx) return -1; } s->out_format = FMT_H263; + avctx->delay=0; break; case CODEC_ID_H263P: s->out_format = FMT_H263; @@ -344,19 +416,25 @@ int MPV_encode_init(AVCodecContext *avctx) s->rtp_payload_size = 1200; s->h263_plus = 1; s->unrestricted_mv = 1; + s->h263_aic = 1; /* These are just to be sure */ s->umvplus = 0; s->umvplus_dec = 0; + avctx->delay=0; break; case CODEC_ID_RV10: s->out_format = FMT_H263; s->h263_rv10 = 1; + avctx->delay=0; break; case CODEC_ID_MPEG4: s->out_format = FMT_H263; s->h263_pred = 1; s->unrestricted_mv = 1; + s->has_b_frames= s->max_b_frames ? 1 : 0; + s->low_delay=0; + avctx->delay= s->low_delay ? 0 : (s->max_b_frames + 1); break; case CODEC_ID_MSMPEG4V1: s->out_format = FMT_H263; @@ -364,6 +442,7 @@ int MPV_encode_init(AVCodecContext *avctx) s->h263_pred = 1; s->unrestricted_mv = 1; s->msmpeg4_version= 1; + avctx->delay=0; break; case CODEC_ID_MSMPEG4V2: s->out_format = FMT_H263; @@ -371,6 +450,7 @@ int MPV_encode_init(AVCodecContext *avctx) s->h263_pred = 1; s->unrestricted_mv = 1; s->msmpeg4_version= 2; + avctx->delay=0; break; case CODEC_ID_MSMPEG4V3: s->out_format = FMT_H263; @@ -378,16 +458,12 @@ int MPV_encode_init(AVCodecContext *avctx) s->h263_pred = 1; s->unrestricted_mv = 1; s->msmpeg4_version= 3; + avctx->delay=0; break; default: return -1; } - if((s->flags&CODEC_FLAG_4MV) && !(s->flags&CODEC_FLAG_HQ)){ - printf("4MV is currently only supported in HQ mode\n"); - return -1; - } - { /* set up some save defaults, some codecs might override them later */ static int done=0; if(!done){ @@ -410,7 +486,7 @@ int MPV_encode_init(AVCodecContext *avctx) mpeg1_encode_init(s); /* dont use mv_penalty table for crap MV as it would be confused */ - if(s->full_search<4) s->mv_penalty= default_mv_penalty; + if (s->me_method < ME_EPZS) s->mv_penalty = default_mv_penalty; s->encoding = 1; @@ -420,18 +496,32 @@ int MPV_encode_init(AVCodecContext *avctx) /* init default q matrix */ for(i=0;i<64;i++) { - s->intra_matrix[i] = default_intra_matrix[i]; - s->non_intra_matrix[i] = default_non_intra_matrix[i]; + if(s->out_format == FMT_H263) + s->intra_matrix[i] = default_non_intra_matrix[i]; + else + s->intra_matrix[i] = default_intra_matrix[i]; + + s->inter_matrix[i] = default_non_intra_matrix[i]; } - /* rate control init */ - rate_control_init(s); + /* precompute matrix */ + /* for mjpeg, we do include qscale in the matrix */ + if (s->out_format != FMT_MJPEG) { + convert_matrix(s->q_intra_matrix, s->q_intra_matrix16, s->q_intra_matrix16_bias, + s->intra_matrix, s->intra_quant_bias); + convert_matrix(s->q_inter_matrix, s->q_inter_matrix16, s->q_inter_matrix16_bias, + s->inter_matrix, s->inter_quant_bias); + } + + if(ff_rate_control_init(s) < 0) + return -1; s->picture_number = 0; s->picture_in_gop_number = 0; s->fake_picture_number = 0; /* motion detector init */ s->f_code = 1; + s->b_code = 1; return 0; } @@ -443,6 +533,9 @@ int MPV_encode_end(AVCodecContext *avctx) #ifdef STATS print_stats(); #endif + + ff_rate_control_uninit(s); + MPV_common_end(s); if (s->out_format == FMT_MJPEG) mjpeg_close(s); @@ -485,12 +578,13 @@ void MPV_frame_start(MpegEncContext *s) UINT8 *tmp; s->mb_skiped = 0; + s->decoding_error=0; + if (s->pict_type == B_TYPE) { for(i=0;i<3;i++) { s->current_picture[i] = s->aux_picture[i]; } } else { - s->last_non_b_pict_type= s->pict_type; for(i=0;i<3;i++) { /* swap next and last */ tmp = s->last_picture[i]; @@ -504,9 +598,11 @@ void MPV_frame_start(MpegEncContext *s) /* generic function for encode/decode called after a frame has been coded/decoded */ void MPV_frame_end(MpegEncContext *s) { +// if((s->picture_number%100)==0 && s->encoding) printf("sads:%d //\n", sads); + /* draw edge for correct motion prediction if outside */ if (s->pict_type != B_TYPE && !s->intra_only) { - if(s->avctx==NULL || s->avctx->codec->id!=CODEC_ID_MPEG4 || s->divx_version==500){ + if(s->avctx==NULL || s->avctx->codec->id!=CODEC_ID_MPEG4 || s->divx_version>=500){ draw_edges(s->current_picture[0], s->linesize, s->mb_width*16, s->mb_height*16, EDGE_WIDTH); draw_edges(s->current_picture[1], s->linesize/2, s->mb_width*8, s->mb_height*8, EDGE_WIDTH/2); draw_edges(s->current_picture[2], s->linesize/2, s->mb_width*8, s->mb_height*8, EDGE_WIDTH/2); @@ -518,107 +614,195 @@ void MPV_frame_end(MpegEncContext *s) } } emms_c(); + + if(s->pict_type!=B_TYPE){ + s->last_non_b_pict_type= s->pict_type; + s->last_non_b_qscale= s->qscale; + s->last_non_b_mc_mb_var= s->mc_mb_var_sum; + s->num_available_buffers++; + if(s->num_available_buffers>2) s->num_available_buffers= 2; + } } -int MPV_encode_picture(AVCodecContext *avctx, - unsigned char *buf, int buf_size, void *data) +/* reorder input for encoding */ +void reorder_input(MpegEncContext *s, AVPicture *pict) { - MpegEncContext *s = avctx->priv_data; - AVPicture *pict = data; - int i, j; + int i, j, index; + + if(s->max_b_frames > FF_MAX_B_FRAMES) s->max_b_frames= FF_MAX_B_FRAMES; - if (s->fixed_qscale) - s->qscale = avctx->quality; +// delay= s->max_b_frames+1; (or 0 if no b frames cuz decoder diff) - init_put_bits(&s->pb, buf, buf_size, NULL, NULL); - - s->force_type= (avctx->flags&CODEC_FLAG_TYPE) ? - (avctx->key_frame ? I_TYPE : P_TYPE) : 0; - if (!s->intra_only) { - /* first picture of GOP is intra */ - if (s->picture_in_gop_number % s->gop_size==0 || s->force_type==I_TYPE){ - s->picture_in_gop_number=0; - s->pict_type = I_TYPE; - }else - s->pict_type = P_TYPE; - } else { - s->pict_type = I_TYPE; + for(j=0; j<REORDER_BUFFER_SIZE-1; j++){ + s->coded_order[j]= s->coded_order[j+1]; } - - MPV_frame_start(s); - - for(i=0;i<3;i++) { - UINT8 *src = pict->data[i]; - UINT8 *dest = s->current_picture[i]; - int src_wrap = pict->linesize[i]; - int dest_wrap = s->linesize; - int w = s->width; - int h = s->height; - - if (i >= 1) { - dest_wrap >>= 1; - w >>= 1; - h >>= 1; + s->coded_order[j].picture[0]= s->coded_order[j].picture[1]= s->coded_order[j].picture[2]= NULL; //catch uninitalized buffers + s->coded_order[j].pict_type=0; + + switch(s->input_pict_type){ + default: + case I_TYPE: + case S_TYPE: + case P_TYPE: + index= s->max_b_frames - s->b_frames_since_non_b; + s->b_frames_since_non_b=0; + break; + case B_TYPE: + index= s->max_b_frames + 1; + s->b_frames_since_non_b++; + break; + } +//printf("index:%d type:%d strides: %d %d\n", index, s->input_pict_type, pict->linesize[0], s->linesize); + if( (index==0 || (s->flags&CODEC_FLAG_INPUT_PRESERVED)) + && pict->linesize[0] == s->linesize + && pict->linesize[1] == s->linesize>>1 + && pict->linesize[2] == s->linesize>>1){ +//printf("ptr\n"); + for(i=0; i<3; i++){ + s->coded_order[index].picture[i]= pict->data[i]; } + }else{ +//printf("copy\n"); + for(i=0; i<3; i++){ + uint8_t *src = pict->data[i]; + uint8_t *dest; + int src_wrap = pict->linesize[i]; + int dest_wrap = s->linesize; + int w = s->width; + int h = s->height; + + if(index==0) dest= s->last_picture[i]+16; //is current_picture indeed but the switch hapens after reordering + else dest= s->picture_buffer[s->picture_buffer_index][i]; + + if (i >= 1) { + dest_wrap >>= 1; + w >>= 1; + h >>= 1; + } - if(dest_wrap==src_wrap){ - s->new_picture[i] = pict->data[i]; - } else { + s->coded_order[index].picture[i]= dest; for(j=0;j<h;j++) { memcpy(dest, src, w); dest += dest_wrap; src += src_wrap; } - s->new_picture[i] = s->current_picture[i]; - } + } + if(index!=0){ + s->picture_buffer_index++; + if(s->picture_buffer_index >= REORDER_BUFFER_SIZE-1) s->picture_buffer_index=0; + } + } + s->coded_order[index].pict_type = s->input_pict_type; + s->coded_order[index].qscale = s->input_qscale; + s->coded_order[index].force_type= s->force_input_type; + s->coded_order[index].picture_in_gop_number= s->input_picture_in_gop_number; + s->coded_order[index].picture_number= s->input_picture_number; + + for(i=0; i<3; i++){ + s->new_picture[i]= s->coded_order[0].picture[i]; } +} + +int MPV_encode_picture(AVCodecContext *avctx, + unsigned char *buf, int buf_size, void *data) +{ + MpegEncContext *s = avctx->priv_data; + AVPicture *pict = data; - encode_picture(s, s->picture_number); - avctx->key_frame = (s->pict_type == I_TYPE); - avctx->header_bits = s->header_bits; - avctx->mv_bits = s->mv_bits; - avctx->misc_bits = s->misc_bits; - avctx->i_tex_bits = s->i_tex_bits; - avctx->p_tex_bits = s->p_tex_bits; - avctx->i_count = s->i_count; - avctx->p_count = s->p_count; - avctx->skip_count = s->skip_count; + s->input_qscale = avctx->quality; - MPV_frame_end(s); - s->picture_number++; - s->picture_in_gop_number++; + init_put_bits(&s->pb, buf, buf_size, NULL, NULL); - if (s->out_format == FMT_MJPEG) - mjpeg_picture_trailer(s); + if(avctx->flags&CODEC_FLAG_TYPE){ + s->input_pict_type= + s->force_input_type= avctx->key_frame ? I_TYPE : P_TYPE; + }else if(s->flags&CODEC_FLAG_PASS2){ + s->input_pict_type= + s->force_input_type= s->rc_context.entry[s->input_picture_number].new_pict_type; + }else{ + s->force_input_type=0; + if (!s->intra_only) { + /* first picture of GOP is intra */ + if (s->input_picture_in_gop_number % s->gop_size==0){ + s->input_pict_type = I_TYPE; + }else if(s->max_b_frames==0){ + s->input_pict_type = P_TYPE; + }else{ + if(s->b_frames_since_non_b < s->max_b_frames) //FIXME more IQ + s->input_pict_type = B_TYPE; + else + s->input_pict_type = P_TYPE; + } + } else { + s->input_pict_type = I_TYPE; + } + } + + if(s->input_pict_type==I_TYPE) + s->input_picture_in_gop_number=0; + + reorder_input(s, pict); + + /* output? */ + if(s->coded_order[0].picture[0]){ + + s->pict_type= s->coded_order[0].pict_type; + if (s->fixed_qscale) /* the ratecontrol needs the last qscale so we dont touch it for CBR */ + s->qscale= s->coded_order[0].qscale; + s->force_type= s->coded_order[0].force_type; + s->picture_in_gop_number= s->coded_order[0].picture_in_gop_number; + s->picture_number= s->coded_order[0].picture_number; + + MPV_frame_start(s); + + encode_picture(s, s->picture_number); + avctx->key_frame = (s->pict_type == I_TYPE); + avctx->pict_type = s->pict_type; + avctx->real_pict_num = s->picture_number; + avctx->header_bits = s->header_bits; + avctx->mv_bits = s->mv_bits; + avctx->misc_bits = s->misc_bits; + avctx->i_tex_bits = s->i_tex_bits; + avctx->p_tex_bits = s->p_tex_bits; + avctx->i_count = s->i_count; + avctx->p_count = s->p_count; + avctx->skip_count = s->skip_count; + + MPV_frame_end(s); + + if (s->out_format == FMT_MJPEG) + mjpeg_picture_trailer(s); + + avctx->quality = s->qscale; + + if(s->flags&CODEC_FLAG_PASS1) + ff_write_pass1_stats(s); + + } + + s->input_picture_number++; + s->input_picture_in_gop_number++; flush_put_bits(&s->pb); - s->last_frame_bits= s->frame_bits; s->frame_bits = (pbBufPtr(&s->pb) - s->pb.buf) * 8; + if(s->pict_type==B_TYPE) s->pb_frame_bits+= s->frame_bits; + else s->pb_frame_bits= s->frame_bits; + s->total_bits += s->frame_bits; avctx->frame_bits = s->frame_bits; //printf("fcode: %d, type: %d, head: %d, mv: %d, misc: %d, frame: %d, itex: %d, ptex: %d\n", //s->f_code, avctx->key_frame, s->header_bits, s->mv_bits, s->misc_bits, s->frame_bits, s->i_tex_bits, s->p_tex_bits); - avctx->quality = s->qscale; if (avctx->get_psnr) { /* At this point pict->data should have the original frame */ /* an s->current_picture should have the coded/decoded frame */ get_psnr(pict->data, s->current_picture, pict->linesize, s->linesize, avctx); +// printf("%f\n", avctx->psnr_y); } return pbBufPtr(&s->pb) - s->pb.buf; } -static inline int clip(int a, int amin, int amax) -{ - if (a < amin) - return amin; - else if (a > amax) - return amax; - else - return a; -} - static inline void gmc1_motion(MpegEncContext *s, UINT8 *dest_y, UINT8 *dest_cb, UINT8 *dest_cr, int dest_offset, @@ -626,7 +810,7 @@ static inline void gmc1_motion(MpegEncContext *s, int h) { UINT8 *ptr; - int dxy, offset, mx, my, src_x, src_y, height, linesize; + int offset, src_x, src_y, linesize; int motion_x, motion_y; if(s->real_sprite_warping_points>1) printf("more than 1 warp point isnt supported\n"); @@ -705,6 +889,8 @@ if(s->quarter_sample) pix_op[dxy](dest_y, ptr, linesize, h); pix_op[dxy](dest_y + 8, ptr + 8, linesize, h); + if(s->flags&CODEC_FLAG_GRAY) return; + if (s->out_format == FMT_H263) { dxy = 0; if ((motion_x & 3) != 0) @@ -768,6 +954,8 @@ static inline void qpel_motion(MpegEncContext *s, qpix_op[dxy](dest_y + linesize*8 , ptr + linesize*8 , linesize, linesize, motion_x&3, motion_y&3); qpix_op[dxy](dest_y + linesize*8 + 8, ptr + linesize*8 + 8, linesize, linesize, motion_x&3, motion_y&3); + if(s->flags&CODEC_FLAG_GRAY) return; + mx= (motion_x>>1) | (motion_x&1); my= (motion_y>>1) | (motion_y&1); @@ -856,6 +1044,8 @@ static inline void MPV_motion(MpegEncContext *s, dest = dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize; pix_op[dxy](dest, ptr, s->linesize, 8); } + + if(s->flags&CODEC_FLAG_GRAY) break; /* In case of 8X8, we construct a single chroma motion vector with a special rounding */ mx = 0; @@ -922,8 +1112,7 @@ static inline void put_dct(MpegEncContext *s, { if (!s->mpeg2) s->dct_unquantize(s, block, i, s->qscale); - ff_idct (block); - put_pixels_clamped(block, dest, line_size); + ff_idct_put (dest, line_size, block); } /* add block[] to dest[] */ @@ -931,14 +1120,53 @@ static inline void add_dct(MpegEncContext *s, DCTELEM *block, int i, UINT8 *dest, int line_size) { if (s->block_last_index[i] >= 0) { - if (!s->mpeg2) - if(s->encoding || (!s->h263_msmpeg4)) - s->dct_unquantize(s, block, i, s->qscale); - ff_idct (block); - add_pixels_clamped(block, dest, line_size); + ff_idct_add (dest, line_size, block); } } +static inline void add_dequant_dct(MpegEncContext *s, + DCTELEM *block, int i, UINT8 *dest, int line_size) +{ + if (s->block_last_index[i] >= 0) { + s->dct_unquantize(s, block, i, s->qscale); + + ff_idct_add (dest, line_size, block); + } +} + +/** + * cleans dc, ac, coded_block for the current non intra MB + */ +void ff_clean_intra_table_entries(MpegEncContext *s) +{ + int wrap = s->block_wrap[0]; + int xy = s->block_index[0]; + + s->dc_val[0][xy ] = + s->dc_val[0][xy + 1 ] = + s->dc_val[0][xy + wrap] = + s->dc_val[0][xy + 1 + wrap] = 1024; + /* ac pred */ + memset(s->ac_val[0][xy ], 0, 32 * sizeof(INT16)); + memset(s->ac_val[0][xy + wrap], 0, 32 * sizeof(INT16)); + if (s->msmpeg4_version>=3) { + s->coded_block[xy ] = + s->coded_block[xy + 1 ] = + s->coded_block[xy + wrap] = + s->coded_block[xy + 1 + wrap] = 0; + } + /* chroma */ + wrap = s->block_wrap[4]; + xy = s->mb_x + 1 + (s->mb_y + 1) * wrap; + s->dc_val[1][xy] = + s->dc_val[2][xy] = 1024; + /* ac pred */ + memset(s->ac_val[1][xy], 0, 16 * sizeof(INT16)); + memset(s->ac_val[2][xy], 0, 16 * sizeof(INT16)); + + s->mbintra_table[s->mb_x + s->mb_y*s->mb_width]= 0; +} + /* generic function called after a macroblock has been parsed by the decoder or after it has been encoded by the encoder. @@ -952,69 +1180,39 @@ static inline void add_dct(MpegEncContext *s, void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) { int mb_x, mb_y; - int dct_linesize, dct_offset; - op_pixels_func *op_pix; - qpel_mc_func *op_qpix; + const int mb_xy = s->mb_y * s->mb_width + s->mb_x; mb_x = s->mb_x; mb_y = s->mb_y; #ifdef FF_POSTPROCESS + /* Obsolete. Exists for compatibility with mplayer only. */ quant_store[mb_y][mb_x]=s->qscale; //printf("[%02d][%02d] %d\n",mb_x,mb_y,s->qscale); +#else + if(s->avctx->quant_store) s->avctx->quant_store[mb_y*s->avctx->qstride+mb_x] = s->qscale; #endif /* update DC predictors for P macroblocks */ if (!s->mb_intra) { if (s->h263_pred || s->h263_aic) { - if(s->mbintra_table[mb_x + mb_y*s->mb_width]) - { - int wrap, xy, v; - s->mbintra_table[mb_x + mb_y*s->mb_width]=0; - wrap = 2 * s->mb_width + 2; - xy = 2 * mb_x + 1 + (2 * mb_y + 1) * wrap; - v = 1024; - - s->dc_val[0][xy] = v; - s->dc_val[0][xy + 1] = v; - s->dc_val[0][xy + wrap] = v; - s->dc_val[0][xy + 1 + wrap] = v; - /* ac pred */ - memset(s->ac_val[0][xy], 0, 16 * sizeof(INT16)); - memset(s->ac_val[0][xy + 1], 0, 16 * sizeof(INT16)); - memset(s->ac_val[0][xy + wrap], 0, 16 * sizeof(INT16)); - memset(s->ac_val[0][xy + 1 + wrap], 0, 16 * sizeof(INT16)); - if (s->h263_msmpeg4) { - s->coded_block[xy] = 0; - s->coded_block[xy + 1] = 0; - s->coded_block[xy + wrap] = 0; - s->coded_block[xy + 1 + wrap] = 0; - } - /* chroma */ - wrap = s->mb_width + 2; - xy = mb_x + 1 + (mb_y + 1) * wrap; - s->dc_val[1][xy] = v; - s->dc_val[2][xy] = v; - /* ac pred */ - memset(s->ac_val[1][xy], 0, 16 * sizeof(INT16)); - memset(s->ac_val[2][xy], 0, 16 * sizeof(INT16)); - } + if(s->mbintra_table[mb_xy]) + ff_clean_intra_table_entries(s); } else { - s->last_dc[0] = 128 << s->intra_dc_precision; - s->last_dc[1] = 128 << s->intra_dc_precision; + s->last_dc[0] = + s->last_dc[1] = s->last_dc[2] = 128 << s->intra_dc_precision; } } else if (s->h263_pred || s->h263_aic) - s->mbintra_table[mb_x + mb_y*s->mb_width]=1; + s->mbintra_table[mb_xy]=1; /* update motion predictor, not for B-frames as they need the motion_val from the last P/S-Frame */ - if (s->out_format == FMT_H263) { - if(s->pict_type!=B_TYPE){ - int xy, wrap, motion_x, motion_y; + if (s->out_format == FMT_H263 && s->pict_type!=B_TYPE) { //FIXME move into h263.c if possible, format specific stuff shouldnt be here + int motion_x, motion_y; - wrap = 2 * s->mb_width + 2; - xy = 2 * mb_x + 1 + (2 * mb_y + 1) * wrap; + const int wrap = s->block_wrap[0]; + const int xy = s->block_index[0]; if (s->mb_intra) { motion_x = 0; motion_y = 0; @@ -1033,20 +1231,23 @@ void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) s->motion_val[xy + 1 + wrap][0] = motion_x; s->motion_val[xy + 1 + wrap][1] = motion_y; } - } } - if (!s->intra_only) { + if (!(s->encoding && (s->intra_only || s->pict_type==B_TYPE))) { UINT8 *dest_y, *dest_cb, *dest_cr; - UINT8 *mbskip_ptr; - - /* avoid copy if macroblock skipped in last frame too */ - if (!s->encoding && s->pict_type != B_TYPE) { - mbskip_ptr = &s->mbskip_table[s->mb_y * s->mb_width + s->mb_x]; + int dct_linesize, dct_offset; + op_pixels_func *op_pix; + qpel_mc_func *op_qpix; + + /* avoid copy if macroblock skipped in last frame too + dont touch it for B-frames as they need the skip info from the next p-frame */ + if (s->pict_type != B_TYPE) { + UINT8 *mbskip_ptr = &s->mbskip_table[mb_xy]; if (s->mb_skiped) { s->mb_skiped = 0; - /* if previous was skipped too, then nothing to do ! */ - if (*mbskip_ptr != 0) + /* if previous was skipped too, then nothing to do ! + skip only during decoding as we might trash the buffers during encoding a bit */ + if (*mbskip_ptr != 0 && !s->encoding) goto the_end; *mbskip_ptr = 1; /* indicate that this time we skiped it */ } else { @@ -1068,33 +1269,53 @@ void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) if (!s->mb_intra) { /* motion handling */ - if (!s->no_rounding){ - op_pix = put_pixels_tab; - op_qpix= qpel_mc_rnd_tab; - }else{ - op_pix = put_no_rnd_pixels_tab; - op_qpix= qpel_mc_no_rnd_tab; - } + /* decoding or more than one mb_type (MC was allready done otherwise) */ + if((!s->encoding) || (s->mb_type[mb_xy]&(s->mb_type[mb_xy]-1))){ + if ((!s->no_rounding) || s->pict_type==B_TYPE){ + op_pix = put_pixels_tab; + op_qpix= qpel_mc_rnd_tab; + }else{ + op_pix = put_no_rnd_pixels_tab; + op_qpix= qpel_mc_no_rnd_tab; + } - if (s->mv_dir & MV_DIR_FORWARD) { - MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture, op_pix, op_qpix); - if (!s->no_rounding) - op_pix = avg_pixels_tab; - else - op_pix = avg_no_rnd_pixels_tab; - } - if (s->mv_dir & MV_DIR_BACKWARD) { - MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture, op_pix, op_qpix); + if (s->mv_dir & MV_DIR_FORWARD) { + MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture, op_pix, op_qpix); + if ((!s->no_rounding) || s->pict_type==B_TYPE) + op_pix = avg_pixels_tab; + else + op_pix = avg_no_rnd_pixels_tab; + } + if (s->mv_dir & MV_DIR_BACKWARD) { + MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture, op_pix, op_qpix); + } } - /* add dct residue */ - add_dct(s, block[0], 0, dest_y, dct_linesize); - add_dct(s, block[1], 1, dest_y + 8, dct_linesize); - add_dct(s, block[2], 2, dest_y + dct_offset, dct_linesize); - add_dct(s, block[3], 3, dest_y + dct_offset + 8, dct_linesize); + /* skip dequant / idct if we are really late ;) */ + if(s->hurry_up>1) goto the_end; - add_dct(s, block[4], 4, dest_cb, s->linesize >> 1); - add_dct(s, block[5], 5, dest_cr, s->linesize >> 1); + /* add dct residue */ + if(!s->mpeg2 && (s->encoding || (!s->h263_msmpeg4))){ + add_dequant_dct(s, block[0], 0, dest_y, dct_linesize); + add_dequant_dct(s, block[1], 1, dest_y + 8, dct_linesize); + add_dequant_dct(s, block[2], 2, dest_y + dct_offset, dct_linesize); + add_dequant_dct(s, block[3], 3, dest_y + dct_offset + 8, dct_linesize); + + if(!(s->flags&CODEC_FLAG_GRAY)){ + add_dequant_dct(s, block[4], 4, dest_cb, s->linesize >> 1); + add_dequant_dct(s, block[5], 5, dest_cr, s->linesize >> 1); + } + } else { + add_dct(s, block[0], 0, dest_y, dct_linesize); + add_dct(s, block[1], 1, dest_y + 8, dct_linesize); + add_dct(s, block[2], 2, dest_y + dct_offset, dct_linesize); + add_dct(s, block[3], 3, dest_y + dct_offset + 8, dct_linesize); + + if(!(s->flags&CODEC_FLAG_GRAY)){ + add_dct(s, block[4], 4, dest_cb, s->linesize >> 1); + add_dct(s, block[5], 5, dest_cr, s->linesize >> 1); + } + } } else { /* dct only in intra block */ put_dct(s, block[0], 0, dest_y, dct_linesize); @@ -1102,128 +1323,188 @@ void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) put_dct(s, block[2], 2, dest_y + dct_offset, dct_linesize); put_dct(s, block[3], 3, dest_y + dct_offset + 8, dct_linesize); - put_dct(s, block[4], 4, dest_cb, s->linesize >> 1); - put_dct(s, block[5], 5, dest_cr, s->linesize >> 1); + if(!(s->flags&CODEC_FLAG_GRAY)){ + put_dct(s, block[4], 4, dest_cb, s->linesize >> 1); + put_dct(s, block[5], 5, dest_cr, s->linesize >> 1); + } } } the_end: emms_c(); //FIXME remove } -static void encode_mb(MpegEncContext *s) +static inline void dct_single_coeff_elimination(MpegEncContext *s, int n, int threshold, int skip_dc) +{ + static const char tab[64]= + {3,2,2,1,1,1,1,1, + 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0}; + int score=0; + int run=0; + int i; + DCTELEM *block= s->block[n]; + const int last_index= s->block_last_index[n]; + + if(skip_dc) skip_dc=1; + + /* are all which we could set to zero are allready zero? */ + if(last_index<=skip_dc - 1) return; + + for(i=0; i<=last_index; i++){ + const int j = zigzag_direct[i]; + const int level = ABS(block[j]); + if(level==1){ + if(skip_dc && i==0) continue; + score+= tab[run]; + run=0; + }else if(level>1){ + return; + }else{ + run++; + } + } + if(score >= threshold) return; + for(i=skip_dc; i<=last_index; i++){ + const int j = zigzag_direct[i]; + block[j]=0; + } + if(block[0]) s->block_last_index[n]= 0; + else s->block_last_index[n]= -1; +} + +static inline void clip_coeffs(MpegEncContext *s, DCTELEM *block, int last_index) +{ + int i; + const int maxlevel= s->max_qcoeff; + const int minlevel= s->min_qcoeff; + + for(i=0;i<=last_index; i++){ + const int j = zigzag_direct[i]; + int level = block[j]; + + if (level>maxlevel) level=maxlevel; + else if(level<minlevel) level=minlevel; + block[j]= level; + } +} + +static void encode_mb(MpegEncContext *s, int motion_x, int motion_y) { - int wrap; const int mb_x= s->mb_x; const int mb_y= s->mb_y; - UINT8 *ptr; - const int motion_x= s->mv[0][0][0]; - const int motion_y= s->mv[0][0][1]; int i; + int skip_dct[6]; +#if 0 + if (s->interlaced_dct) { + dct_linesize = s->linesize * 2; + dct_offset = s->linesize; + } else { + dct_linesize = s->linesize; + dct_offset = s->linesize * 8; + } +#endif + for(i=0; i<6; i++) skip_dct[i]=0; - /* get the pixels */ - wrap = s->linesize; - ptr = s->new_picture[0] + (mb_y * 16 * wrap) + mb_x * 16; - get_pixels(s->block[0], ptr, wrap); - get_pixels(s->block[1], ptr + 8, wrap); - get_pixels(s->block[2], ptr + 8 * wrap, wrap); - get_pixels(s->block[3], ptr + 8 * wrap + 8, wrap); - wrap = s->linesize >> 1; - ptr = s->new_picture[1] + (mb_y * 8 * wrap) + mb_x * 8; - get_pixels(s->block[4], ptr, wrap); - - wrap = s->linesize >> 1; - ptr = s->new_picture[2] + (mb_y * 8 * wrap) + mb_x * 8; - get_pixels(s->block[5], ptr, wrap); - - /* subtract previous frame if non intra */ - if (!s->mb_intra) { - int dxy, offset, mx, my; + if (s->mb_intra) { + UINT8 *ptr; + int wrap; + + wrap = s->linesize; + ptr = s->new_picture[0] + (mb_y * 16 * wrap) + mb_x * 16; + get_pixels(s->block[0], ptr , wrap); + get_pixels(s->block[1], ptr + 8, wrap); + get_pixels(s->block[2], ptr + 8 * wrap , wrap); + get_pixels(s->block[3], ptr + 8 * wrap + 8, wrap); + + if(s->flags&CODEC_FLAG_GRAY){ + skip_dct[4]= 1; + skip_dct[5]= 1; + }else{ + wrap >>=1; + ptr = s->new_picture[1] + (mb_y * 8 * wrap) + mb_x * 8; + get_pixels(s->block[4], ptr, wrap); + + ptr = s->new_picture[2] + (mb_y * 8 * wrap) + mb_x * 8; + get_pixels(s->block[5], ptr, wrap); + } + }else{ + op_pixels_func *op_pix; + qpel_mc_func *op_qpix; + UINT8 *dest_y, *dest_cb, *dest_cr; + UINT8 *ptr_y, *ptr_cb, *ptr_cr; + int wrap_y, wrap_c; + + dest_y = s->current_picture[0] + (mb_y * 16 * s->linesize ) + mb_x * 16; + dest_cb = s->current_picture[1] + (mb_y * 8 * (s->linesize >> 1)) + mb_x * 8; + dest_cr = s->current_picture[2] + (mb_y * 8 * (s->linesize >> 1)) + mb_x * 8; + wrap_y = s->linesize; + wrap_c = wrap_y>>1; + ptr_y = s->new_picture[0] + (mb_y * 16 * wrap_y) + mb_x * 16; + ptr_cb = s->new_picture[1] + (mb_y * 8 * wrap_c) + mb_x * 8; + ptr_cr = s->new_picture[2] + (mb_y * 8 * wrap_c) + mb_x * 8; + + if ((!s->no_rounding) || s->pict_type==B_TYPE){ + op_pix = put_pixels_tab; + op_qpix= qpel_mc_rnd_tab; + }else{ + op_pix = put_no_rnd_pixels_tab; + op_qpix= qpel_mc_no_rnd_tab; + } + + if (s->mv_dir & MV_DIR_FORWARD) { + MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture, op_pix, op_qpix); + if ((!s->no_rounding) || s->pict_type==B_TYPE) + op_pix = avg_pixels_tab; + else + op_pix = avg_no_rnd_pixels_tab; + } + if (s->mv_dir & MV_DIR_BACKWARD) { + MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture, op_pix, op_qpix); + } + + diff_pixels(s->block[0], ptr_y , dest_y , wrap_y); + diff_pixels(s->block[1], ptr_y + 8, dest_y + 8, wrap_y); + diff_pixels(s->block[2], ptr_y + 8 * wrap_y , dest_y + 8 * wrap_y , wrap_y); + diff_pixels(s->block[3], ptr_y + 8 * wrap_y + 8, dest_y + 8 * wrap_y + 8, wrap_y); - if(s->mv_type==MV_TYPE_16X16){ - dxy = ((motion_y & 1) << 1) | (motion_x & 1); - ptr = s->last_picture[0] + - ((mb_y * 16 + (motion_y >> 1)) * s->linesize) + - (mb_x * 16 + (motion_x >> 1)); - - sub_pixels_2(s->block[0], ptr, s->linesize, dxy); - sub_pixels_2(s->block[1], ptr + 8, s->linesize, dxy); - sub_pixels_2(s->block[2], ptr + s->linesize * 8, s->linesize, dxy); - sub_pixels_2(s->block[3], ptr + 8 + s->linesize * 8, s->linesize ,dxy); - - if (s->out_format == FMT_H263) { - /* special rounding for h263 */ - dxy = 0; - if ((motion_x & 3) != 0) - dxy |= 1; - if ((motion_y & 3) != 0) - dxy |= 2; - mx = motion_x >> 2; - my = motion_y >> 2; - } else { - mx = motion_x / 2; - my = motion_y / 2; - dxy = ((my & 1) << 1) | (mx & 1); - mx >>= 1; - my >>= 1; - } - offset = ((mb_y * 8 + my) * (s->linesize >> 1)) + (mb_x * 8 + mx); - ptr = s->last_picture[1] + offset; - sub_pixels_2(s->block[4], ptr, s->linesize >> 1, dxy); - ptr = s->last_picture[2] + offset; - sub_pixels_2(s->block[5], ptr, s->linesize >> 1, dxy); + if(s->flags&CODEC_FLAG_GRAY){ + skip_dct[4]= 1; + skip_dct[5]= 1; }else{ - int src_x, src_y; - - for(i=0;i<4;i++) { - int motion_x = s->mv[0][i][0]; - int motion_y = s->mv[0][i][1]; - - dxy = ((motion_y & 1) << 1) | (motion_x & 1); - src_x = mb_x * 16 + (motion_x >> 1) + (i & 1) * 8; - src_y = mb_y * 16 + (motion_y >> 1) + (i >>1) * 8; - - ptr = s->last_picture[0] + (src_y * s->linesize) + (src_x); - sub_pixels_2(s->block[i], ptr, s->linesize, dxy); - } - /* In case of 8X8, we construct a single chroma motion vector - with a special rounding */ - mx = 0; - my = 0; - for(i=0;i<4;i++) { - mx += s->mv[0][i][0]; - my += s->mv[0][i][1]; - } - if (mx >= 0) - mx = (h263_chroma_roundtab[mx & 0xf] + ((mx >> 3) & ~1)); - else { - mx = -mx; - mx = -(h263_chroma_roundtab[mx & 0xf] + ((mx >> 3) & ~1)); - } - if (my >= 0) - my = (h263_chroma_roundtab[my & 0xf] + ((my >> 3) & ~1)); - else { - my = -my; - my = -(h263_chroma_roundtab[my & 0xf] + ((my >> 3) & ~1)); - } - dxy = ((my & 1) << 1) | (mx & 1); - mx >>= 1; - my >>= 1; - - src_x = mb_x * 8 + mx; - src_y = mb_y * 8 + my; - src_x = clip(src_x, -8, s->width/2); - if (src_x == s->width/2) - dxy &= ~1; - src_y = clip(src_y, -8, s->height/2); - if (src_y == s->height/2) - dxy &= ~2; - - offset = (src_y * (s->linesize >> 1)) + src_x; - ptr = s->last_picture[1] + offset; - sub_pixels_2(s->block[4], ptr, s->linesize >> 1, dxy); - ptr = s->last_picture[2] + offset; - sub_pixels_2(s->block[5], ptr, s->linesize >> 1, dxy); + diff_pixels(s->block[4], ptr_cb, dest_cb, wrap_c); + diff_pixels(s->block[5], ptr_cr, dest_cr, wrap_c); } + + /* pre quantization */ + if(s->mc_mb_var[s->mb_width*mb_y+ mb_x]<2*s->qscale*s->qscale){ + if(pix_abs8x8(ptr_y , dest_y , wrap_y) < 20*s->qscale) skip_dct[0]= 1; + if(pix_abs8x8(ptr_y + 8, dest_y + 8, wrap_y) < 20*s->qscale) skip_dct[1]= 1; + if(pix_abs8x8(ptr_y + 8*wrap_y , dest_y + 8*wrap_y , wrap_y) < 20*s->qscale) skip_dct[2]= 1; + if(pix_abs8x8(ptr_y + 8*wrap_y + 8, dest_y + 8*wrap_y + 8, wrap_y) < 20*s->qscale) skip_dct[3]= 1; + if(pix_abs8x8(ptr_cb , dest_cb , wrap_y) < 20*s->qscale) skip_dct[4]= 1; + if(pix_abs8x8(ptr_cr , dest_cr , wrap_y) < 20*s->qscale) skip_dct[5]= 1; +#if 0 +{ + static int stat[7]; + int num=0; + for(i=0; i<6; i++) + if(skip_dct[i]) num++; + stat[num]++; + + if(s->mb_x==0 && s->mb_y==0){ + for(i=0; i<7; i++){ + printf("%6d %1d\n", stat[i], i); + } + } +} +#endif + } + } #if 0 @@ -1240,17 +1521,47 @@ static void encode_mb(MpegEncContext *s) } #endif /* DCT & quantize */ - if (s->h263_msmpeg4) { - msmpeg4_dc_scale(s); - } else if (s->h263_pred) { + if (s->h263_pred && !(s->msmpeg4_version==1 || s->msmpeg4_version==2)) { h263_dc_scale(s); + } else if (s->h263_aic) { + s->y_dc_scale = 2*s->qscale; + s->c_dc_scale = 2*s->qscale; } else { /* default quantization values */ s->y_dc_scale = 8; s->c_dc_scale = 8; } - for(i=0;i<6;i++) { - s->block_last_index[i] = dct_quantize(s, s->block[i], i, s->qscale); + if(s->out_format==FMT_MJPEG){ + for(i=0;i<6;i++) { + int overflow; + s->block_last_index[i] = dct_quantize(s, s->block[i], i, 8, &overflow); + if (overflow) clip_coeffs(s, s->block[i], s->block_last_index[i]); + } + }else{ + for(i=0;i<6;i++) { + if(!skip_dct[i]){ + int overflow; + s->block_last_index[i] = dct_quantize(s, s->block[i], i, s->qscale, &overflow); + // FIXME we could decide to change to quantizer instead of clipping + // JS: I don't think that would be a good idea it could lower quality instead + // of improve it. Just INTRADC clipping deserves changes in quantizer + if (overflow) clip_coeffs(s, s->block[i], s->block_last_index[i]); + }else + s->block_last_index[i]= -1; + } + if(s->luma_elim_threshold && !s->mb_intra) + for(i=0; i<4; i++) + dct_single_coeff_elimination(s, i, s->luma_elim_threshold, 0); + if(s->chroma_elim_threshold && !s->mb_intra) + for(i=4; i<6; i++) + dct_single_coeff_elimination(s, i, s->chroma_elim_threshold, 1); + } + + if((s->flags&CODEC_FLAG_GRAY) && s->mb_intra){ + s->block_last_index[4]= + s->block_last_index[5]= 0; + s->block[4][0]= + s->block[5][0]= 128; } /* huffman encode */ @@ -1272,14 +1583,113 @@ static void encode_mb(MpegEncContext *s) } } -static void copy_bits(PutBitContext *pb, UINT8 *src, int length) +void ff_copy_bits(PutBitContext *pb, UINT8 *src, int length) { +#if 1 + int bytes= length>>4; + int bits= length&15; + int i; + + if(length==0) return; + + for(i=0; i<bytes; i++) put_bits(pb, 16, be2me_16(((uint16_t*)src)[i])); + put_bits(pb, bits, be2me_16(((uint16_t*)src)[i])>>(16-bits)); +#else int bytes= length>>3; int bits= length&7; int i; for(i=0; i<bytes; i++) put_bits(pb, 8, src[i]); put_bits(pb, bits, src[i]>>(8-bits)); +#endif +} + +static inline void copy_context_before_encode(MpegEncContext *d, MpegEncContext *s, int type){ + int i; + + memcpy(d->last_mv, s->last_mv, 2*2*2*sizeof(int)); //FIXME is memcpy faster then a loop? + + /* mpeg1 */ + d->mb_incr= s->mb_incr; + for(i=0; i<3; i++) + d->last_dc[i]= s->last_dc[i]; + + /* statistics */ + d->mv_bits= s->mv_bits; + d->i_tex_bits= s->i_tex_bits; + d->p_tex_bits= s->p_tex_bits; + d->i_count= s->i_count; + d->p_count= s->p_count; + d->skip_count= s->skip_count; + d->misc_bits= s->misc_bits; + d->last_bits= 0; + + d->mb_skiped= s->mb_skiped; +} + +static inline void copy_context_after_encode(MpegEncContext *d, MpegEncContext *s, int type){ + int i; + + memcpy(d->mv, s->mv, 2*4*2*sizeof(int)); + memcpy(d->last_mv, s->last_mv, 2*2*2*sizeof(int)); //FIXME is memcpy faster then a loop? + + /* mpeg1 */ + d->mb_incr= s->mb_incr; + for(i=0; i<3; i++) + d->last_dc[i]= s->last_dc[i]; + + /* statistics */ + d->mv_bits= s->mv_bits; + d->i_tex_bits= s->i_tex_bits; + d->p_tex_bits= s->p_tex_bits; + d->i_count= s->i_count; + d->p_count= s->p_count; + d->skip_count= s->skip_count; + d->misc_bits= s->misc_bits; + + d->mb_intra= s->mb_intra; + d->mb_skiped= s->mb_skiped; + d->mv_type= s->mv_type; + d->mv_dir= s->mv_dir; + d->pb= s->pb; + if(s->data_partitioning){ + d->pb2= s->pb2; + d->tex_pb= s->tex_pb; + } + d->block= s->block; + for(i=0; i<6; i++) + d->block_last_index[i]= s->block_last_index[i]; +} + +static inline void encode_mb_hq(MpegEncContext *s, MpegEncContext *backup, MpegEncContext *best, int type, + PutBitContext pb[2], PutBitContext pb2[2], PutBitContext tex_pb[2], + int *dmin, int *next_block, int motion_x, int motion_y) +{ + int bits_count; + + copy_context_before_encode(s, backup, type); + + s->block= s->blocks[*next_block]; + s->pb= pb[*next_block]; + if(s->data_partitioning){ + s->pb2 = pb2 [*next_block]; + s->tex_pb= tex_pb[*next_block]; + } + + encode_mb(s, motion_x, motion_y); + + bits_count= get_bit_count(&s->pb); + if(s->data_partitioning){ + bits_count+= get_bit_count(&s->pb2); + bits_count+= get_bit_count(&s->tex_pb); + } + + if(bits_count<*dmin){ + *dmin= bits_count; + *next_block^=1; + + copy_context_after_encode(best, s, type); + } } static void encode_picture(MpegEncContext *s, int picture_number) @@ -1287,8 +1697,17 @@ static void encode_picture(MpegEncContext *s, int picture_number) int mb_x, mb_y, last_gob, pdif = 0; int i; int bits; - MpegEncContext best_s; - UINT8 bit_buf[4][3000]; //FIXME check that this is ALLWAYS large enogh for a MB + MpegEncContext best_s, backup_s; + UINT8 bit_buf[2][3000]; + UINT8 bit_buf2[2][3000]; + UINT8 bit_buf_tex[2][3000]; + PutBitContext pb[2], pb2[2], tex_pb[2]; + + for(i=0; i<2; i++){ + init_put_bits(&pb [i], bit_buf [i], 3000, NULL, NULL); + init_put_bits(&pb2 [i], bit_buf2 [i], 3000, NULL, NULL); + init_put_bits(&tex_pb[i], bit_buf_tex[i], 3000, NULL, NULL); + } s->picture_number = picture_number; @@ -1299,12 +1718,16 @@ static void encode_picture(MpegEncContext *s, int picture_number) s->block_wrap[4]= s->block_wrap[5]= s->mb_width + 2; - s->last_mc_mb_var = s->mc_mb_var; /* Reset the average MB variance */ - s->avg_mb_var = 0; - s->mc_mb_var = 0; + s->mb_var_sum = 0; + s->mc_mb_var_sum = 0; + + /* we need to initialize some time vars before we can encode b-frames */ + if (s->h263_pred && !s->h263_msmpeg4) + ff_set_mpeg4_time(s, s->picture_number); + /* Estimate motion for every MB */ - if(s->pict_type == P_TYPE){ + if(s->pict_type != I_TYPE){ for(mb_y=0; mb_y < s->mb_height; mb_y++) { s->block_index[0]= s->block_wrap[0]*(mb_y*2 + 1) - 1; s->block_index[1]= s->block_wrap[0]*(mb_y*2 + 1); @@ -1319,127 +1742,61 @@ static void encode_picture(MpegEncContext *s, int picture_number) s->block_index[3]+=2; /* compute motion vector & mb_type and store in context */ - estimate_motion(s, mb_x, mb_y); + if(s->pict_type==B_TYPE) + ff_estimate_b_frame_motion(s, mb_x, mb_y); + else + ff_estimate_p_frame_motion(s, mb_x, mb_y); // s->mb_type[mb_y*s->mb_width + mb_x]=MB_TYPE_INTER; } } emms_c(); - }else{ + }else /* if(s->pict_type == I_TYPE) */{ /* I-Frame */ //FIXME do we need to zero them? memset(s->motion_val[0], 0, sizeof(INT16)*(s->mb_width*2 + 2)*(s->mb_height*2 + 2)*2); - memset(s->mv_table[0] , 0, sizeof(INT16)*s->mb_width*s->mb_height); - memset(s->mv_table[1] , 0, sizeof(INT16)*s->mb_width*s->mb_height); + memset(s->p_mv_table , 0, sizeof(INT16)*(s->mb_width+2)*(s->mb_height+2)*2); memset(s->mb_type , MB_TYPE_INTRA, sizeof(UINT8)*s->mb_width*s->mb_height); } - if(s->avg_mb_var < s->mc_mb_var && s->pict_type != B_TYPE && (!s->force_type)){ //FIXME subtract MV bits + if(s->mb_var_sum < s->mc_mb_var_sum && s->pict_type == P_TYPE){ //FIXME subtract MV bits s->pict_type= I_TYPE; - s->picture_in_gop_number=0; memset(s->mb_type , MB_TYPE_INTRA, sizeof(UINT8)*s->mb_width*s->mb_height); + if(s->max_b_frames==0){ + s->input_pict_type= I_TYPE; + s->input_picture_in_gop_number=0; + } //printf("Scene change detected, encoding as I Frame\n"); } - - /* find best f_code for ME which do unlimited searches */ - if(s->pict_type==P_TYPE && s->full_search>3){ - int mv_num[8]; - int i; - int loose=0; - UINT8 * fcode_tab= s->fcode_tab; - - for(i=0; i<8; i++) mv_num[i]=0; - - for(i=0; i<s->mb_num; i++){ - if(s->mb_type[i] & MB_TYPE_INTER){ - mv_num[ fcode_tab[s->mv_table[0][i] + MAX_MV] ]++; - mv_num[ fcode_tab[s->mv_table[1][i] + MAX_MV] ]++; -//printf("%d %d %d\n", s->mv_table[0][i], fcode_tab[s->mv_table[0][i] + MAX_MV], i); - } -//else printf("I"); - } - - for(i=MAX_FCODE; i>1; i--){ - loose+= mv_num[i]; - if(loose > 10) break; //FIXME this is pretty ineffective - } - s->f_code= i; -/* for(i=0; i<=MAX_FCODE; i++){ - printf("%d ", mv_num[i]); - } - printf("\n");*/ - }else{ - s->f_code= 1; + + if(s->pict_type==P_TYPE || s->pict_type==S_TYPE) + s->f_code= ff_get_best_fcode(s, s->p_mv_table, MB_TYPE_INTER); + ff_fix_long_p_mvs(s); + if(s->pict_type==B_TYPE){ + s->f_code= ff_get_best_fcode(s, s->b_forw_mv_table, MB_TYPE_FORWARD); + s->b_code= ff_get_best_fcode(s, s->b_back_mv_table, MB_TYPE_BACKWARD); + + ff_fix_long_b_mvs(s, s->b_forw_mv_table, s->f_code, MB_TYPE_FORWARD); + ff_fix_long_b_mvs(s, s->b_back_mv_table, s->b_code, MB_TYPE_BACKWARD); + ff_fix_long_b_mvs(s, s->b_bidir_forw_mv_table, s->f_code, MB_TYPE_BIDIR); + ff_fix_long_b_mvs(s, s->b_bidir_back_mv_table, s->b_code, MB_TYPE_BIDIR); } - + //printf("f_code %d ///\n", s->f_code); - /* convert MBs with too long MVs to I-Blocks */ - if(s->pict_type==P_TYPE){ - int i, x, y; - const int f_code= s->f_code; - UINT8 * fcode_tab= s->fcode_tab; -//FIXME try to clip instead of intra izing ;) - /* clip / convert to intra 16x16 type MVs */ - for(i=0; i<s->mb_num; i++){ - if(s->mb_type[i]&MB_TYPE_INTER){ - if( fcode_tab[s->mv_table[0][i] + MAX_MV] > f_code - || fcode_tab[s->mv_table[0][i] + MAX_MV] == 0 - || fcode_tab[s->mv_table[1][i] + MAX_MV] > f_code - || fcode_tab[s->mv_table[1][i] + MAX_MV] == 0 ){ - s->mb_type[i] &= ~MB_TYPE_INTER; - s->mb_type[i] |= MB_TYPE_INTRA; - s->mv_table[0][i] = 0; - s->mv_table[1][i] = 0; - } - } - } - - if(s->flags&CODEC_FLAG_4MV){ - int wrap= 2+ s->mb_width*2; - - /* clip / convert to intra 8x8 type MVs */ - for(y=0; y<s->mb_height; y++){ - int xy= (y*2 + 1)*wrap + 1; - i= y*s->mb_width; - - for(x=0; x<s->mb_width; x++){ - if(s->mb_type[i]&MB_TYPE_INTER4V){ - int block; - for(block=0; block<4; block++){ - int off= (block& 1) + (block>>1)*wrap; - int mx= s->motion_val[ xy + off ][0]; - int my= s->motion_val[ xy + off ][1]; - - if( fcode_tab[mx + MAX_MV] > f_code - || fcode_tab[mx + MAX_MV] == 0 - || fcode_tab[my + MAX_MV] > f_code - || fcode_tab[my + MAX_MV] == 0 ){ - s->mb_type[i] &= ~MB_TYPE_INTER4V; - s->mb_type[i] |= MB_TYPE_INTRA; - } - } - xy+=2; - i++; - } - } - } - } - } // printf("%d %d\n", s->avg_mb_var, s->mc_mb_var); - if (!s->fixed_qscale) - s->qscale = rate_estimate_qscale(s); + if(s->flags&CODEC_FLAG_PASS2) + s->qscale = ff_rate_estimate_qscale_pass2(s); + else if (!s->fixed_qscale) + s->qscale = ff_rate_estimate_qscale(s); - /* precompute matrix */ if (s->out_format == FMT_MJPEG) { /* for mjpeg, we do include qscale in the matrix */ s->intra_matrix[0] = default_intra_matrix[0]; for(i=1;i<64;i++) - s->intra_matrix[i] = (default_intra_matrix[i] * s->qscale) >> 3; - convert_matrix(s->q_intra_matrix, s->q_intra_matrix16, s->intra_matrix, 8); - } else { - convert_matrix(s->q_intra_matrix, s->q_intra_matrix16, s->intra_matrix, s->qscale); - convert_matrix(s->q_non_intra_matrix, s->q_non_intra_matrix16, s->non_intra_matrix, s->qscale); + s->intra_matrix[i] = CLAMP_TO_8BIT((default_intra_matrix[i] * s->qscale) >> 3); + convert_matrix(s->q_intra_matrix, s->q_intra_matrix16, + s->q_intra_matrix16_bias, s->intra_matrix, s->intra_quant_bias); } s->last_bits= get_bit_count(&s->pb); @@ -1489,21 +1846,31 @@ static void encode_picture(MpegEncContext *s, int picture_number) s->gob_index = 2; else s->gob_index = 4; + }else if(s->codec_id==CODEC_ID_MPEG4){ + s->gob_index = 1; } - - s->avg_mb_var = s->avg_mb_var / s->mb_num; - + + if(s->codec_id==CODEC_ID_MPEG4 && s->data_partitioning && s->pict_type!=B_TYPE) + ff_mpeg4_init_partitions(s); + + s->resync_mb_x=0; + s->resync_mb_y=0; for(mb_y=0; mb_y < s->mb_height; mb_y++) { - /* Put GOB header based on RTP MTU */ + /* Put GOB header based on RTP MTU for formats which support it per line (H263*)*/ /* TODO: Put all this stuff in a separate generic function */ if (s->rtp_mode) { if (!mb_y) { s->ptr_lastgob = s->pb.buf; s->ptr_last_mb_line = s->pb.buf; } else if (s->out_format == FMT_H263 && !s->h263_pred && !s->h263_msmpeg4 && !(mb_y % s->gob_index)) { + // MN: we could move the space check from h263 -> here, as its not h263 specific last_gob = h263_encode_gob_header(s, mb_y); if (last_gob) { - s->first_gob_line = 1; + s->first_slice_line = 1; + }else{ + /*MN: we reset it here instead at the end of each line cuz mpeg4 can have + slice lines starting & ending in the middle*/ + s->first_slice_line = 0; } } } @@ -1516,10 +1883,9 @@ static void encode_picture(MpegEncContext *s, int picture_number) s->block_index[5]= s->block_wrap[4]*(mb_y + 1 + s->mb_height + 2) + s->block_wrap[0]*(s->mb_height*2 + 2); for(mb_x=0; mb_x < s->mb_width; mb_x++) { const int mb_type= s->mb_type[mb_y * s->mb_width + mb_x]; - PutBitContext pb; - int d; + const int xy= (mb_y+1) * (s->mb_width+2) + mb_x + 1; +// int d; int dmin=10000000; - int best=0; s->mb_x = mb_x; s->mb_y = mb_y; @@ -1529,114 +1895,216 @@ static void encode_picture(MpegEncContext *s, int picture_number) s->block_index[3]+=2; s->block_index[4]++; s->block_index[5]++; + + /* write gob / video packet header for formats which support it at any MB (MPEG4) */ + if(s->rtp_mode && s->mb_y>0 && s->codec_id==CODEC_ID_MPEG4){ + int pdif= pbBufPtr(&s->pb) - s->ptr_lastgob; + + //the *2 is there so we stay below the requested size + if(pdif + s->mb_line_avgsize/s->mb_width >= s->rtp_payload_size){ + if(s->codec_id==CODEC_ID_MPEG4){ + if(s->data_partitioning && s->pict_type!=B_TYPE){ + ff_mpeg4_merge_partitions(s); + ff_mpeg4_init_partitions(s); + } + ff_mpeg4_encode_video_packet_header(s); + + if(s->flags&CODEC_FLAG_PASS1){ + int bits= get_bit_count(&s->pb); + s->misc_bits+= bits - s->last_bits; + s->last_bits= bits; + } + ff_mpeg4_clean_buffers(s); + } + s->ptr_lastgob = pbBufPtr(&s->pb); + s->first_slice_line=1; + s->resync_mb_x=mb_x; + s->resync_mb_y=mb_y; + } + + if( (s->resync_mb_x == s->mb_x) + && s->resync_mb_y+1 == s->mb_y){ + s->first_slice_line=0; + } + } - s->mv_dir = MV_DIR_FORWARD; if(mb_type & (mb_type-1)){ // more than 1 MB type possible - pb= s->pb; + int next_block=0; + int pb_bits_count, pb2_bits_count, tex_pb_bits_count; + + copy_context_before_encode(&backup_s, s, -1); + backup_s.pb= s->pb; + best_s.data_partitioning= s->data_partitioning; + if(s->data_partitioning){ + backup_s.pb2= s->pb2; + backup_s.tex_pb= s->tex_pb; + } + if(mb_type&MB_TYPE_INTER){ + s->mv_dir = MV_DIR_FORWARD; s->mv_type = MV_TYPE_16X16; s->mb_intra= 0; - s->mv[0][0][0] = s->mv_table[0][mb_y * s->mb_width + mb_x]; - s->mv[0][0][1] = s->mv_table[1][mb_y * s->mb_width + mb_x]; - init_put_bits(&s->pb, bit_buf[1], 3000, NULL, NULL); - s->block= s->inter_block; - - encode_mb(s); - d= get_bit_count(&s->pb); - if(d<dmin){ - flush_put_bits(&s->pb); - dmin=d; - best_s.mv[0][0][0]= s->mv[0][0][0]; - best_s.mv[0][0][1]= s->mv[0][0][1]; - best_s.mb_intra= 0; - best_s.mv_type = MV_TYPE_16X16; - best_s.pb=s->pb; - best_s.block= s->block; - best=1; - for(i=0; i<6; i++) - best_s.block_last_index[i]= s->block_last_index[i]; - } + s->mv[0][0][0] = s->p_mv_table[xy][0]; + s->mv[0][0][1] = s->p_mv_table[xy][1]; + encode_mb_hq(s, &backup_s, &best_s, MB_TYPE_INTER, pb, pb2, tex_pb, + &dmin, &next_block, s->mv[0][0][0], s->mv[0][0][1]); } - if(mb_type&MB_TYPE_INTER4V){ + if(mb_type&MB_TYPE_INTER4V){ + s->mv_dir = MV_DIR_FORWARD; s->mv_type = MV_TYPE_8X8; s->mb_intra= 0; for(i=0; i<4; i++){ s->mv[0][i][0] = s->motion_val[s->block_index[i]][0]; s->mv[0][i][1] = s->motion_val[s->block_index[i]][1]; } - init_put_bits(&s->pb, bit_buf[2], 3000, NULL, NULL); - s->block= s->inter4v_block; - - encode_mb(s); - d= get_bit_count(&s->pb); - if(d<dmin){ - flush_put_bits(&s->pb); - dmin=d; - for(i=0; i<4; i++){ - best_s.mv[0][i][0] = s->mv[0][i][0]; - best_s.mv[0][i][1] = s->mv[0][i][1]; - } - best_s.mb_intra= 0; - best_s.mv_type = MV_TYPE_8X8; - best_s.pb=s->pb; - best_s.block= s->block; - best=2; - for(i=0; i<6; i++) - best_s.block_last_index[i]= s->block_last_index[i]; - } + encode_mb_hq(s, &backup_s, &best_s, MB_TYPE_INTER4V, pb, pb2, tex_pb, + &dmin, &next_block, 0, 0); + } + if(mb_type&MB_TYPE_FORWARD){ + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_16X16; + s->mb_intra= 0; + s->mv[0][0][0] = s->b_forw_mv_table[xy][0]; + s->mv[0][0][1] = s->b_forw_mv_table[xy][1]; + encode_mb_hq(s, &backup_s, &best_s, MB_TYPE_FORWARD, pb, pb2, tex_pb, + &dmin, &next_block, s->mv[0][0][0], s->mv[0][0][1]); + } + if(mb_type&MB_TYPE_BACKWARD){ + s->mv_dir = MV_DIR_BACKWARD; + s->mv_type = MV_TYPE_16X16; + s->mb_intra= 0; + s->mv[1][0][0] = s->b_back_mv_table[xy][0]; + s->mv[1][0][1] = s->b_back_mv_table[xy][1]; + encode_mb_hq(s, &backup_s, &best_s, MB_TYPE_BACKWARD, pb, pb2, tex_pb, + &dmin, &next_block, s->mv[1][0][0], s->mv[1][0][1]); + } + if(mb_type&MB_TYPE_BIDIR){ + s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD; + s->mv_type = MV_TYPE_16X16; + s->mb_intra= 0; + s->mv[0][0][0] = s->b_bidir_forw_mv_table[xy][0]; + s->mv[0][0][1] = s->b_bidir_forw_mv_table[xy][1]; + s->mv[1][0][0] = s->b_bidir_back_mv_table[xy][0]; + s->mv[1][0][1] = s->b_bidir_back_mv_table[xy][1]; + encode_mb_hq(s, &backup_s, &best_s, MB_TYPE_BIDIR, pb, pb2, tex_pb, + &dmin, &next_block, 0, 0); + } + if(mb_type&MB_TYPE_DIRECT){ + s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD | MV_DIRECT; + s->mv_type = MV_TYPE_16X16; //FIXME + s->mb_intra= 0; + s->mv[0][0][0] = s->b_direct_forw_mv_table[xy][0]; + s->mv[0][0][1] = s->b_direct_forw_mv_table[xy][1]; + s->mv[1][0][0] = s->b_direct_back_mv_table[xy][0]; + s->mv[1][0][1] = s->b_direct_back_mv_table[xy][1]; + encode_mb_hq(s, &backup_s, &best_s, MB_TYPE_DIRECT, pb, pb2, tex_pb, + &dmin, &next_block, s->b_direct_mv_table[xy][0], s->b_direct_mv_table[xy][1]); } if(mb_type&MB_TYPE_INTRA){ + s->mv_dir = MV_DIR_FORWARD; s->mv_type = MV_TYPE_16X16; s->mb_intra= 1; s->mv[0][0][0] = 0; s->mv[0][0][1] = 0; - init_put_bits(&s->pb, bit_buf[0], 3000, NULL, NULL); - s->block= s->intra_block; - - encode_mb(s); - d= get_bit_count(&s->pb); - if(d<dmin){ - flush_put_bits(&s->pb); - dmin=d; - best_s.mv[0][0][0]= 0; - best_s.mv[0][0][1]= 0; - best_s.mb_intra= 1; - best_s.mv_type = MV_TYPE_16X16; - best_s.pb=s->pb; - best_s.block= s->block; - for(i=0; i<6; i++) - best_s.block_last_index[i]= s->block_last_index[i]; - best=0; - } - /* force cleaning of ac/dc if needed ... */ - s->mbintra_table[mb_x + mb_y*s->mb_width]=1; + encode_mb_hq(s, &backup_s, &best_s, MB_TYPE_INTRA, pb, pb2, tex_pb, + &dmin, &next_block, 0, 0); + /* force cleaning of ac/dc pred stuff if needed ... */ + if(s->h263_pred || s->h263_aic) + s->mbintra_table[mb_x + mb_y*s->mb_width]=1; } - for(i=0; i<4; i++){ - s->mv[0][i][0] = best_s.mv[0][i][0]; - s->mv[0][i][1] = best_s.mv[0][i][1]; + copy_context_after_encode(s, &best_s, -1); + + pb_bits_count= get_bit_count(&s->pb); + flush_put_bits(&s->pb); + ff_copy_bits(&backup_s.pb, bit_buf[next_block^1], pb_bits_count); + s->pb= backup_s.pb; + + if(s->data_partitioning){ + pb2_bits_count= get_bit_count(&s->pb2); + flush_put_bits(&s->pb2); + ff_copy_bits(&backup_s.pb2, bit_buf2[next_block^1], pb2_bits_count); + s->pb2= backup_s.pb2; + + tex_pb_bits_count= get_bit_count(&s->tex_pb); + flush_put_bits(&s->tex_pb); + ff_copy_bits(&backup_s.tex_pb, bit_buf_tex[next_block^1], tex_pb_bits_count); + s->tex_pb= backup_s.tex_pb; } - s->mb_intra= best_s.mb_intra; - s->mv_type= best_s.mv_type; - for(i=0; i<6; i++) - s->block_last_index[i]= best_s.block_last_index[i]; - copy_bits(&pb, bit_buf[best], dmin); - s->block= best_s.block; - s->pb= pb; + s->last_bits= get_bit_count(&s->pb); } else { + int motion_x, motion_y; + s->mv_type=MV_TYPE_16X16; // only one MB-Type possible - if(mb_type&MB_TYPE_INTRA){ + switch(mb_type){ + case MB_TYPE_INTRA: + s->mv_dir = MV_DIR_FORWARD; s->mb_intra= 1; - s->mv[0][0][0] = 0; - s->mv[0][0][1] = 0; - }else{ + motion_x= s->mv[0][0][0] = 0; + motion_y= s->mv[0][0][1] = 0; + break; + case MB_TYPE_INTER: + s->mv_dir = MV_DIR_FORWARD; + s->mb_intra= 0; + motion_x= s->mv[0][0][0] = s->p_mv_table[xy][0]; + motion_y= s->mv[0][0][1] = s->p_mv_table[xy][1]; + break; + case MB_TYPE_INTER4V: + s->mv_dir = MV_DIR_FORWARD; + s->mv_type = MV_TYPE_8X8; s->mb_intra= 0; - s->mv[0][0][0] = s->mv_table[0][mb_y * s->mb_width + mb_x]; - s->mv[0][0][1] = s->mv_table[1][mb_y * s->mb_width + mb_x]; + for(i=0; i<4; i++){ + s->mv[0][i][0] = s->motion_val[s->block_index[i]][0]; + s->mv[0][i][1] = s->motion_val[s->block_index[i]][1]; + } + motion_x= motion_y= 0; + break; + case MB_TYPE_DIRECT: + s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD | MV_DIRECT; + s->mb_intra= 0; + motion_x=s->b_direct_mv_table[xy][0]; + motion_y=s->b_direct_mv_table[xy][1]; + s->mv[0][0][0] = s->b_direct_forw_mv_table[xy][0]; + s->mv[0][0][1] = s->b_direct_forw_mv_table[xy][1]; + s->mv[1][0][0] = s->b_direct_back_mv_table[xy][0]; + s->mv[1][0][1] = s->b_direct_back_mv_table[xy][1]; + break; + case MB_TYPE_BIDIR: + s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD; + s->mb_intra= 0; + motion_x=0; + motion_y=0; + s->mv[0][0][0] = s->b_bidir_forw_mv_table[xy][0]; + s->mv[0][0][1] = s->b_bidir_forw_mv_table[xy][1]; + s->mv[1][0][0] = s->b_bidir_back_mv_table[xy][0]; + s->mv[1][0][1] = s->b_bidir_back_mv_table[xy][1]; + break; + case MB_TYPE_BACKWARD: + s->mv_dir = MV_DIR_BACKWARD; + s->mb_intra= 0; + motion_x= s->mv[1][0][0] = s->b_back_mv_table[xy][0]; + motion_y= s->mv[1][0][1] = s->b_back_mv_table[xy][1]; + break; + case MB_TYPE_FORWARD: + s->mv_dir = MV_DIR_FORWARD; + s->mb_intra= 0; + motion_x= s->mv[0][0][0] = s->b_forw_mv_table[xy][0]; + motion_y= s->mv[0][0][1] = s->b_forw_mv_table[xy][1]; +// printf(" %d %d ", motion_x, motion_y); + break; + default: + motion_x=motion_y=0; //gcc warning fix + printf("illegal MB type\n"); } - encode_mb(s); + encode_mb(s, motion_x, motion_y); + } + /* clean the MV table in IPS frames for direct mode in B frames */ + if(s->mb_intra /* && I,P,S_TYPE */){ + s->p_mv_table[xy][0]=0; + s->p_mv_table[xy][1]=0; } MPV_decode_mb(s, s->block); +//printf("MB %d %d bits\n", s->mb_x+s->mb_y*s->mb_width, get_bit_count(&s->pb)); } @@ -1650,14 +2118,20 @@ static void encode_picture(MpegEncContext *s, int picture_number) } //fprintf(stderr, "\nMB line: %d\tSize: %u\tAvg. Size: %u", s->mb_y, // (s->pb.buf_ptr - s->ptr_last_mb_line), s->mb_line_avgsize); - s->first_gob_line = 0; + if(s->codec_id!=CODEC_ID_MPEG4) s->first_slice_line = 0; //FIXME clean } } emms_c(); - if (s->h263_msmpeg4 && s->pict_type == I_TYPE) + if(s->codec_id==CODEC_ID_MPEG4 && s->data_partitioning && s->pict_type!=B_TYPE) + ff_mpeg4_merge_partitions(s); + + if (s->msmpeg4_version && s->msmpeg4_version<4 && s->pict_type == I_TYPE) msmpeg4_encode_ext_header(s); + if(s->codec_id==CODEC_ID_MPEG4) + ff_mpeg4_stuffing(&s->pb); + //if (s->gob_number) // fprintf(stderr,"\nNumber of GOB: %d", s->gob_number); @@ -1675,30 +2149,14 @@ static void encode_picture(MpegEncContext *s, int picture_number) static int dct_quantize_c(MpegEncContext *s, DCTELEM *block, int n, - int qscale) + int qscale, int *overflow) { int i, j, level, last_non_zero, q; const int *qmat; - int minLevel, maxLevel; - - if(s->avctx!=NULL && s->avctx->codec->id==CODEC_ID_MPEG4){ - /* mpeg4 */ - minLevel= -2048; - maxLevel= 2047; - }else if(s->out_format==FMT_MPEG1){ - /* mpeg1 */ - minLevel= -255; - maxLevel= 255; - }else if(s->out_format==FMT_MJPEG){ - /* (m)jpeg */ - minLevel= -1023; - maxLevel= 1023; - }else{ - /* h263 / msmpeg4 */ - minLevel= -128; - maxLevel= 127; - } - + int bias; + int max=0; + unsigned int threshold1, threshold2; + av_fdct (block); /* we need this permutation so that we correct the IDCT @@ -1706,81 +2164,54 @@ static int dct_quantize_c(MpegEncContext *s, block_permute(block); if (s->mb_intra) { - if (n < 4) - q = s->y_dc_scale; - else - q = s->c_dc_scale; - q = q << 3; - + if (!s->h263_aic) { + if (n < 4) + q = s->y_dc_scale; + else + q = s->c_dc_scale; + q = q << 3; + } else + /* For AIC we skip quant/dequant of INTRADC */ + q = 1 << 3; + /* note: block[0] is assumed to be positive */ block[0] = (block[0] + (q >> 1)) / q; i = 1; last_non_zero = 0; - if (s->out_format == FMT_H263) { - qmat = s->q_non_intra_matrix; - } else { - qmat = s->q_intra_matrix; - } + qmat = s->q_intra_matrix[qscale]; + bias= s->intra_quant_bias<<(QMAT_SHIFT - 3 - QUANT_BIAS_SHIFT); } else { i = 0; last_non_zero = -1; - qmat = s->q_non_intra_matrix; + qmat = s->q_inter_matrix[qscale]; + bias= s->inter_quant_bias<<(QMAT_SHIFT - 3 - QUANT_BIAS_SHIFT); } + threshold1= (1<<(QMAT_SHIFT - 3)) - bias - 1; + threshold2= threshold1<<1; for(;i<64;i++) { j = zigzag_direct[i]; level = block[j]; level = level * qmat[j]; -#ifdef PARANOID - { - static int count = 0; - int level1, level2, qmat1; - double val; - if (qmat == s->q_non_intra_matrix) { - qmat1 = default_non_intra_matrix[j] * s->qscale; - } else { - qmat1 = default_intra_matrix[j] * s->qscale; - } - if (av_fdct != jpeg_fdct_ifast) - val = ((double)block[j] * 8.0) / (double)qmat1; - else - val = ((double)block[j] * 8.0 * 2048.0) / - ((double)qmat1 * aanscales[j]); - level1 = (int)val; - level2 = level / (1 << (QMAT_SHIFT - 3)); - if (level1 != level2) { - fprintf(stderr, "%d: quant error qlevel=%d wanted=%d level=%d qmat1=%d qmat=%d wantedf=%0.6f\n", - count, level2, level1, block[j], qmat1, qmat[j], - val); - count++; - } - } -#endif - /* XXX: slight error for the low range. Test should be equivalent to - (level <= -(1 << (QMAT_SHIFT - 3)) || level >= (1 << - (QMAT_SHIFT - 3))) - */ - if (((level << (31 - (QMAT_SHIFT - 3))) >> (31 - (QMAT_SHIFT - 3))) != - level) { - level = level / (1 << (QMAT_SHIFT - 3)); - /* XXX: currently, this code is not optimal. the range should be: - mpeg1: -255..255 - mpeg2: -2048..2047 - h263: -128..127 - mpeg4: -2048..2047 - */ - if (level > maxLevel) - level = maxLevel; - else if (level < minLevel) - level = minLevel; - - block[j] = level; +// if( bias+level >= (1<<(QMAT_SHIFT - 3)) +// || bias-level >= (1<<(QMAT_SHIFT - 3))){ + if(((unsigned)(level+threshold1))>threshold2){ + if(level>0){ + level= (bias + level)>>(QMAT_SHIFT - 3); + block[j]= level; + }else{ + level= (bias - level)>>(QMAT_SHIFT - 3); + block[j]= -level; + } + max |=level; last_non_zero = i; - } else { - block[j] = 0; + }else{ + block[j]=0; } } + *overflow= s->max_qcoeff < max; //overflow might have happend + return last_non_zero; } @@ -1822,7 +2253,7 @@ static void dct_unquantize_mpeg1_c(MpegEncContext *s, } } else { i = 0; - quant_matrix = s->non_intra_matrix; + quant_matrix = s->inter_matrix; for(;i<nCoeffs;i++) { int j= zigzag_direct[i]; level = block[j]; @@ -1848,6 +2279,69 @@ static void dct_unquantize_mpeg1_c(MpegEncContext *s, } } +static void dct_unquantize_mpeg2_c(MpegEncContext *s, + DCTELEM *block, int n, int qscale) +{ + int i, level, nCoeffs; + const UINT16 *quant_matrix; + + if(s->alternate_scan) nCoeffs= 64; + else nCoeffs= s->block_last_index[n]+1; + + if (s->mb_intra) { + if (n < 4) + block[0] = block[0] * s->y_dc_scale; + else + block[0] = block[0] * s->c_dc_scale; + quant_matrix = s->intra_matrix; + for(i=1;i<nCoeffs;i++) { + int j= zigzag_direct[i]; + level = block[j]; + if (level) { + if (level < 0) { + level = -level; + level = (int)(level * qscale * quant_matrix[j]) >> 3; + level = -level; + } else { + level = (int)(level * qscale * quant_matrix[j]) >> 3; + } +#ifdef PARANOID + if (level < -2048 || level > 2047) + fprintf(stderr, "unquant error %d %d\n", i, level); +#endif + block[j] = level; + } + } + } else { + int sum=-1; + i = 0; + quant_matrix = s->inter_matrix; + for(;i<nCoeffs;i++) { + int j= zigzag_direct[i]; + level = block[j]; + if (level) { + if (level < 0) { + level = -level; + level = (((level << 1) + 1) * qscale * + ((int) (quant_matrix[j]))) >> 4; + level = -level; + } else { + level = (((level << 1) + 1) * qscale * + ((int) (quant_matrix[j]))) >> 4; + } +#ifdef PARANOID + if (level < -2048 || level > 2047) + fprintf(stderr, "unquant error %d %d\n", i, level); +#endif + block[j] = level; + sum+=level; + } + } + block[63]^=sum&1; + } +} + + static void dct_unquantize_h263_c(MpegEncContext *s, DCTELEM *block, int n, int qscale) { @@ -1891,188 +2385,117 @@ static void dct_unquantize_h263_c(MpegEncContext *s, } } -/* rate control */ - -/* an I frame is I_FRAME_SIZE_RATIO bigger than a P frame */ -#define I_FRAME_SIZE_RATIO 3.0 -#define QSCALE_K 20 - -static void rate_control_init(MpegEncContext *s) +static void remove_ac(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, int mb_x, int mb_y) { -#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; - - if (s->intra_only) { - s->I_frame_bits = ((INT64)s->bit_rate * FRAME_RATE_BASE) / s->frame_rate; - s->P_frame_bits = s->I_frame_bits; - } else { - s->P_frame_bits = (int) ((float)(s->gop_size * s->bit_rate) / - (float)((float)s->frame_rate / FRAME_RATE_BASE * (I_FRAME_SIZE_RATIO + s->gop_size - 1))); - s->I_frame_bits = (int)(s->P_frame_bits * I_FRAME_SIZE_RATIO); + int dc, dcb, dcr, y, i; + for(i=0; i<4; i++){ + dc= s->dc_val[0][mb_x*2+1 + (i&1) + (mb_y*2+1 + (i>>1))*(s->mb_width*2+2)]; + for(y=0; y<8; y++){ + int x; + for(x=0; x<8; x++){ + dest_y[x + (i&1)*8 + (y + (i>>1)*8)*s->linesize]= dc/8; + } + } + } + dcb = s->dc_val[1][mb_x+1 + (mb_y+1)*(s->mb_width+2)]; + dcr= s->dc_val[2][mb_x+1 + (mb_y+1)*(s->mb_width+2)]; + for(y=0; y<8; y++){ + int x; + for(x=0; x<8; x++){ + dest_cb[x + y*(s->linesize>>1)]= dcb/8; + dest_cr[x + y*(s->linesize>>1)]= dcr/8; + } } - -#if defined(DEBUG) - printf("I_frame_size=%d P_frame_size=%d\n", - s->I_frame_bits, s->P_frame_bits); -#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; } -static int rate_estimate_qscale(MpegEncContext *s) +/** + * will conceal past errors, and allso drop b frames if needed + * + */ +void ff_conceal_past_errors(MpegEncContext *s, int unknown_pos) { -#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; - + int mb_x= s->mb_x; + int mb_y= s->mb_y; + int mb_dist=0; + int i, intra_count=0, inter_count=0; + int intra_conceal= s->msmpeg4_version ? 50 : 50; //FIXME finetune + int inter_conceal= s->msmpeg4_version ? 50 : 50; - 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); - } - } + // for last block + if(mb_x>=s->mb_width) mb_x= s->mb_width -1; + if(mb_y>=s->mb_height) mb_y= s->mb_height-1; - 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; - } - } + if(s->decoding_error==0 && unknown_pos){ + if(s->data_partitioning && s->pict_type!=B_TYPE) + s->decoding_error= DECODING_AC_LOST; + else + s->decoding_error= DECODING_DESYNC; } - s->short_term_qsum*=s->qblur; - s->short_term_qcount*=s->qblur; + if(s->decoding_error==DECODING_DESYNC && s->pict_type!=B_TYPE) s->next_p_frame_damaged=1; - s->short_term_qsum+= rate_q; - s->short_term_qcount++; - short_term_q= s->short_term_qsum/s->short_term_qcount; + for(i=mb_x + mb_y*s->mb_width; i>=0; i--){ + if(s->mbintra_table[i]) intra_count++; + else inter_count++; + } - long_term_q= s->qsum/s->qcount*(s->total_bits+1)/(wanted_bits+1); //+1 to avoid nan & 0 - -// 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); + if(s->decoding_error==DECODING_AC_LOST){ + intra_conceal*=2; + inter_conceal*=2; + }else if(s->decoding_error==DECODING_ACDC_LOST){ + intra_conceal*=2; + inter_conceal*=2; + } - diff= s->total_bits - wanted_bits; - br_compensation= (s->bit_rate_tolerance - diff)/s->bit_rate_tolerance; - if(br_compensation<=0.0) br_compensation=0.001; - q/=br_compensation; + if(unknown_pos && (intra_count<inter_count)){ + intra_conceal= inter_conceal= s->mb_num; +// printf("%d %d\n",intra_count, inter_count); + } - 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; + fprintf(stderr, "concealing errors\n"); + + /* for all MBs from the current one back until the last resync marker */ + for(; mb_y>=0 && mb_y>=s->resync_mb_y; mb_y--){ + for(; mb_x>=0; mb_x--){ + uint8_t *dest_y = s->current_picture[0] + (mb_y * 16* s->linesize ) + mb_x * 16; + uint8_t *dest_cb = s->current_picture[1] + (mb_y * 8 * (s->linesize >> 1)) + mb_x * 8; + uint8_t *dest_cr = s->current_picture[2] + (mb_y * 8 * (s->linesize >> 1)) + mb_x * 8; + int mb_x_backup= s->mb_x; //FIXME pass xy to mpeg_motion + int mb_y_backup= s->mb_y; + s->mb_x=mb_x; + s->mb_y=mb_y; + if(s->mbintra_table[mb_y*s->mb_width + mb_x] && mb_dist<intra_conceal){ + if(s->decoding_error==DECODING_AC_LOST){ + remove_ac(s, dest_y, dest_cb, dest_cr, mb_x, mb_y); +// printf("remove ac to %d %d\n", mb_x, mb_y); + }else{ + mpeg_motion(s, dest_y, dest_cb, dest_cr, 0, + s->last_picture, 0, 0, put_pixels_tab, + 0/*mx*/, 0/*my*/, 16); + } + } + else if(!s->mbintra_table[mb_y*s->mb_width + mb_x] && mb_dist<inter_conceal){ + int mx=0; + int my=0; + + if(s->decoding_error!=DECODING_DESYNC){ + int xy= mb_x*2+1 + (mb_y*2+1)*(s->mb_width*2+2); + mx= s->motion_val[ xy ][0]; + my= s->motion_val[ xy ][1]; + } - s->qsum+= qscale; - s->qcount++; + mpeg_motion(s, dest_y, dest_cb, dest_cr, 0, + s->last_picture, 0, 0, put_pixels_tab, + mx, my, 16); + } + s->mb_x= mb_x_backup; + s->mb_y= mb_y_backup; - s->last_pict_type= s->pict_type; -//printf("q:%d diff:%d comp:%f rate_q:%d st_q:%f fvar:%d last_size:%d\n", qscale, (int)diff, br_compensation, -// rate_q, 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; - float q; - int qscale; - if (s->pict_type == I_TYPE) { - s->wanted_bits += s->I_frame_bits; - } else { - s->wanted_bits += s->P_frame_bits; - } - diff = s->wanted_bits - total_bits; - q = 31.0 - (float)diff / (QSCALE_K * s->mb_height * s->mb_width); - /* adjust for I frame */ - if (s->pict_type == I_TYPE && !s->intra_only) { - q /= I_FRAME_SIZE_RATIO; - } - - /* using a too small Q scale leeds to problems in mpeg1 and h263 - because AC coefficients are clamped to 255 or 127 */ - qmin = 3; - if (q < qmin) - q = qmin; - else if (q > 31) - q = 31; - qscale = (int)(q + 0.5); -#if defined(DEBUG) - printf("\n%d: total=%0.0f wanted=%0.0f br=%0.1f diff=%d qest=%2.1f\n", - s->picture_number, - (double)total_bits, - (double)s->wanted_bits, - (float)s->frame_rate / FRAME_RATE_BASE * - total_bits / s->picture_number, - (int)diff, q); -#endif - return qscale; -#endif + if(mb_x== s->resync_mb_x && mb_y== s->resync_mb_y) return; + if(!s->mbskip_table[mb_x + mb_y*s->mb_width]) mb_dist++; + } + mb_x=s->mb_width-1; + } } AVCodec mpeg1video_encoder = { |