diff options
author | Mike Melanson <mike@multimedia.cx> | 2004-03-14 21:14:07 +0000 |
---|---|---|
committer | Mike Melanson <mike@multimedia.cx> | 2004-03-14 21:14:07 +0000 |
commit | 0d90aec0fd7428a77b5c4c536ab65635669bc42d (patch) | |
tree | 9eb56c6c1176bf6a6f3ae65199a3f43aa8c2aa2d /src/libffmpeg/libavcodec/mpegvideo.c | |
parent | b4d3aa3dcce07b90098e33c37b563e797378d0f1 (diff) | |
download | xine-lib-0d90aec0fd7428a77b5c4c536ab65635669bc42d.tar.gz xine-lib-0d90aec0fd7428a77b5c4c536ab65635669bc42d.tar.bz2 |
sync to ffmpeg build 4707
CVS patchset: 6253
CVS date: 2004/03/14 21:14:07
Diffstat (limited to 'src/libffmpeg/libavcodec/mpegvideo.c')
-rw-r--r-- | src/libffmpeg/libavcodec/mpegvideo.c | 2037 |
1 files changed, 1323 insertions, 714 deletions
diff --git a/src/libffmpeg/libavcodec/mpegvideo.c b/src/libffmpeg/libavcodec/mpegvideo.c index 883c21260..32a92917c 100644 --- a/src/libffmpeg/libavcodec/mpegvideo.c +++ b/src/libffmpeg/libavcodec/mpegvideo.c @@ -26,6 +26,7 @@ */ #include <limits.h> +#include <math.h> //for PI #include "avcodec.h" #include "dsputil.h" #include "mpegvideo.h" @@ -38,7 +39,15 @@ //#undef NDEBUG //#include <assert.h> -#if defined(CONFIG_ENCODERS) || defined(XINE_MPEG_ENCODER) + +/* if xine's MPEG encoder is enabled, enable the encoding features in + * this particular module */ +#ifdef XINE_MPEG_ENCODER +#define CONFIG_ENCODERS +#endif + + +#ifdef CONFIG_ENCODERS static void encode_picture(MpegEncContext *s, int picture_number); #endif //CONFIG_ENCODERS static void dct_unquantize_mpeg1_intra_c(MpegEncContext *s, @@ -54,9 +63,10 @@ static void dct_unquantize_h263_intra_c(MpegEncContext *s, static void dct_unquantize_h263_inter_c(MpegEncContext *s, DCTELEM *block, int n, int qscale); static void draw_edges_c(uint8_t *buf, int wrap, int width, int height, int w); -#if defined(CONFIG_ENCODERS) || defined(XINE_MPEG_ENCODER) +#ifdef CONFIG_ENCODERS static int dct_quantize_c(MpegEncContext *s, DCTELEM *block, int n, int qscale, int *overflow); static int dct_quantize_trellis_c(MpegEncContext *s, DCTELEM *block, int n, int qscale, int *overflow); +static int dct_quantize_refine(MpegEncContext *s, DCTELEM *block, int16_t *weight, DCTELEM *orig, int n, int qscale); static int sse_mb(MpegEncContext *s); static void denoise_dct_c(MpegEncContext *s, DCTELEM *block); #endif //CONFIG_ENCODERS @@ -101,7 +111,7 @@ static const uint8_t ff_default_chroma_qscale_table[32]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 }; -#if defined(CONFIG_ENCODERS) || defined(XINE_MPEG_ENCODER) +#ifdef CONFIG_ENCODERS static uint8_t (*default_mv_penalty)[MAX_MV*2+1]=NULL; static uint8_t default_fcode_tab[MAX_MV*2+1]; @@ -195,7 +205,7 @@ void ff_init_scantable(uint8_t *permutation, ScanTable *st, const uint8_t *src_s } } -#if defined(CONFIG_ENCODERS) || defined(XINE_MPEG_ENCODER) +#ifdef CONFIG_ENCODERS void ff_write_quant_matrix(PutBitContext *pb, int16_t *matrix){ int i; @@ -219,7 +229,7 @@ int DCT_common_init(MpegEncContext *s) s->dct_unquantize_mpeg2_intra = dct_unquantize_mpeg2_intra_c; s->dct_unquantize_mpeg2_inter = dct_unquantize_mpeg2_inter_c; -#if defined(CONFIG_ENCODERS) || defined(XINE_MPEG_ENCODER) +#ifdef CONFIG_ENCODERS s->dct_quantize= dct_quantize_c; s->denoise_dct= denoise_dct_c; #endif @@ -243,7 +253,7 @@ int DCT_common_init(MpegEncContext *s) MPV_common_init_ppc(s); #endif -#if defined(CONFIG_ENCODERS) || defined(XINE_MPEG_ENCODER) +#ifdef CONFIG_ENCODERS s->fast_dct_quantize= s->dct_quantize; if(s->flags&CODEC_FLAG_TRELLIS_QUANT){ @@ -265,8 +275,6 @@ int DCT_common_init(MpegEncContext *s) ff_init_scantable(s->dsp.idct_permutation, &s->intra_h_scantable, ff_alternate_horizontal_scan); ff_init_scantable(s->dsp.idct_permutation, &s->intra_v_scantable, ff_alternate_vertical_scan); - s->picture_structure= PICT_FRAME; - return 0; } @@ -340,18 +348,21 @@ static int alloc_picture(MpegEncContext *s, Picture *pic, int shared){ pic->mb_type= pic->mb_type_base + s->mb_stride+1; if(s->out_format == FMT_H264){ for(i=0; i<2; i++){ - CHECKED_ALLOCZ(pic->motion_val_base[i], 2 * (b4_array_size+1) * sizeof(int16_t)) - pic->motion_val[i]= pic->motion_val_base[i]+1; + CHECKED_ALLOCZ(pic->motion_val_base[i], 2 * (b4_array_size+2) * sizeof(int16_t)) + pic->motion_val[i]= pic->motion_val_base[i]+2; CHECKED_ALLOCZ(pic->ref_index[i] , b8_array_size * sizeof(uint8_t)) } pic->motion_subsample_log2= 2; }else if(s->out_format == FMT_H263 || s->encoding || (s->avctx->debug&FF_DEBUG_MV) || (s->avctx->debug_mv)){ for(i=0; i<2; i++){ - CHECKED_ALLOCZ(pic->motion_val_base[i], 2 * (b8_array_size+1) * sizeof(int16_t)*2) //FIXME - pic->motion_val[i]= pic->motion_val_base[i]+1; + CHECKED_ALLOCZ(pic->motion_val_base[i], 2 * (b8_array_size+2) * sizeof(int16_t)*2) //FIXME + pic->motion_val[i]= pic->motion_val_base[i]+2; } pic->motion_subsample_log2= 3; } + if(s->avctx->debug&FF_DEBUG_DCT_COEFF) { + CHECKED_ALLOCZ(pic->dct_coeff, 64 * mb_array_size * sizeof(DCTELEM)*6) + } pic->qstride= s->mb_stride; CHECKED_ALLOCZ(pic->pan_scan , 1 * sizeof(AVPanScan)) } @@ -383,6 +394,7 @@ static void free_picture(MpegEncContext *s, Picture *pic){ av_freep(&pic->mbskip_table); av_freep(&pic->qscale_table); av_freep(&pic->mb_type_base); + av_freep(&pic->dct_coeff); av_freep(&pic->pan_scan); pic->mb_type= NULL; for(i=0; i<2; i++){ @@ -399,6 +411,105 @@ static void free_picture(MpegEncContext *s, Picture *pic){ } } +static int init_duplicate_context(MpegEncContext *s, MpegEncContext *base){ + int i; + + // edge emu needs blocksize + filter length - 1 (=17x17 for halfpel / 21x21 for h264) + CHECKED_ALLOCZ(s->allocated_edge_emu_buffer, (s->width+64)*2*17*2); //(width + edge + align)*interlaced*MBsize*tolerance + s->edge_emu_buffer= s->allocated_edge_emu_buffer + (s->width+64)*2*17; + + //FIXME should be linesize instead of s->width*2 but that isnt known before get_buffer() + CHECKED_ALLOCZ(s->me.scratchpad, (s->width+64)*2*16*2*sizeof(uint8_t)) + s->rd_scratchpad= s->me.scratchpad; + s->b_scratchpad= s->me.scratchpad; + s->obmc_scratchpad= s->me.scratchpad + 16; + if (s->encoding) { + CHECKED_ALLOCZ(s->me.map , ME_MAP_SIZE*sizeof(uint32_t)) + CHECKED_ALLOCZ(s->me.score_map, ME_MAP_SIZE*sizeof(uint32_t)) + if(s->avctx->noise_reduction){ + CHECKED_ALLOCZ(s->dct_error_sum, 2 * 64 * sizeof(int)) + } + } + CHECKED_ALLOCZ(s->blocks, 64*12*2 * sizeof(DCTELEM)) + s->block= s->blocks[0]; + + for(i=0;i<12;i++){ + s->pblocks[i] = (short *)(&s->block[i]); + } + return 0; +fail: + return -1; //free() through MPV_common_end() +} + +static void free_duplicate_context(MpegEncContext *s){ + if(s==NULL) return; + + av_freep(&s->allocated_edge_emu_buffer); s->edge_emu_buffer= NULL; + av_freep(&s->me.scratchpad); + s->rd_scratchpad= + s->b_scratchpad= + s->obmc_scratchpad= NULL; + + av_freep(&s->dct_error_sum); + av_freep(&s->me.map); + av_freep(&s->me.score_map); + av_freep(&s->blocks); + s->block= NULL; +} + +static void backup_duplicate_context(MpegEncContext *bak, MpegEncContext *src){ +#define COPY(a) bak->a= src->a + COPY(allocated_edge_emu_buffer); + COPY(edge_emu_buffer); + COPY(me.scratchpad); + COPY(rd_scratchpad); + COPY(b_scratchpad); + COPY(obmc_scratchpad); + COPY(me.map); + COPY(me.score_map); + COPY(blocks); + COPY(block); + COPY(start_mb_y); + COPY(end_mb_y); + COPY(me.map_generation); + COPY(pb); + COPY(dct_error_sum); + COPY(dct_count[0]); + COPY(dct_count[1]); +#undef COPY +} + +void ff_update_duplicate_context(MpegEncContext *dst, MpegEncContext *src){ + MpegEncContext bak; + int i; + //FIXME copy only needed parts +//START_TIMER + backup_duplicate_context(&bak, dst); + memcpy(dst, src, sizeof(MpegEncContext)); + backup_duplicate_context(dst, &bak); + for(i=0;i<12;i++){ + dst->pblocks[i] = (short *)(&dst->block[i]); + } +//STOP_TIMER("update_duplicate_context") //about 10k cycles / 0.01 sec for 1000frames on 1ghz with 2 threads +} + +static void update_duplicate_context_after_me(MpegEncContext *dst, MpegEncContext *src){ +#define COPY(a) dst->a= src->a + COPY(pict_type); + COPY(current_picture); + COPY(f_code); + COPY(b_code); + COPY(qscale); + COPY(lambda); + COPY(lambda2); + COPY(picture_in_gop_number); + COPY(gop_picture_number); + COPY(frame_pred_frame_dct); //FIXME dont set in encode_header + COPY(progressive_frame); //FIXME dont set in encode_header + COPY(partitioned_frame); //FIXME dont set in encode_header +#undef COPY +} + /* init common structure for both encoder and decoder */ int MPV_common_init(MpegEncContext *s) { @@ -434,9 +545,18 @@ int MPV_common_init(MpegEncContext *s) s->y_dc_scale_table= s->c_dc_scale_table= ff_mpeg1_dc_scale_table; s->chroma_qscale_table= ff_default_chroma_qscale_table; - if (!s->encoding) - s->progressive_sequence= 1; - s->progressive_frame= 1; + if( s->codec_id != CODEC_ID_MPEG1VIDEO && + s->codec_id != CODEC_ID_MPEG2VIDEO) + { + /* default structure is frame */ + s->progressive_frame= 1; + s->picture_structure= PICT_FRAME; + + s->y_dc_scale_table= + s->c_dc_scale_table= ff_mpeg1_dc_scale_table; + if (!s->encoding) + s->progressive_sequence= 1; + } s->coded_picture_number = 0; y_size = (2 * s->mb_width + 2) * (2 * s->mb_height + 2); @@ -454,9 +574,6 @@ int MPV_common_init(MpegEncContext *s) + (toupper((s->avctx->stream_codec_tag>>16)&0xFF)<<16) + (toupper((s->avctx->stream_codec_tag>>24)&0xFF)<<24); - CHECKED_ALLOCZ(s->allocated_edge_emu_buffer, (s->width+64)*2*17*2); //(width + edge + align)*interlaced*MBsize*tolerance - s->edge_emu_buffer= s->allocated_edge_emu_buffer + (s->width+64)*2*17; - s->avctx->coded_frame= (AVFrame*)&s->current_picture; CHECKED_ALLOCZ(s->mb_index2xy, (s->mb_num+1)*sizeof(int)) //error ressilience code looks cleaner with this @@ -482,17 +599,6 @@ int MPV_common_init(MpegEncContext *s) s->b_bidir_back_mv_table= s->b_bidir_back_mv_table_base + s->mb_stride + 1; s->b_direct_mv_table = s->b_direct_mv_table_base + s->mb_stride + 1; - //FIXME should be linesize instead of s->width*2 but that isnt known before get_buffer() - CHECKED_ALLOCZ(s->me.scratchpad, s->width*2*16*3*sizeof(uint8_t)) - - CHECKED_ALLOCZ(s->me.map , ME_MAP_SIZE*sizeof(uint32_t)) - CHECKED_ALLOCZ(s->me.score_map, ME_MAP_SIZE*sizeof(uint32_t)) - - 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->msmpeg4_version){ CHECKED_ALLOCZ(s->ac_stats, 2*2*(MAX_LEVEL+1)*(MAX_RUN+1)*2*sizeof(int)); } @@ -511,12 +617,9 @@ int MPV_common_init(MpegEncContext *s) CHECKED_ALLOCZ(s->reordered_input_picture, MAX_PICTURE_COUNT * sizeof(Picture*)) if(s->avctx->noise_reduction){ - CHECKED_ALLOCZ(s->dct_error_sum, 2 * 64 * sizeof(int)) CHECKED_ALLOCZ(s->dct_offset, 2 * 64 * sizeof(uint16_t)) } } - CHECKED_ALLOCZ(s->blocks, 64*6*2 * sizeof(DCTELEM)) - CHECKED_ALLOCZ(s->picture, MAX_PICTURE_COUNT * sizeof(Picture)) CHECKED_ALLOCZ(s->error_status_table, mb_array_size*sizeof(uint8_t)) @@ -576,12 +679,6 @@ int MPV_common_init(MpegEncContext *s) //Note the +1 is for a quicker mpeg4 slice_end detection CHECKED_ALLOCZ(s->prev_pict_types, PREV_PICT_TYPES_BUFFER_SIZE); - s->block= s->blocks[0]; - - for(i=0;i<12;i++){ - s->pblocks[i] = (short *)(&s->block[i]); - } - s->parse_context.state= -1; if((s->avctx->debug&(FF_DEBUG_VIS_QP|FF_DEBUG_VIS_MB_TYPE)) || (s->avctx->debug_mv)){ s->visualization_buffer[0] = av_malloc((s->mb_width*16 + 2*EDGE_WIDTH) * s->mb_height*16 + 2*EDGE_WIDTH); @@ -590,20 +687,38 @@ int MPV_common_init(MpegEncContext *s) } s->context_initialized = 1; + + s->thread_context[0]= s; + for(i=1; i<s->avctx->thread_count; i++){ + s->thread_context[i]= av_malloc(sizeof(MpegEncContext)); + memcpy(s->thread_context[i], s, sizeof(MpegEncContext)); + } + + for(i=0; i<s->avctx->thread_count; i++){ + if(init_duplicate_context(s->thread_context[i], s) < 0) + goto fail; + s->thread_context[i]->start_mb_y= (s->mb_height*(i ) + s->avctx->thread_count/2) / s->avctx->thread_count; + s->thread_context[i]->end_mb_y = (s->mb_height*(i+1) + s->avctx->thread_count/2) / s->avctx->thread_count; + } + return 0; fail: MPV_common_end(s); return -1; } - -//extern int sads; - /* init common structure for both encoder and decoder */ void MPV_common_end(MpegEncContext *s) { int i, j, k; + for(i=0; i<s->avctx->thread_count; i++){ + free_duplicate_context(s->thread_context[i]); + } + for(i=1; i<s->avctx->thread_count; i++){ + av_freep(&s->thread_context[i]); + } + av_freep(&s->parse_context.buffer); s->parse_context.buffer_size=0; @@ -639,16 +754,10 @@ void MPV_common_end(MpegEncContext *s) av_freep(&s->mbintra_table); av_freep(&s->cbp_table); av_freep(&s->pred_dir_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->prev_pict_types); av_freep(&s->bitstream_buffer); - av_freep(&s->tex_pb_buffer); - av_freep(&s->pb2_buffer); - av_freep(&s->allocated_edge_emu_buffer); s->edge_emu_buffer= NULL; av_freep(&s->avctx->stats_out); av_freep(&s->ac_stats); av_freep(&s->error_status_table); @@ -658,10 +767,8 @@ void MPV_common_end(MpegEncContext *s) av_freep(&s->q_inter_matrix); av_freep(&s->q_intra_matrix16); av_freep(&s->q_inter_matrix16); - av_freep(&s->blocks); av_freep(&s->input_picture); av_freep(&s->reordered_input_picture); - av_freep(&s->dct_error_sum); av_freep(&s->dct_offset); if(s->picture){ @@ -680,7 +787,7 @@ void MPV_common_end(MpegEncContext *s) av_free(s->visualization_buffer[i]); } -#if defined(CONFIG_ENCODERS) || defined(XINE_MPEG_ENCODER) +#ifdef CONFIG_ENCODERS /* init video encoder */ int MPV_encode_init(AVCodecContext *avctx) @@ -746,7 +853,7 @@ int MPV_encode_init(AVCodecContext *avctx) } if((s->flags & CODEC_FLAG_4MV) && s->codec_id != CODEC_ID_MPEG4 - && s->codec_id != CODEC_ID_H263 && s->codec_id != CODEC_ID_H263P){ + && s->codec_id != CODEC_ID_H263 && s->codec_id != CODEC_ID_H263P && s->codec_id != CODEC_ID_FLV1){ av_log(avctx, AV_LOG_ERROR, "4MV not supported by codec\n"); return -1; } @@ -795,6 +902,21 @@ int MPV_encode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_ERROR, "closed gop with scene change detection arent supported yet\n"); return -1; } + + if(s->avctx->thread_count > 1 && s->codec_id != CODEC_ID_MPEG4 + && s->codec_id != CODEC_ID_MPEG1VIDEO && s->codec_id != CODEC_ID_MPEG2VIDEO + && (s->codec_id != CODEC_ID_H263P || !(s->flags & CODEC_FLAG_H263P_SLICE_STRUCT))){ + av_log(avctx, AV_LOG_ERROR, "multi threaded encoding not supported by codec\n"); + return -1; + } + + if(s->avctx->thread_count > MAX_THREADS || 16*s->avctx->thread_count > s->height){ + av_log(avctx, AV_LOG_ERROR, "too many threads\n"); + return -1; + } + + if(s->avctx->thread_count > 1) + s->rtp_mode= 1; i= ff_gcd(avctx->frame_rate, avctx->frame_rate_base); if(i > 1){ @@ -831,7 +953,8 @@ int MPV_encode_init(AVCodecContext *avctx) s->low_delay= 0; //s->max_b_frames ? 0 : 1; avctx->delay= s->low_delay ? 0 : (s->max_b_frames + 1); break; -#if defined(CONFIG_ENCODERS) || !defined(XINE_MPEG_ENCODER) +/* xine: this is never used in either decode or MPEG-1 encode mode */ +#if 0 case CODEC_ID_MPEG2VIDEO: s->out_format = FMT_MPEG1; s->low_delay= 0; //s->max_b_frames ? 0 : 1; @@ -953,7 +1076,7 @@ int MPV_encode_init(AVCodecContext *avctx) s->low_delay=1; break; #endif -#endif +#endif /* #if 0 */ default: return -1; } @@ -990,14 +1113,18 @@ int MPV_encode_init(AVCodecContext *avctx) s->chroma_qscale_table= ff_h263_chroma_qscale_table; s->progressive_frame= s->progressive_sequence= !(avctx->flags & (CODEC_FLAG_INTERLACED_DCT|CODEC_FLAG_INTERLACED_ME)); + s->quant_precision=5; ff_set_cmp(&s->dsp, s->dsp.ildct_cmp, s->avctx->ildct_cmp); -#if defined(CONFIG_ENCODERS) || !defined(XINE_MPEG_ENCODER) +/* xine: do not need this for decode or MPEG-1 encoding modes */ +#if 0 ff_init_me(s); -#endif +#endif /* #if 0 */ -#if defined(CONFIG_ENCODERS) || !defined(XINE_MPEG_ENCODER) +/* xine: do not need this for decode or MPEG-1 encoding modes */ +#if 0 +#ifdef CONFIG_ENCODERS #ifdef CONFIG_RISKY if (s->out_format == FMT_H263) h263_encode_init(s); @@ -1005,6 +1132,8 @@ int MPV_encode_init(AVCodecContext *avctx) ff_msmpeg4_encode_init(s); #endif #endif +#endif /* #if 0 */ +/* xine: we do want this for MPEG-1 encoding */ if (s->out_format == FMT_MPEG1) ff_mpeg1_encode_init(s); @@ -1062,11 +1191,12 @@ int MPV_encode_end(AVCodecContext *avctx) ff_rate_control_uninit(s); +/* xine: do not need this for decode or MPEG-1 encoding modes */ +#if 0 MPV_common_end(s); -#if defined(CONFIG_ENCODERS) || !defined(XINE_MPEG_ENCODER) if (s->out_format == FMT_MJPEG) mjpeg_close(s); -#endif +#endif /* #if 0 */ av_freep(&avctx->extradata); @@ -1650,7 +1780,7 @@ v= (int)(128 + r*sin(theta*3.141592/180)); } } -#if defined(CONFIG_ENCODERS) || defined(XINE_MPEG_ENCODER) +#ifdef CONFIG_ENCODERS static int get_sae(uint8_t *src, int ref, int stride){ int x,y; @@ -1753,8 +1883,18 @@ static int load_input_picture(MpegEncContext *s, AVFrame *pic_arg){ copy_picture_attributes(pic, pic_arg); pic->display_picture_number= s->input_picture_number++; + if(pic->pts != AV_NOPTS_VALUE){ + s->user_specified_pts= pic->pts; + }else{ + if(s->user_specified_pts){ + pic->pts= s->user_specified_pts + AV_TIME_BASE*(int64_t)s->avctx->frame_rate_base / s->avctx->frame_rate; + av_log(s->avctx, AV_LOG_INFO, "Warning: AVFrame.pts=? trying to guess (%Ld)\n", pic->pts); + }else{ + pic->pts= av_rescale(pic->display_picture_number*(int64_t)s->avctx->frame_rate_base, AV_TIME_BASE, s->avctx->frame_rate); + } + } } - + /* shift buffer entries */ for(i=1; i<MAX_PICTURE_COUNT /*s->encoding_delay+1*/; i++) s->input_picture[i-1]= s->input_picture[i]; @@ -1907,7 +2047,15 @@ int MPV_encode_picture(AVCodecContext *avctx, return -1; } - init_put_bits(&s->pb, buf, buf_size); + for(i=0; i<avctx->thread_count; i++){ + int start_y= s->thread_context[i]->start_mb_y; + int end_y= s->thread_context[i]-> end_mb_y; + int h= s->mb_height; + uint8_t *start= buf + buf_size*start_y/h; + uint8_t *end = buf + buf_size* end_y/h; + + init_put_bits(&s->thread_context[i]->pb, start, end - start); + } s->picture_in_gop_number++; @@ -1936,10 +2084,11 @@ int MPV_encode_picture(AVCodecContext *avctx, MPV_frame_end(s); -#if defined(CONFIG_ENCODERS) || !defined(XINE_MPEG_ENCODER) +/* xine: do not need this for decode or MPEG-1 encoding modes */ +#if 0 if (s->out_format == FMT_MJPEG) mjpeg_picture_trailer(s); -#endif +#endif /* #if 0 */ if(s->flags&CODEC_FLAG_PASS1) ff_write_pass1_stats(s); @@ -1949,7 +2098,7 @@ int MPV_encode_picture(AVCodecContext *avctx, } flush_put_bits(&s->pb); - s->frame_bits = (pbBufPtr(&s->pb) - s->pb.buf) * 8; + s->frame_bits = put_bits_count(&s->pb); stuffing_count= ff_vbv_update(s, s->frame_bits); if(stuffing_count){ @@ -1972,11 +2121,11 @@ int MPV_encode_picture(AVCodecContext *avctx, av_log(s->avctx, AV_LOG_ERROR, "vbv buffer overflow\n"); } flush_put_bits(&s->pb); - s->frame_bits = (pbBufPtr(&s->pb) - s->pb.buf) * 8; + s->frame_bits = put_bits_count(&s->pb); } /* update mpeg1/2 vbv_delay for CBR */ - if(s->avctx->rc_max_rate && s->avctx->rc_min_rate == s->avctx->rc_max_rate){ + if(s->avctx->rc_max_rate && s->avctx->rc_min_rate == s->avctx->rc_max_rate && s->out_format == FMT_MPEG1){ int vbv_delay; assert(s->repeat_first_field==0); @@ -2005,8 +2154,7 @@ int MPV_encode_picture(AVCodecContext *avctx, static inline void gmc1_motion(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, - int dest_offset, - uint8_t **ref_picture, int src_offset) + uint8_t **ref_picture) { uint8_t *ptr; int offset, src_x, src_y, linesize, uvlinesize; @@ -2029,9 +2177,8 @@ static inline void gmc1_motion(MpegEncContext *s, linesize = s->linesize; uvlinesize = s->uvlinesize; - ptr = ref_picture[0] + (src_y * linesize) + src_x + src_offset; + ptr = ref_picture[0] + (src_y * linesize) + src_x; - dest_y+=dest_offset; if(s->flags&CODEC_FLAG_EMU_EDGE){ if( (unsigned)src_x >= s->h_edge_pos - 17 || (unsigned)src_y >= s->v_edge_pos - 17){ @@ -2069,7 +2216,7 @@ static inline void gmc1_motion(MpegEncContext *s, if (src_y == s->height>>1) motion_y =0; - offset = (src_y * uvlinesize) + src_x + (src_offset>>1); + offset = (src_y * uvlinesize) + src_x; ptr = ref_picture[1] + offset; if(s->flags&CODEC_FLAG_EMU_EDGE){ if( (unsigned)src_x >= (s->h_edge_pos>>1) - 9 @@ -2079,22 +2226,21 @@ static inline void gmc1_motion(MpegEncContext *s, emu=1; } } - s->dsp.gmc1(dest_cb + (dest_offset>>1), ptr, uvlinesize, 8, motion_x&15, motion_y&15, 128 - s->no_rounding); + s->dsp.gmc1(dest_cb, ptr, uvlinesize, 8, motion_x&15, motion_y&15, 128 - s->no_rounding); ptr = ref_picture[2] + offset; if(emu){ ff_emulated_edge_mc(s->edge_emu_buffer, ptr, uvlinesize, 9, 9, src_x, src_y, s->h_edge_pos>>1, s->v_edge_pos>>1); ptr= s->edge_emu_buffer; } - s->dsp.gmc1(dest_cr + (dest_offset>>1), ptr, uvlinesize, 8, motion_x&15, motion_y&15, 128 - s->no_rounding); + s->dsp.gmc1(dest_cr, ptr, uvlinesize, 8, motion_x&15, motion_y&15, 128 - s->no_rounding); return; } static inline void gmc_motion(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, - int dest_offset, - uint8_t **ref_picture, int src_offset) + uint8_t **ref_picture) { uint8_t *ptr; int linesize, uvlinesize; @@ -2104,10 +2250,8 @@ static inline void gmc_motion(MpegEncContext *s, linesize = s->linesize; uvlinesize = s->uvlinesize; - ptr = ref_picture[0] + src_offset; + ptr = ref_picture[0]; - dest_y+=dest_offset; - ox= s->sprite_offset[0][0] + s->sprite_delta[0][0]*s->mb_x*16 + s->sprite_delta[0][1]*s->mb_y*16; oy= s->sprite_offset[0][1] + s->sprite_delta[1][0]*s->mb_x*16 + s->sprite_delta[1][1]*s->mb_y*16; @@ -2128,14 +2272,10 @@ static inline void gmc_motion(MpegEncContext *s, if(s->flags&CODEC_FLAG_GRAY) return; - - dest_cb+=dest_offset>>1; - dest_cr+=dest_offset>>1; - ox= s->sprite_offset[1][0] + s->sprite_delta[0][0]*s->mb_x*8 + s->sprite_delta[0][1]*s->mb_y*8; oy= s->sprite_offset[1][1] + s->sprite_delta[1][0]*s->mb_x*8 + s->sprite_delta[1][1]*s->mb_y*8; - ptr = ref_picture[1] + (src_offset>>1); + ptr = ref_picture[1]; s->dsp.gmc(dest_cb, ptr, uvlinesize, 8, ox, oy, @@ -2144,7 +2284,7 @@ static inline void gmc_motion(MpegEncContext *s, a+1, (1<<(2*a+1)) - s->no_rounding, s->h_edge_pos>>1, s->v_edge_pos>>1); - ptr = ref_picture[2] + (src_offset>>1); + ptr = ref_picture[2]; s->dsp.gmc(dest_cr, ptr, uvlinesize, 8, ox, oy, @@ -2226,7 +2366,8 @@ void ff_emulated_edge_mc(uint8_t *buf, uint8_t *src, int linesize, int block_w, } static inline int hpel_motion(MpegEncContext *s, - uint8_t *dest, uint8_t *src, + uint8_t *dest, uint8_t *src, + int field_based, int field_select, int src_x, int src_y, int width, int height, int stride, int h_edge_pos, int v_edge_pos, @@ -2252,12 +2393,14 @@ static inline int hpel_motion(MpegEncContext *s, if(s->unrestricted_mv && (s->flags&CODEC_FLAG_EMU_EDGE)){ if( (unsigned)src_x > h_edge_pos - (motion_x&1) - w || (unsigned)src_y > v_edge_pos - (motion_y&1) - h){ - ff_emulated_edge_mc(s->edge_emu_buffer, src, stride, w+1, h+1, - src_x, src_y, h_edge_pos, v_edge_pos); + ff_emulated_edge_mc(s->edge_emu_buffer, src, s->linesize, w+1, (h+1)<<field_based, + src_x, src_y<<field_based, h_edge_pos, s->v_edge_pos); src= s->edge_emu_buffer; emu=1; } } + if(field_select) + src += s->linesize; pix_op[dxy](dest, src, stride, h); return emu; } @@ -2265,14 +2408,13 @@ static inline int hpel_motion(MpegEncContext *s, /* apply one mpeg motion vector to the three components */ static inline void mpeg_motion(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, - int dest_offset, - uint8_t **ref_picture, int src_offset, - int field_based, op_pixels_func (*pix_op)[4], + int field_based, int bottom_field, int field_select, + uint8_t **ref_picture, op_pixels_func (*pix_op)[4], int motion_x, int motion_y, int h) { - uint8_t *ptr; - int dxy, offset, mx, my, src_x, src_y, height, v_edge_pos, uvlinesize; - int emu=0; + uint8_t *ptr_y, *ptr_cb, *ptr_cr; + int dxy, uvdxy, mx, my, src_x, src_y, uvsrc_x, uvsrc_y, v_edge_pos, uvlinesize, linesize; + #if 0 if(s->quarter_sample) { @@ -2281,61 +2423,64 @@ if(s->quarter_sample) } #endif - height = s->height >> field_based; v_edge_pos = s->v_edge_pos >> field_based; + linesize = s->current_picture.linesize[0] << field_based; uvlinesize = s->current_picture.linesize[1] << field_based; - emu= hpel_motion(s, - dest_y + dest_offset, ref_picture[0] + src_offset, - s->mb_x * 16, s->mb_y * (16 >> field_based), - s->width, height, s->current_picture.linesize[0] << field_based, - s->h_edge_pos, v_edge_pos, - 16, h, pix_op[0], - motion_x, motion_y); - - - if(s->flags&CODEC_FLAG_GRAY) return; + dxy = ((motion_y & 1) << 1) | (motion_x & 1); + src_x = s->mb_x* 16 + (motion_x >> 1); + src_y = s->mb_y*(16>>field_based) + (motion_y >> 1); if (s->out_format == FMT_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; + uvdxy = dxy | (motion_y & 2) | ((motion_x & 2) >> 1); + uvsrc_x = src_x>>1; + uvsrc_y = src_y>>1; } else { mx = motion_x / 2; my = motion_y / 2; - dxy = ((my & 1) << 1) | (mx & 1); - mx >>= 1; - my >>= 1; + uvdxy = ((my & 1) << 1) | (mx & 1); + uvsrc_x = s->mb_x* 8 + (mx >> 1); + uvsrc_y = s->mb_y*(8>>field_based) + (my >> 1); } - - src_x = s->mb_x * 8 + mx; - src_y = s->mb_y * (8 >> field_based) + my; - src_x = clip(src_x, -8, s->width >> 1); - if (src_x == (s->width >> 1)) - dxy &= ~1; - src_y = clip(src_y, -8, height >> 1); - if (src_y == (height >> 1)) - dxy &= ~2; - offset = (src_y * uvlinesize) + src_x + (src_offset >> 1); - ptr = ref_picture[1] + offset; - if(emu){ - ff_emulated_edge_mc(s->edge_emu_buffer, ptr - (src_offset >> 1), s->uvlinesize, 9, 9+field_based, - src_x, src_y<<field_based, s->h_edge_pos>>1, s->v_edge_pos>>1); - ptr= s->edge_emu_buffer + (src_offset >> 1); + + ptr_y = ref_picture[0] + src_y * linesize + src_x; + ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x; + ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x; + + if( (unsigned)src_x > s->h_edge_pos - (motion_x&1) - 16 + || (unsigned)src_y > v_edge_pos - (motion_y&1) - h){ + ff_emulated_edge_mc(s->edge_emu_buffer, ptr_y, s->linesize, 17, 17+field_based, + src_x, src_y<<field_based, s->h_edge_pos, s->v_edge_pos); + ptr_y = s->edge_emu_buffer; + if(!(s->flags&CODEC_FLAG_GRAY)){ + uint8_t *uvbuf= s->edge_emu_buffer+18*s->linesize; + ff_emulated_edge_mc(uvbuf , ptr_cb, s->uvlinesize, 9, 9+field_based, + uvsrc_x, uvsrc_y<<field_based, s->h_edge_pos>>1, s->v_edge_pos>>1); + ff_emulated_edge_mc(uvbuf+16, ptr_cr, s->uvlinesize, 9, 9+field_based, + uvsrc_x, uvsrc_y<<field_based, s->h_edge_pos>>1, s->v_edge_pos>>1); + ptr_cb= uvbuf; + ptr_cr= uvbuf+16; + } } - pix_op[1][dxy](dest_cb + (dest_offset >> 1), ptr, uvlinesize, h >> 1); - ptr = ref_picture[2] + offset; - if(emu){ - ff_emulated_edge_mc(s->edge_emu_buffer, ptr - (src_offset >> 1), s->uvlinesize, 9, 9+field_based, - src_x, src_y<<field_based, s->h_edge_pos>>1, s->v_edge_pos>>1); - ptr= s->edge_emu_buffer + (src_offset >> 1); + if(bottom_field){ //FIXME use this for field pix too instead of the obnoxious hack which changes picture.data + dest_y += s->linesize; + dest_cb+= s->uvlinesize; + dest_cr+= s->uvlinesize; + } + + if(field_select){ + ptr_y += s->linesize; + ptr_cb+= s->uvlinesize; + ptr_cr+= s->uvlinesize; + } + + pix_op[0][dxy](dest_y, ptr_y, linesize, h); + + if(!(s->flags&CODEC_FLAG_GRAY)){ + pix_op[1][uvdxy](dest_cb, ptr_cb, uvlinesize, h >> 1); + pix_op[1][uvdxy](dest_cr, ptr_cr, uvlinesize, h >> 1); } - pix_op[1][dxy](dest_cr + (dest_offset >> 1), ptr, uvlinesize, h >> 1); } //FIXME move to dsputil, avg variant, 16x16 version static inline void put_obmc(uint8_t *dst, uint8_t *src[5], int stride){ @@ -2406,8 +2551,8 @@ static inline void obmc_motion(MpegEncContext *s, if(i && mv[i][0]==mv[MID][0] && mv[i][1]==mv[MID][1]){ ptr[i]= ptr[MID]; }else{ - ptr[i]= s->edge_emu_buffer + 16 + 8*(i&1) + s->linesize*8*(i>>1); - hpel_motion(s, ptr[i], src, + ptr[i]= s->obmc_scratchpad + 8*(i&1) + s->linesize*8*(i>>1); + hpel_motion(s, ptr[i], src, 0, 0, src_x, src_y, s->width, s->height, s->linesize, s->h_edge_pos, s->v_edge_pos, @@ -2421,54 +2566,22 @@ static inline void obmc_motion(MpegEncContext *s, static inline void qpel_motion(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, - int dest_offset, - uint8_t **ref_picture, int src_offset, - int field_based, op_pixels_func (*pix_op)[4], + int field_based, int bottom_field, int field_select, + uint8_t **ref_picture, op_pixels_func (*pix_op)[4], qpel_mc_func (*qpix_op)[16], int motion_x, int motion_y, int h) { - uint8_t *ptr; - int dxy, offset, mx, my, src_x, src_y, height, v_edge_pos, linesize, uvlinesize; - int emu=0; + uint8_t *ptr_y, *ptr_cb, *ptr_cr; + int dxy, uvdxy, mx, my, src_x, src_y, uvsrc_x, uvsrc_y, v_edge_pos, linesize, uvlinesize; dxy = ((motion_y & 3) << 2) | (motion_x & 3); - src_x = s->mb_x * 16 + (motion_x >> 2); + src_x = s->mb_x * 16 + (motion_x >> 2); src_y = s->mb_y * (16 >> field_based) + (motion_y >> 2); - height = s->height >> field_based; v_edge_pos = s->v_edge_pos >> field_based; - src_x = clip(src_x, -16, s->width); - if (src_x == s->width) - dxy &= ~3; - src_y = clip(src_y, -16, height); - if (src_y == height) - dxy &= ~12; linesize = s->linesize << field_based; uvlinesize = s->uvlinesize << field_based; - ptr = ref_picture[0] + (src_y * linesize) + src_x + src_offset; - dest_y += dest_offset; -//printf("%d %d %d\n", src_x, src_y, dxy); - if(s->flags&CODEC_FLAG_EMU_EDGE){ - if( (unsigned)src_x > s->h_edge_pos - (motion_x&3) - 16 - || (unsigned)src_y > v_edge_pos - (motion_y&3) - h ){ - ff_emulated_edge_mc(s->edge_emu_buffer, ptr - src_offset, s->linesize, 17, 17+field_based, - src_x, src_y<<field_based, s->h_edge_pos, s->v_edge_pos); - ptr= s->edge_emu_buffer + src_offset; - emu=1; - } - } - if(!field_based) - qpix_op[0][dxy](dest_y, ptr, linesize); - else{ - //damn interlaced mode - //FIXME boundary mirroring is not exactly correct here - qpix_op[1][dxy](dest_y , ptr , linesize); - qpix_op[1][dxy](dest_y+8, ptr+8, linesize); - } - - if(s->flags&CODEC_FLAG_GRAY) return; - if(field_based){ mx= motion_x/2; my= motion_y>>1; @@ -2486,35 +2599,56 @@ static inline void qpel_motion(MpegEncContext *s, mx= (mx>>1)|(mx&1); my= (my>>1)|(my&1); - dxy= (mx&1) | ((my&1)<<1); + uvdxy= (mx&1) | ((my&1)<<1); mx>>=1; my>>=1; - src_x = s->mb_x * 8 + mx; - src_y = s->mb_y * (8 >> field_based) + my; - src_x = clip(src_x, -8, s->width >> 1); - if (src_x == (s->width >> 1)) - dxy &= ~1; - src_y = clip(src_y, -8, height >> 1); - if (src_y == (height >> 1)) - dxy &= ~2; + uvsrc_x = s->mb_x * 8 + mx; + uvsrc_y = s->mb_y * (8 >> field_based) + my; + + ptr_y = ref_picture[0] + src_y * linesize + src_x; + ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x; + ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x; + + if( (unsigned)src_x > s->h_edge_pos - (motion_x&3) - 16 + || (unsigned)src_y > v_edge_pos - (motion_y&3) - h ){ + ff_emulated_edge_mc(s->edge_emu_buffer, ptr_y, s->linesize, 17, 17+field_based, + src_x, src_y<<field_based, s->h_edge_pos, s->v_edge_pos); + ptr_y= s->edge_emu_buffer; + if(!(s->flags&CODEC_FLAG_GRAY)){ + uint8_t *uvbuf= s->edge_emu_buffer + 18*s->linesize; + ff_emulated_edge_mc(uvbuf, ptr_cb, s->uvlinesize, 9, 9 + field_based, + uvsrc_x, uvsrc_y<<field_based, s->h_edge_pos>>1, s->v_edge_pos>>1); + ff_emulated_edge_mc(uvbuf + 16, ptr_cr, s->uvlinesize, 9, 9 + field_based, + uvsrc_x, uvsrc_y<<field_based, s->h_edge_pos>>1, s->v_edge_pos>>1); + ptr_cb= uvbuf; + ptr_cr= uvbuf + 16; + } + } - offset = (src_y * uvlinesize) + src_x + (src_offset >> 1); - ptr = ref_picture[1] + offset; - if(emu){ - ff_emulated_edge_mc(s->edge_emu_buffer, ptr - (src_offset >> 1), s->uvlinesize, 9, 9 + field_based, - src_x, src_y<<field_based, s->h_edge_pos>>1, s->v_edge_pos>>1); - ptr= s->edge_emu_buffer + (src_offset >> 1); + if(!field_based) + qpix_op[0][dxy](dest_y, ptr_y, linesize); + else{ + if(bottom_field){ + dest_y += s->linesize; + dest_cb+= s->uvlinesize; + dest_cr+= s->uvlinesize; + } + + if(field_select){ + ptr_y += s->linesize; + ptr_cb += s->uvlinesize; + ptr_cr += s->uvlinesize; + } + //damn interlaced mode + //FIXME boundary mirroring is not exactly correct here + qpix_op[1][dxy](dest_y , ptr_y , linesize); + qpix_op[1][dxy](dest_y+8, ptr_y+8, linesize); } - pix_op[1][dxy](dest_cb + (dest_offset >> 1), ptr, uvlinesize, h >> 1); - - ptr = ref_picture[2] + offset; - if(emu){ - ff_emulated_edge_mc(s->edge_emu_buffer, ptr - (src_offset >> 1), s->uvlinesize, 9, 9 + field_based, - src_x, src_y<<field_based, s->h_edge_pos>>1, s->v_edge_pos>>1); - ptr= s->edge_emu_buffer + (src_offset >> 1); + if(!(s->flags&CODEC_FLAG_GRAY)){ + pix_op[1][uvdxy](dest_cr, ptr_cr, uvlinesize, h >> 1); + pix_op[1][uvdxy](dest_cb, ptr_cb, uvlinesize, h >> 1); } - pix_op[1][dxy](dest_cr + (dest_offset >> 1), ptr, uvlinesize, h >> 1); } inline int ff_h263_round_chroma(int x){ @@ -2665,16 +2799,16 @@ static inline void MPV_motion(MpegEncContext *s, #ifdef CONFIG_RISKY if(s->mcsel){ if(s->real_sprite_warping_points==1){ - gmc1_motion(s, dest_y, dest_cb, dest_cr, 0, - ref_picture, 0); + gmc1_motion(s, dest_y, dest_cb, dest_cr, + ref_picture); }else{ - gmc_motion(s, dest_y, dest_cb, dest_cr, 0, - ref_picture, 0); + gmc_motion(s, dest_y, dest_cb, dest_cr, + ref_picture); } }else if(s->quarter_sample){ - qpel_motion(s, dest_y, dest_cb, dest_cr, 0, - ref_picture, 0, - 0, pix_op, qpix_op, + qpel_motion(s, dest_y, dest_cb, dest_cr, + 0, 0, 0, + ref_picture, pix_op, qpix_op, s->mv[dir][0][0], s->mv[dir][0][1], 16); }else if(s->mspel){ ff_mspel_motion(s, dest_y, dest_cb, dest_cr, @@ -2683,9 +2817,9 @@ static inline void MPV_motion(MpegEncContext *s, }else #endif { - mpeg_motion(s, dest_y, dest_cb, dest_cr, 0, - ref_picture, 0, - 0, pix_op, + mpeg_motion(s, dest_y, dest_cb, dest_cr, + 0, 0, 0, + ref_picture, pix_op, s->mv[dir][0][0], s->mv[dir][0][1], 16); } break; @@ -2726,7 +2860,7 @@ static inline void MPV_motion(MpegEncContext *s, }else{ for(i=0;i<4;i++) { hpel_motion(s, dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize, - ref_picture[0], + ref_picture[0], 0, 0, mb_x * 16 + (i & 1) * 8, mb_y * 16 + (i >>1) * 8, s->width, s->height, s->linesize, s->h_edge_pos, s->v_edge_pos, @@ -2744,140 +2878,83 @@ static inline void MPV_motion(MpegEncContext *s, case MV_TYPE_FIELD: if (s->picture_structure == PICT_FRAME) { if(s->quarter_sample){ - /* top field */ - qpel_motion(s, dest_y, dest_cb, dest_cr, 0, - ref_picture, s->field_select[dir][0] ? s->linesize : 0, - 1, pix_op, qpix_op, - s->mv[dir][0][0], s->mv[dir][0][1], 8); - /* bottom field */ - qpel_motion(s, dest_y, dest_cb, dest_cr, s->linesize, - ref_picture, s->field_select[dir][1] ? s->linesize : 0, - 1, pix_op, qpix_op, - s->mv[dir][1][0], s->mv[dir][1][1], 8); + for(i=0; i<2; i++){ + qpel_motion(s, dest_y, dest_cb, dest_cr, + 1, i, s->field_select[dir][i], + ref_picture, pix_op, qpix_op, + s->mv[dir][i][0], s->mv[dir][i][1], 8); + } }else{ /* top field */ - mpeg_motion(s, dest_y, dest_cb, dest_cr, 0, - ref_picture, s->field_select[dir][0] ? s->linesize : 0, - 1, pix_op, + mpeg_motion(s, dest_y, dest_cb, dest_cr, + 1, 0, s->field_select[dir][0], + ref_picture, pix_op, s->mv[dir][0][0], s->mv[dir][0][1], 8); /* bottom field */ - mpeg_motion(s, dest_y, dest_cb, dest_cr, s->linesize, - ref_picture, s->field_select[dir][1] ? s->linesize : 0, - 1, pix_op, + mpeg_motion(s, dest_y, dest_cb, dest_cr, + 1, 1, s->field_select[dir][1], + ref_picture, pix_op, s->mv[dir][1][0], s->mv[dir][1][1], 8); } } else { - int offset; - if(s->picture_structure == s->field_select[dir][0] + 1 || s->pict_type == B_TYPE || s->first_field){ - offset= s->field_select[dir][0] ? s->linesize : 0; - }else{ - ref_picture= s->current_picture.data; - offset= s->field_select[dir][0] ? s->linesize : -s->linesize; + if(s->picture_structure != s->field_select[dir][0] + 1 && s->pict_type != B_TYPE && !s->first_field){ + ref_picture= s->current_picture_ptr->data; } - mpeg_motion(s, dest_y, dest_cb, dest_cr, 0, - ref_picture, offset, - 0, pix_op, + mpeg_motion(s, dest_y, dest_cb, dest_cr, + 0, 0, s->field_select[dir][0], + ref_picture, pix_op, s->mv[dir][0][0], s->mv[dir][0][1], 16); } break; - case MV_TYPE_16X8:{ - int offset; - uint8_t ** ref2picture; + case MV_TYPE_16X8: + for(i=0; i<2; i++){ + uint8_t ** ref2picture; - if(s->picture_structure == s->field_select[dir][0] + 1 || s->pict_type == B_TYPE || s->first_field){ + if(s->picture_structure == s->field_select[dir][i] + 1 || s->pict_type == B_TYPE || s->first_field){ ref2picture= ref_picture; - offset= s->field_select[dir][0] ? s->linesize : 0; }else{ - ref2picture= s->current_picture.data; - offset= s->field_select[dir][0] ? s->linesize : -s->linesize; + ref2picture= s->current_picture_ptr->data; } - mpeg_motion(s, dest_y, dest_cb, dest_cr, 0, - ref2picture, offset, - 0, pix_op, - s->mv[dir][0][0], s->mv[dir][0][1], 8); - - - if(s->picture_structure == s->field_select[dir][1] + 1 || s->pict_type == B_TYPE || s->first_field){ - ref2picture= ref_picture; - offset= s->field_select[dir][1] ? s->linesize : 0; - }else{ - ref2picture= s->current_picture.data; - offset= s->field_select[dir][1] ? s->linesize : -s->linesize; - } - // I know it is ugly but this is the only way to fool emu_edge without rewrite mpeg_motion - mpeg_motion(s, dest_y+16*s->linesize, dest_cb+8*s->uvlinesize, dest_cr+8*s->uvlinesize, - 0, - ref2picture, offset, - 0, pix_op, - s->mv[dir][1][0], s->mv[dir][1][1]+16, 8); - } - + mpeg_motion(s, dest_y, dest_cb, dest_cr, + 0, 0, s->field_select[dir][i], + ref2picture, pix_op, + s->mv[dir][i][0], s->mv[dir][i][1] + 16*i, 8); + + dest_y += 16*s->linesize; + dest_cb+= 8*s->uvlinesize; + dest_cr+= 8*s->uvlinesize; + } break; case MV_TYPE_DMV: - { - op_pixels_func (*dmv_pix_op)[4]; - int offset; - - dmv_pix_op = s->dsp.put_pixels_tab; - if(s->picture_structure == PICT_FRAME){ - //put top field from top field - mpeg_motion(s, dest_y, dest_cb, dest_cr, 0, - ref_picture, 0, - 1, dmv_pix_op, - s->mv[dir][0][0], s->mv[dir][0][1], 8); - //put bottom field from bottom field - mpeg_motion(s, dest_y, dest_cb, dest_cr, s->linesize, - ref_picture, s->linesize, - 1, dmv_pix_op, - s->mv[dir][0][0], s->mv[dir][0][1], 8); - - dmv_pix_op = s->dsp.avg_pixels_tab; - - //avg top field from bottom field - mpeg_motion(s, dest_y, dest_cb, dest_cr, 0, - ref_picture, s->linesize, - 1, dmv_pix_op, - s->mv[dir][2][0], s->mv[dir][2][1], 8); - //avg bottom field from top field - mpeg_motion(s, dest_y, dest_cb, dest_cr, s->linesize, - ref_picture, 0, - 1, dmv_pix_op, - s->mv[dir][3][0], s->mv[dir][3][1], 8); - + for(i=0; i<2; i++){ + int j; + for(j=0; j<2; j++){ + mpeg_motion(s, dest_y, dest_cb, dest_cr, + 1, j, j^i, + ref_picture, pix_op, + s->mv[dir][2*i + j][0], s->mv[dir][2*i + j][1], 8); + } + pix_op = s->dsp.avg_pixels_tab; + } }else{ - offset=(s->picture_structure == PICT_BOTTOM_FIELD)? - s->linesize : 0; - - //put field from the same parity - //same parity is never in the same frame - mpeg_motion(s, dest_y, dest_cb, dest_cr, 0, - ref_picture,offset, - 0,dmv_pix_op, - s->mv[dir][0][0],s->mv[dir][0][1],16); - - // after put we make avg of the same block - dmv_pix_op=s->dsp.avg_pixels_tab; - - //opposite parity is always in the same frame if this is second field - if(!s->first_field){ - ref_picture = s->current_picture.data; - //top field is one linesize from frame beginig - offset=(s->picture_structure == PICT_BOTTOM_FIELD)? - -s->linesize : s->linesize; - }else - offset=(s->picture_structure == PICT_BOTTOM_FIELD)? - 0 : s->linesize; - - //avg field from the opposite parity - mpeg_motion(s, dest_y, dest_cb, dest_cr,0, - ref_picture, offset, - 0,dmv_pix_op, - s->mv[dir][2][0],s->mv[dir][2][1],16); + for(i=0; i<2; i++){ + mpeg_motion(s, dest_y, dest_cb, dest_cr, + 0, 0, s->picture_structure != i+1, + ref_picture, pix_op, + s->mv[dir][2*i][0],s->mv[dir][2*i][1],16); + + // after put we make avg of the same block + pix_op=s->dsp.avg_pixels_tab; + + //opposite parity is always in the same frame if this is second field + if(!s->first_field){ + ref_picture = s->current_picture_ptr->data; + } + } } - } break; default: assert(0); } @@ -2968,6 +3045,15 @@ void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) mb_x = s->mb_x; mb_y = s->mb_y; + if(s->avctx->debug&FF_DEBUG_DCT_COEFF) { + /* save DCT coefficients */ + int i,j; + DCTELEM *dct = &s->current_picture.dct_coeff[mb_xy*64*6]; + for(i=0; i<6; i++) + for(j=0; j<64; j++) + *dct++ = block[i][s->dsp.idct_permutation[j]]; + } + s->current_picture.qscale_table[mb_xy]= s->qscale; /* update DC predictors for P macroblocks */ @@ -3032,9 +3118,9 @@ void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) dest_cb= s->dest[1]; dest_cr= s->dest[2]; }else{ - dest_y = s->edge_emu_buffer+32; //FIXME cleanup scratchpad pointers - dest_cb= s->edge_emu_buffer+48; - dest_cr= s->edge_emu_buffer+56; + dest_y = s->b_scratchpad; + dest_cb= s->b_scratchpad+16*linesize; + dest_cr= s->b_scratchpad+16*linesize+8; } if (!s->mb_intra) { /* motion handling */ @@ -3121,7 +3207,7 @@ void MPV_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) } } -#if defined(CONFIG_ENCODERS) || defined(XINE_MPEG_ENCODER) +#ifdef CONFIG_ENCODERS static inline void dct_single_coeff_elimination(MpegEncContext *s, int n, int threshold) { @@ -3270,15 +3356,43 @@ void ff_init_block_index(MpegEncContext *s){ //FIXME maybe rename } } -#if defined(CONFIG_ENCODERS) || defined(XINE_MPEG_ENCODER) +#ifdef CONFIG_ENCODERS + +static void get_vissual_weight(int16_t *weight, uint8_t *ptr, int stride){ + int x, y; +//FIXME optimize + for(y=0; y<8; y++){ + for(x=0; x<8; x++){ + int x2, y2; + int sum=0; + int sqr=0; + int count=0; + + for(y2= FFMAX(y-1, 0); y2 < FFMIN(8, y+2); y2++){ + for(x2= FFMAX(x-1, 0); x2 < FFMIN(8, x+2); x2++){ + int v= ptr[x2 + y2*stride]; + sum += v; + sqr += v*v; + count++; + } + } + weight[x + 8*y]= (36*ff_sqrt(count*sqr - sum*sum)) / count; + } + } +} static void encode_mb(MpegEncContext *s, int motion_x, int motion_y) { + int16_t weight[6][64]; + DCTELEM orig[6][64]; const int mb_x= s->mb_x; const int mb_y= s->mb_y; int i; int skip_dct[6]; int dct_offset = s->linesize*8; //default for progressive frames + uint8_t *ptr_y, *ptr_cb, *ptr_cr; + int wrap_y, wrap_c; + int emu=0; for(i=0; i<6; i++) skip_dct[i]=0; @@ -3292,43 +3406,52 @@ static void encode_mb(MpegEncContext *s, int motion_x, int motion_y) if(!(s->flags&CODEC_FLAG_QP_RD)){ s->dquant= s->qscale - last_qp; - if(s->out_format==FMT_H263) + if(s->out_format==FMT_H263){ s->dquant= clip(s->dquant, -2, 2); //FIXME RD - if(s->codec_id==CODEC_ID_MPEG4){ - if(!s->mb_intra){ - if((s->mv_dir&MV_DIRECT) || s->mv_type==MV_TYPE_8X8) - s->dquant=0; + if(s->codec_id==CODEC_ID_MPEG4){ + if(!s->mb_intra){ + if(s->pict_type == B_TYPE){ + if(s->dquant&1) + s->dquant= (s->dquant/2)*2; + if(s->mv_dir&MV_DIRECT) + s->dquant= 0; + } + if(s->mv_type==MV_TYPE_8X8) + s->dquant=0; + } } } } ff_set_qscale(s, last_qp + s->dquant); } - if (s->mb_intra) { - uint8_t *ptr; - int wrap_y; - int emu=0; + wrap_y = s->linesize; + wrap_c = s->uvlinesize; + ptr_y = s->new_picture.data[0] + (mb_y * 16 * wrap_y) + mb_x * 16; + ptr_cb = s->new_picture.data[1] + (mb_y * 8 * wrap_c) + mb_x * 8; + ptr_cr = s->new_picture.data[2] + (mb_y * 8 * wrap_c) + mb_x * 8; - wrap_y = s->linesize; - ptr = s->new_picture.data[0] + (mb_y * 16 * wrap_y) + mb_x * 16; + if(mb_x*16+16 > s->width || mb_y*16+16 > s->height){ + ff_emulated_edge_mc(s->edge_emu_buffer , ptr_y , wrap_y,16,16,mb_x*16,mb_y*16, s->width , s->height); + ptr_y= s->edge_emu_buffer; + ff_emulated_edge_mc(s->edge_emu_buffer+18*wrap_y , ptr_cb, wrap_c, 8, 8, mb_x*8, mb_y*8, s->width>>1, s->height>>1); + ptr_cb= s->edge_emu_buffer+18*wrap_y; + ff_emulated_edge_mc(s->edge_emu_buffer+18*wrap_y+9, ptr_cr, wrap_c, 8, 8, mb_x*8, mb_y*8, s->width>>1, s->height>>1); + ptr_cr= s->edge_emu_buffer+18*wrap_y+9; + } - if(mb_x*16+16 > s->width || mb_y*16+16 > s->height){ - ff_emulated_edge_mc(s->edge_emu_buffer, ptr, wrap_y, 16, 16, mb_x*16, mb_y*16, s->width, s->height); - ptr= s->edge_emu_buffer; - emu=1; - } - + if (s->mb_intra) { if(s->flags&CODEC_FLAG_INTERLACED_DCT){ int progressive_score, interlaced_score; s->interlaced_dct=0; - progressive_score= s->dsp.ildct_cmp[4](s, ptr , NULL, wrap_y, 8) - +s->dsp.ildct_cmp[4](s, ptr + wrap_y*8, NULL, wrap_y, 8) - 400; + progressive_score= s->dsp.ildct_cmp[4](s, ptr_y , NULL, wrap_y, 8) + +s->dsp.ildct_cmp[4](s, ptr_y + wrap_y*8, NULL, wrap_y, 8) - 400; if(progressive_score > 0){ - interlaced_score = s->dsp.ildct_cmp[4](s, ptr , NULL, wrap_y*2, 8) - +s->dsp.ildct_cmp[4](s, ptr + wrap_y , NULL, wrap_y*2, 8); + interlaced_score = s->dsp.ildct_cmp[4](s, ptr_y , NULL, wrap_y*2, 8) + +s->dsp.ildct_cmp[4](s, ptr_y + wrap_y , NULL, wrap_y*2, 8); if(progressive_score > interlaced_score){ s->interlaced_dct=1; @@ -3338,46 +3461,26 @@ static void encode_mb(MpegEncContext *s, int motion_x, int motion_y) } } - s->dsp.get_pixels(s->block[0], ptr , wrap_y); - s->dsp.get_pixels(s->block[1], ptr + 8, wrap_y); - s->dsp.get_pixels(s->block[2], ptr + dct_offset , wrap_y); - s->dsp.get_pixels(s->block[3], ptr + dct_offset + 8, wrap_y); + s->dsp.get_pixels(s->block[0], ptr_y , wrap_y); + s->dsp.get_pixels(s->block[1], ptr_y + 8, wrap_y); + s->dsp.get_pixels(s->block[2], ptr_y + dct_offset , wrap_y); + s->dsp.get_pixels(s->block[3], ptr_y + dct_offset + 8, wrap_y); if(s->flags&CODEC_FLAG_GRAY){ skip_dct[4]= 1; skip_dct[5]= 1; }else{ - int wrap_c = s->uvlinesize; - ptr = s->new_picture.data[1] + (mb_y * 8 * wrap_c) + mb_x * 8; - if(emu){ - ff_emulated_edge_mc(s->edge_emu_buffer, ptr, wrap_c, 8, 8, mb_x*8, mb_y*8, s->width>>1, s->height>>1); - ptr= s->edge_emu_buffer; - } - s->dsp.get_pixels(s->block[4], ptr, wrap_c); - - ptr = s->new_picture.data[2] + (mb_y * 8 * wrap_c) + mb_x * 8; - if(emu){ - ff_emulated_edge_mc(s->edge_emu_buffer, ptr, wrap_c, 8, 8, mb_x*8, mb_y*8, s->width>>1, s->height>>1); - ptr= s->edge_emu_buffer; - } - s->dsp.get_pixels(s->block[5], ptr, wrap_c); + s->dsp.get_pixels(s->block[4], ptr_cb, wrap_c); + s->dsp.get_pixels(s->block[5], ptr_cr, wrap_c); } }else{ op_pixels_func (*op_pix)[4]; qpel_mc_func (*op_qpix)[16]; uint8_t *dest_y, *dest_cb, *dest_cr; - uint8_t *ptr_y, *ptr_cb, *ptr_cr; - int wrap_y, wrap_c; - int emu=0; dest_y = s->dest[0]; dest_cb = s->dest[1]; dest_cr = s->dest[2]; - wrap_y = s->linesize; - wrap_c = s->uvlinesize; - ptr_y = s->new_picture.data[0] + (mb_y * 16 * wrap_y) + mb_x * 16; - ptr_cb = s->new_picture.data[1] + (mb_y * 8 * wrap_c) + mb_x * 8; - ptr_cr = s->new_picture.data[2] + (mb_y * 8 * wrap_c) + mb_x * 8; if ((!s->no_rounding) || s->pict_type==B_TYPE){ op_pix = s->dsp.put_pixels_tab; @@ -3396,12 +3499,6 @@ static void encode_mb(MpegEncContext *s, int motion_x, int motion_y) MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture.data, op_pix, op_qpix); } - if(mb_x*16+16 > s->width || mb_y*16+16 > s->height){ - ff_emulated_edge_mc(s->edge_emu_buffer, ptr_y, wrap_y, 16, 16, mb_x*16, mb_y*16, s->width, s->height); - ptr_y= s->edge_emu_buffer; - emu=1; - } - if(s->flags&CODEC_FLAG_INTERLACED_DCT){ int progressive_score, interlaced_score; @@ -3433,15 +3530,7 @@ static void encode_mb(MpegEncContext *s, int motion_x, int motion_y) skip_dct[4]= 1; skip_dct[5]= 1; }else{ - if(emu){ - ff_emulated_edge_mc(s->edge_emu_buffer, ptr_cb, wrap_c, 8, 8, mb_x*8, mb_y*8, s->width>>1, s->height>>1); - ptr_cb= s->edge_emu_buffer; - } s->dsp.diff_pixels(s->block[4], ptr_cb, dest_cb, wrap_c); - if(emu){ - ff_emulated_edge_mc(s->edge_emu_buffer, ptr_cr, wrap_c, 8, 8, mb_x*8, mb_y*8, s->width>>1, s->height>>1); - ptr_cr= s->edge_emu_buffer; - } s->dsp.diff_pixels(s->block[5], ptr_cr, dest_cr, wrap_c); } /* pre quantization */ @@ -3453,33 +3542,22 @@ static void encode_mb(MpegEncContext *s, int motion_x, int motion_y) if(s->dsp.sad[1](NULL, ptr_y +dct_offset+ 8, dest_y +dct_offset+ 8, wrap_y, 8) < 20*s->qscale) skip_dct[3]= 1; if(s->dsp.sad[1](NULL, ptr_cb , dest_cb , wrap_c, 8) < 20*s->qscale) skip_dct[4]= 1; if(s->dsp.sad[1](NULL, ptr_cr , dest_cr , wrap_c, 8) < 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(s->avctx->quantizer_noise_shaping){ + if(!skip_dct[0]) get_vissual_weight(weight[0], ptr_y , wrap_y); + if(!skip_dct[1]) get_vissual_weight(weight[1], ptr_y + 8, wrap_y); + if(!skip_dct[2]) get_vissual_weight(weight[2], ptr_y + dct_offset , wrap_y); + if(!skip_dct[3]) get_vissual_weight(weight[3], ptr_y + dct_offset + 8, wrap_y); + if(!skip_dct[4]) get_vissual_weight(weight[4], ptr_cb , wrap_c); + if(!skip_dct[5]) get_vissual_weight(weight[5], ptr_cr , wrap_c); + memcpy(orig[0], s->block[0], sizeof(DCTELEM)*64*6); } /* DCT & quantize */ - if(s->out_format==FMT_MJPEG){ - for(i=0;i<6;i++) { - int overflow; - s->block_last_index[i] = s->dct_quantize(s, s->block[i], i, 8, &overflow); - if (overflow) clip_coeffs(s, s->block[i], s->block_last_index[i]); - } - }else{ + assert(s->out_format!=FMT_MJPEG || s->qscale==8); + { for(i=0;i<6;i++) { if(!skip_dct[i]){ int overflow; @@ -3491,6 +3569,13 @@ static void encode_mb(MpegEncContext *s, int motion_x, int motion_y) }else s->block_last_index[i]= -1; } + if(s->avctx->quantizer_noise_shaping){ + for(i=0;i<6;i++) { + if(!skip_dct[i]){ + s->block_last_index[i] = dct_quantize_refine(s, s->block[i], weight[i], orig[i], i, s->qscale); + } + } + } if(s->luma_elim_threshold && !s->mb_intra) for(i=0; i<4; i++) @@ -3532,7 +3617,8 @@ static void encode_mb(MpegEncContext *s, int motion_x, int motion_y) case CODEC_ID_MPEG1VIDEO: case CODEC_ID_MPEG2VIDEO: mpeg1_encode_mb(s, s->block, motion_x, motion_y); break; -#if defined(CONFIG_ENCODERS) || !defined(XINE_MPEG_ENCODER) +/* xine: do not need this for decode or MPEG-1 encoding modes */ +#if 0 #ifdef CONFIG_RISKY case CODEC_ID_MPEG4: mpeg4_encode_mb(s, s->block, motion_x, motion_y); break; @@ -3550,7 +3636,7 @@ static void encode_mb(MpegEncContext *s, int motion_x, int motion_y) #endif case CODEC_ID_MJPEG: mjpeg_encode_mb(s, s->block); break; -#endif +#endif /* #if 0 */ default: assert(0); } @@ -3636,19 +3722,32 @@ void ff_mpeg_flush(AVCodecContext *avctx){ s->parse_context.overread_index= 0; s->parse_context.index= 0; s->parse_context.last_index= 0; + s->bitstream_buffer_size=0; } -#if defined(CONFIG_ENCODERS) || defined(XINE_MPEG_ENCODER) +#ifdef CONFIG_ENCODERS void ff_copy_bits(PutBitContext *pb, uint8_t *src, int length) { - int bytes= length>>4; + const uint16_t *srcw= (uint16_t*)src; + int words= 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)); + + if(words < 16){ + for(i=0; i<words; i++) put_bits(pb, 16, be2me_16(srcw[i])); + }else if(put_bits_count(pb)&7){ + for(i=0; i<words; i++) put_bits(pb, 16, be2me_16(srcw[i])); + }else{ + for(i=0; put_bits_count(pb)&31; i++) + put_bits(pb, 8, src[i]); + flush_put_bits(pb); + memcpy(pbBufPtr(pb), src+i, 2*words-i); + skip_put_bytes(pb, 2*words-i); + } + + put_bits(pb, bits, be2me_16(srcw[words])>>(16-bits)); } static inline void copy_context_before_encode(MpegEncContext *d, MpegEncContext *s, int type){ @@ -3732,19 +3831,18 @@ static inline void encode_mb_hq(MpegEncContext *s, MpegEncContext *backup, MpegE if(*next_block){ memcpy(dest_backup, s->dest, sizeof(s->dest)); - s->dest[0] = s->me.scratchpad; - s->dest[1] = s->me.scratchpad + 16; - s->dest[2] = s->me.scratchpad + 16 + 8; - assert(2*s->uvlinesize == s->linesize); //should be no prob for encoding - assert(s->linesize >= 64); //FIXME + s->dest[0] = s->rd_scratchpad; + s->dest[1] = s->rd_scratchpad + 16*s->linesize; + s->dest[2] = s->rd_scratchpad + 16*s->linesize + 8; + assert(s->linesize >= 32); //FIXME } encode_mb(s, motion_x, motion_y); - score= get_bit_count(&s->pb); + score= put_bits_count(&s->pb); if(s->data_partitioning){ - score+= get_bit_count(&s->pb2); - score+= get_bit_count(&s->tex_pb); + score+= put_bits_count(&s->pb2); + score+= put_bits_count(&s->tex_pb); } if(s->avctx->mb_decision == FF_MB_DECISION_RD){ @@ -3804,270 +3902,108 @@ static int sse_mb(MpegEncContext *s){ +sse(s, s->new_picture.data[2] + s->mb_x*8 + s->mb_y*s->uvlinesize*8,s->dest[2], w>>1, h>>1, s->uvlinesize); } -static void encode_picture(MpegEncContext *s, int picture_number) -{ - int mb_x, mb_y, pdif = 0; - int i, j; - int bits; - MpegEncContext best_s, backup_s; - uint8_t bit_buf[2][3000]; - uint8_t bit_buf2[2][3000]; - uint8_t bit_buf_tex[2][3000]; - PutBitContext pb[2], pb2[2], tex_pb[2]; +static int pre_estimate_motion_thread(AVCodecContext *c, void *arg){ + MpegEncContext *s= arg; - for(i=0; i<2; i++){ - init_put_bits(&pb [i], bit_buf [i], 3000); - init_put_bits(&pb2 [i], bit_buf2 [i], 3000); - init_put_bits(&tex_pb[i], bit_buf_tex[i], 3000); - } - - s->picture_number = picture_number; - - /* Reset the average MB variance */ - s->current_picture.mb_var_sum = 0; - s->current_picture.mc_mb_var_sum = 0; - -#if defined(CONFIG_ENCODERS) || !defined(XINE_MPEG_ENCODER) -#ifdef CONFIG_RISKY - /* we need to initialize some time vars before we can encode b-frames */ - // RAL: Condition added for MPEG1VIDEO - if (s->codec_id == CODEC_ID_MPEG1VIDEO || s->codec_id == CODEC_ID_MPEG2VIDEO || (s->h263_pred && !s->h263_msmpeg4)) - ff_set_mpeg4_time(s, s->picture_number); -#endif -#endif - - s->scene_change_score=0; - s->lambda= s->current_picture_ptr->quality; //FIXME qscale / ... stuff for ME ratedistoration - - if(s->pict_type==I_TYPE){ - if(s->msmpeg4_version >= 3) s->no_rounding=1; - else s->no_rounding=0; - }else if(s->pict_type!=B_TYPE){ - if(s->flipflop_rounding || s->codec_id == CODEC_ID_H263P || s->codec_id == CODEC_ID_MPEG4) - s->no_rounding ^= 1; - } - - /* Estimate motion for every MB */ - s->mb_intra=0; //for the rate distoration & bit compare functions - if(s->pict_type != I_TYPE){ -#if defined(CONFIG_ENCODERS) || !defined(XINE_MPEG_ENCODER) - if(s->pict_type != B_TYPE){ - if((s->avctx->pre_me && s->last_non_b_pict_type==I_TYPE) || s->avctx->pre_me==2){ - s->me.pre_pass=1; - s->me.dia_size= s->avctx->pre_dia_size; - - for(mb_y=s->mb_height-1; mb_y >=0 ; mb_y--) { - s->mb_y = mb_y; - for(mb_x=s->mb_width-1; mb_x >=0 ; mb_x--) { - s->mb_x = mb_x; - ff_pre_estimate_p_frame_motion(s, mb_x, mb_y); - } - } - s->me.pre_pass=0; - } - } - - s->me.dia_size= s->avctx->dia_size; - for(mb_y=0; mb_y < s->mb_height; mb_y++) { - s->mb_y = 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); - s->block_index[2]= s->block_wrap[0]*(mb_y*2 + 2) - 1; - s->block_index[3]= s->block_wrap[0]*(mb_y*2 + 2); - for(mb_x=0; mb_x < s->mb_width; mb_x++) { - s->mb_x = mb_x; - s->block_index[0]+=2; - s->block_index[1]+=2; - s->block_index[2]+=2; - s->block_index[3]+=2; - - /* compute motion vector & mb_type and store in context */ - 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); - } - } -#endif - }else /* if(s->pict_type == I_TYPE) */{ - /* I-Frame */ - for(i=0; i<s->mb_stride*s->mb_height; i++) - s->mb_type[i]= CANDIDATE_MB_TYPE_INTRA; - - if(!s->fixed_qscale){ - /* finding spatial complexity for I-frame rate control */ - for(mb_y=0; mb_y < s->mb_height; mb_y++) { - for(mb_x=0; mb_x < s->mb_width; mb_x++) { - int xx = mb_x * 16; - int yy = mb_y * 16; - uint8_t *pix = s->new_picture.data[0] + (yy * s->linesize) + xx; - int varc; - int sum = s->dsp.pix_sum(pix, s->linesize); - - varc = (s->dsp.pix_norm1(pix, s->linesize) - (((unsigned)(sum*sum))>>8) + 500 + 128)>>8; - - s->current_picture.mb_var [s->mb_stride * mb_y + mb_x] = varc; - s->current_picture.mb_mean[s->mb_stride * mb_y + mb_x] = (sum+128)>>8; - s->current_picture.mb_var_sum += varc; - } - } + s->me.pre_pass=1; + s->me.dia_size= s->avctx->pre_dia_size; + s->first_slice_line=1; + for(s->mb_y= s->end_mb_y-1; s->mb_y >= s->start_mb_y; s->mb_y--) { + for(s->mb_x=s->mb_width-1; s->mb_x >=0 ;s->mb_x--) { + ff_pre_estimate_p_frame_motion(s, s->mb_x, s->mb_y); } + s->first_slice_line=0; } - emms_c(); - - if(s->scene_change_score > s->avctx->scenechange_threshold && s->pict_type == P_TYPE){ - s->pict_type= I_TYPE; - for(i=0; i<s->mb_stride*s->mb_height; i++) - s->mb_type[i]= CANDIDATE_MB_TYPE_INTRA; -//printf("Scene change detected, encoding as I Frame %d %d\n", s->current_picture.mb_var_sum, s->current_picture.mc_mb_var_sum); - } + + s->me.pre_pass=0; + + return 0; +} -#if defined(CONFIG_ENCODERS) || !defined(XINE_MPEG_ENCODER) - if(!s->umvplus){ - if(s->pict_type==P_TYPE || s->pict_type==S_TYPE) { - s->f_code= ff_get_best_fcode(s, s->p_mv_table, CANDIDATE_MB_TYPE_INTER); +static int estimate_motion_thread(AVCodecContext *c, void *arg){ + MpegEncContext *s= arg; - if(s->flags & CODEC_FLAG_INTERLACED_ME){ - int a,b; - a= ff_get_best_fcode(s, s->p_field_mv_table[0][0], CANDIDATE_MB_TYPE_INTER_I); //FIXME field_select - b= ff_get_best_fcode(s, s->p_field_mv_table[1][1], CANDIDATE_MB_TYPE_INTER_I); - s->f_code= FFMAX(s->f_code, FFMAX(a,b)); - } - - ff_fix_long_p_mvs(s); - ff_fix_long_mvs(s, NULL, 0, s->p_mv_table, s->f_code, CANDIDATE_MB_TYPE_INTER, 0); - if(s->flags & CODEC_FLAG_INTERLACED_ME){ - for(i=0; i<2; i++){ - for(j=0; j<2; j++) - ff_fix_long_mvs(s, s->p_field_select_table[i], j, - s->p_field_mv_table[i][j], s->f_code, CANDIDATE_MB_TYPE_INTER_I, 0); - } - } + s->me.dia_size= s->avctx->dia_size; + s->first_slice_line=1; + for(s->mb_y= s->start_mb_y; s->mb_y < s->end_mb_y; s->mb_y++) { + s->mb_x=0; //for block init below + ff_init_block_index(s); + for(s->mb_x=0; s->mb_x < s->mb_width; s->mb_x++) { + s->block_index[0]+=2; + s->block_index[1]+=2; + s->block_index[2]+=2; + s->block_index[3]+=2; + + /* compute motion vector & mb_type and store in context */ + if(s->pict_type==B_TYPE) + ff_estimate_b_frame_motion(s, s->mb_x, s->mb_y); + else + ff_estimate_p_frame_motion(s, s->mb_x, s->mb_y); } + s->first_slice_line=0; + } + return 0; +} - if(s->pict_type==B_TYPE){ - int a, b; - - a = ff_get_best_fcode(s, s->b_forw_mv_table, CANDIDATE_MB_TYPE_FORWARD); - b = ff_get_best_fcode(s, s->b_bidir_forw_mv_table, CANDIDATE_MB_TYPE_BIDIR); - s->f_code = FFMAX(a, b); +static int mb_var_thread(AVCodecContext *c, void *arg){ + MpegEncContext *s= arg; + int mb_x, mb_y; - a = ff_get_best_fcode(s, s->b_back_mv_table, CANDIDATE_MB_TYPE_BACKWARD); - b = ff_get_best_fcode(s, s->b_bidir_back_mv_table, CANDIDATE_MB_TYPE_BIDIR); - s->b_code = FFMAX(a, b); + for(mb_y=s->start_mb_y; mb_y < s->end_mb_y; mb_y++) { + for(mb_x=0; mb_x < s->mb_width; mb_x++) { + int xx = mb_x * 16; + int yy = mb_y * 16; + uint8_t *pix = s->new_picture.data[0] + (yy * s->linesize) + xx; + int varc; + int sum = s->dsp.pix_sum(pix, s->linesize); + + varc = (s->dsp.pix_norm1(pix, s->linesize) - (((unsigned)(sum*sum))>>8) + 500 + 128)>>8; - ff_fix_long_mvs(s, NULL, 0, s->b_forw_mv_table, s->f_code, CANDIDATE_MB_TYPE_FORWARD, 1); - ff_fix_long_mvs(s, NULL, 0, s->b_back_mv_table, s->b_code, CANDIDATE_MB_TYPE_BACKWARD, 1); - ff_fix_long_mvs(s, NULL, 0, s->b_bidir_forw_mv_table, s->f_code, CANDIDATE_MB_TYPE_BIDIR, 1); - ff_fix_long_mvs(s, NULL, 0, s->b_bidir_back_mv_table, s->b_code, CANDIDATE_MB_TYPE_BIDIR, 1); - if(s->flags & CODEC_FLAG_INTERLACED_ME){ - int dir; - for(dir=0; dir<2; dir++){ - for(i=0; i<2; i++){ - for(j=0; j<2; j++){ - int type= dir ? (CANDIDATE_MB_TYPE_BACKWARD_I|CANDIDATE_MB_TYPE_BIDIR_I) - : (CANDIDATE_MB_TYPE_FORWARD_I |CANDIDATE_MB_TYPE_BIDIR_I); - ff_fix_long_mvs(s, s->b_field_select_table[dir][i], j, - s->b_field_mv_table[dir][i][j], dir ? s->b_code : s->f_code, type, 1); - } - } - } - } + s->current_picture.mb_var [s->mb_stride * mb_y + mb_x] = varc; + s->current_picture.mb_mean[s->mb_stride * mb_y + mb_x] = (sum+128)>>8; + s->mb_var_sum_temp += varc; } } -#endif - - if (!s->fixed_qscale) - s->current_picture.quality = ff_rate_estimate_qscale(s); + return 0; +} - if(s->adaptive_quant){ -#if defined(CONFIG_ENCODERS) || !defined(XINE_MPEG_ENCODER) -#ifdef CONFIG_RISKY - switch(s->codec_id){ - case CODEC_ID_MPEG4: - ff_clean_mpeg4_qscales(s); - break; - case CODEC_ID_H263: - case CODEC_ID_H263P: - case CODEC_ID_FLV1: - ff_clean_h263_qscales(s); - break; +static void write_slice_end(MpegEncContext *s){ +/* xine: do not need this for decode or MPEG-1 encoding modes */ +#if 0 + if(s->codec_id==CODEC_ID_MPEG4){ + if(s->partitioned_frame){ + ff_mpeg4_merge_partitions(s); } -#endif -#endif - - s->lambda= s->lambda_table[0]; - //FIXME broken - }else - s->lambda= s->current_picture.quality; -//printf("%d %d\n", s->avctx->global_quality, s->current_picture.quality); - update_qscale(s); - if(s->qscale < 3 && s->max_qcoeff<=128 && s->pict_type==I_TYPE && !(s->flags & CODEC_FLAG_QSCALE)) - s->qscale= 3; //reduce cliping problems - - if (s->out_format == FMT_MJPEG) { - /* for mjpeg, we do include qscale in the matrix */ - s->intra_matrix[0] = ff_mpeg1_default_intra_matrix[0]; - for(i=1;i<64;i++){ - int j= s->dsp.idct_permutation[i]; - - s->intra_matrix[j] = CLAMP_TO_8BIT((ff_mpeg1_default_intra_matrix[i] * s->qscale) >> 3); - } - convert_matrix(&s->dsp, s->q_intra_matrix, s->q_intra_matrix16, - s->intra_matrix, s->intra_quant_bias, 8, 8); + ff_mpeg4_stuffing(&s->pb); + }else if(s->out_format == FMT_MJPEG){ + ff_mjpeg_stuffing(&s->pb); } - - //FIXME var duplication - s->current_picture.key_frame= s->pict_type == I_TYPE; - s->current_picture.pict_type= s->pict_type; +#endif /* #if 0 */ - if(s->current_picture.key_frame) - s->picture_in_gop_number=0; + align_put_bits(&s->pb); + flush_put_bits(&s->pb); +} - s->last_bits= get_bit_count(&s->pb); - switch(s->out_format) { -#if defined(CONFIG_ENCODERS) || !defined(XINE_MPEG_ENCODER) - case FMT_MJPEG: - mjpeg_picture_header(s); - break; -#ifdef CONFIG_RISKY - case FMT_H263: - if (s->codec_id == CODEC_ID_WMV2) - ff_wmv2_encode_picture_header(s, picture_number); - else if (s->h263_msmpeg4) - msmpeg4_encode_picture_header(s, picture_number); - else if (s->h263_pred) - mpeg4_encode_picture_header(s, picture_number); - else if (s->codec_id == CODEC_ID_RV10) - rv10_encode_picture_header(s, picture_number); - else if (s->codec_id == CODEC_ID_FLV1) - ff_flv_encode_picture_header(s, picture_number); - else - h263_encode_picture_header(s, picture_number); - break; -#else - case FMT_H263: - break; -#endif -#else - case FMT_MJPEG: - break; - case FMT_H263: - break; -#endif - case FMT_MPEG1: - mpeg1_encode_picture_header(s, picture_number); - break; - case FMT_H264: - break; - default: - assert(0); +static int encode_thread(AVCodecContext *c, void *arg){ + MpegEncContext *s= arg; + int mb_x, mb_y, pdif = 0; + int i, j; + MpegEncContext best_s, backup_s; + uint8_t bit_buf[2][3000]; + uint8_t bit_buf2[2][3000]; + uint8_t bit_buf_tex[2][3000]; + PutBitContext pb[2], pb2[2], tex_pb[2]; +//printf("%d->%d\n", s->resync_mb_y, s->end_mb_y); + + for(i=0; i<2; i++){ + init_put_bits(&pb [i], bit_buf [i], 3000); + init_put_bits(&pb2 [i], bit_buf2 [i], 3000); + init_put_bits(&tex_pb[i], bit_buf_tex[i], 3000); } - bits= get_bit_count(&s->pb); - s->header_bits= bits - s->last_bits; - s->last_bits= bits; + + s->last_bits= put_bits_count(&s->pb); s->mv_bits=0; s->misc_bits=0; s->i_tex_bits=0; @@ -4089,7 +4025,6 @@ static void encode_picture(MpegEncContext *s, int picture_number) s->last_mv_dir = 0; -#if defined(CONFIG_ENCODERS) || !defined(XINE_MPEG_ENCODER) #ifdef CONFIG_RISKY switch(s->codec_id){ case CODEC_ID_H263: @@ -4097,19 +4032,22 @@ static void encode_picture(MpegEncContext *s, int picture_number) case CODEC_ID_FLV1: s->gob_index = ff_h263_get_gob_height(s); break; +/* xine: do not need this for decode or MPEG-1 encoding modes */ +#if 0 case CODEC_ID_MPEG4: if(s->partitioned_frame) ff_mpeg4_init_partitions(s); break; +#endif /* #if 0 */ } #endif -#endif s->resync_mb_x=0; - s->resync_mb_y=0; + s->resync_mb_y=0; s->first_slice_line = 1; s->ptr_lastgob = s->pb.buf; - for(mb_y=0; mb_y < s->mb_height; mb_y++) { + for(mb_y= s->start_mb_y; mb_y < s->end_mb_y; mb_y++) { +// printf("row %d at %X\n", s->mb_y, (int)s); s->mb_x=0; s->mb_y= mb_y; @@ -4127,15 +4065,18 @@ static void encode_picture(MpegEncContext *s, int picture_number) ff_update_block_index(s); /* write gob / video packet header */ -#if defined(CONFIG_ENCODERS) || !defined(XINE_MPEG_ENCODER) +/* xine: do not need this for decode or MPEG-1 encoding modes */ +#if 0 #ifdef CONFIG_RISKY if(s->rtp_mode){ int current_packet_size, is_gob_start; - current_packet_size= pbBufPtr(&s->pb) - s->ptr_lastgob; + current_packet_size= ((put_bits_count(&s->pb)+7)>>3) - (s->ptr_lastgob - s->pb.buf); is_gob_start= s->avctx->rtp_payload_size && current_packet_size >= s->avctx->rtp_payload_size && mb_y + mb_x>0; + if(s->start_mb_y == mb_y && mb_y > 0 && mb_x==0) is_gob_start=1; + switch(s->codec_id){ case CODEC_ID_H263: case CODEC_ID_H263P: @@ -4148,24 +4089,24 @@ static void encode_picture(MpegEncContext *s, int picture_number) if(s->mb_skip_run) is_gob_start=0; break; } - + if(is_gob_start){ - if(s->codec_id==CODEC_ID_MPEG4 && s->partitioned_frame){ - ff_mpeg4_merge_partitions(s); - ff_mpeg4_init_partitions(s); + if(s->start_mb_y != mb_y || mb_x!=0){ + write_slice_end(s); + +/* xine: do not need this for decode or MPEG-1 encoding modes */ +#if 0 + if(s->codec_id==CODEC_ID_MPEG4 && s->partitioned_frame){ + ff_mpeg4_init_partitions(s); + } +#endif /* #if 0 */ } - if(s->codec_id==CODEC_ID_MPEG4) - ff_mpeg4_stuffing(&s->pb); - - align_put_bits(&s->pb); - flush_put_bits(&s->pb); - - assert((get_bit_count(&s->pb)&7) == 0); + assert((put_bits_count(&s->pb)&7) == 0); current_packet_size= pbBufPtr(&s->pb) - s->ptr_lastgob; if(s->avctx->error_rate && s->resync_mb_x + s->resync_mb_y > 0){ - int r= get_bit_count(&s->pb)/8 + s->picture_number + s->codec_id + s->mb_x + s->mb_y; + int r= put_bits_count(&s->pb)/8 + s->picture_number + s->codec_id + s->mb_x + s->mb_y; int d= 100 / s->avctx->error_rate; if(r % d == 0){ current_packet_size=0; @@ -4196,7 +4137,7 @@ static void encode_picture(MpegEncContext *s, int picture_number) } if(s->flags&CODEC_FLAG_PASS1){ - int bits= get_bit_count(&s->pb); + int bits= put_bits_count(&s->pb); s->misc_bits+= bits - s->last_bits; s->last_bits= bits; } @@ -4208,7 +4149,8 @@ static void encode_picture(MpegEncContext *s, int picture_number) } } #endif -#endif +#endif /* #if 0 */ + if( (s->resync_mb_x == s->mb_x) && s->resync_mb_y+1 == s->mb_y){ @@ -4307,11 +4249,12 @@ static void encode_picture(MpegEncContext *s, int picture_number) s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD | MV_DIRECT; s->mb_intra= 0; -#if defined(CONFIG_ENCODERS) || !defined(XINE_MPEG_ENCODER) +/* xine: do not need this for decode or MPEG-1 encoding modes */ +#if 0 #ifdef CONFIG_RISKY ff_mpeg4_set_direct_mv(s, mx, my); #endif -#endif +#endif /* #if 0 */ encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_DIRECT, pb, pb2, tex_pb, &dmin, &next_block, mx, my); } @@ -4424,33 +4367,33 @@ static void encode_picture(MpegEncContext *s, int picture_number) copy_context_after_encode(s, &best_s, -1); - pb_bits_count= get_bit_count(&s->pb); + pb_bits_count= put_bits_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); + pb2_bits_count= put_bits_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); + tex_pb_bits_count= put_bits_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->last_bits= get_bit_count(&s->pb); + s->last_bits= put_bits_count(&s->pb); #ifdef CONFIG_RISKY if (s->out_format == FMT_H263 && s->pict_type!=B_TYPE) ff_h263_update_motion_val(s); #endif - if(next_block==0){ - s->dsp.put_pixels_tab[0][0](s->dest[0], s->me.scratchpad , s->linesize ,16); - s->dsp.put_pixels_tab[1][0](s->dest[1], s->me.scratchpad + 16, s->uvlinesize, 8); - s->dsp.put_pixels_tab[1][0](s->dest[2], s->me.scratchpad + 24, s->uvlinesize, 8); + if(next_block==0){ //FIXME 16 vs linesize16 + s->dsp.put_pixels_tab[0][0](s->dest[0], s->rd_scratchpad , s->linesize ,16); + s->dsp.put_pixels_tab[1][0](s->dest[1], s->rd_scratchpad + 16*s->linesize , s->uvlinesize, 8); + s->dsp.put_pixels_tab[1][0](s->dest[2], s->rd_scratchpad + 16*s->linesize + 8, s->uvlinesize, 8); } if(s->avctx->mb_decision == FF_MB_DECISION_BITS) @@ -4499,11 +4442,12 @@ static void encode_picture(MpegEncContext *s, int picture_number) s->mb_intra= 0; motion_x=s->b_direct_mv_table[xy][0]; motion_y=s->b_direct_mv_table[xy][1]; -#if defined(CONFIG_ENCODERS) || !defined(XINE_MPEG_ENCODER) +/* xine: do not need this for decode or MPEG-1 encoding modes */ +#if 0 #ifdef CONFIG_RISKY ff_mpeg4_set_direct_mv(s, motion_x, motion_y); #endif -#endif +#endif /* #if 0 */ break; case CANDIDATE_MB_TYPE_BIDIR: s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD; @@ -4606,31 +4550,296 @@ static void encode_picture(MpegEncContext *s, int picture_number) } if(s->loop_filter) ff_h263_loop_filter(s); -//printf("MB %d %d bits\n", s->mb_x+s->mb_y*s->mb_stride, get_bit_count(&s->pb)); +//printf("MB %d %d bits\n", s->mb_x+s->mb_y*s->mb_stride, put_bits_count(&s->pb)); } } - emms_c(); -#if defined(CONFIG_ENCODERS) || !defined(XINE_MPEG_ENCODER) +/* xine: do not need this for decode or MPEG-1 encoding modes */ +#if 0 #ifdef CONFIG_RISKY - if(s->codec_id==CODEC_ID_MPEG4 && s->partitioned_frame) - ff_mpeg4_merge_partitions(s); - + //not beautifull here but we must write it before flushing so it has to be here 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); -#endif #endif +#endif /* #if 0 */ + + write_slice_end(s); /* Send the last GOB if RTP */ if (s->avctx->rtp_callback) { - flush_put_bits(&s->pb); pdif = pbBufPtr(&s->pb) - s->ptr_lastgob; /* Call the RTP callback to send the last GOB */ + emms_c(); s->avctx->rtp_callback(s->ptr_lastgob, pdif, 0); } + + return 0; +} + +#define MERGE(field) dst->field += src->field; src->field=0 +static void merge_context_after_me(MpegEncContext *dst, MpegEncContext *src){ + MERGE(scene_change_score); + MERGE(mc_mb_var_sum_temp); + MERGE(mb_var_sum_temp); +} + +static void merge_context_after_encode(MpegEncContext *dst, MpegEncContext *src){ + int i; + + MERGE(dct_count[0]); //note, the other dct vars are not part of the context + MERGE(dct_count[1]); + MERGE(mv_bits); + MERGE(header_bits); + MERGE(i_tex_bits); + MERGE(p_tex_bits); + MERGE(i_count); + MERGE(f_count); + MERGE(b_count); + MERGE(skip_count); + MERGE(misc_bits); + MERGE(error_count); + MERGE(padding_bug_score); + + if(dst->avctx->noise_reduction){ + for(i=0; i<64; i++){ + MERGE(dct_error_sum[0][i]); + MERGE(dct_error_sum[1][i]); + } + } + + assert(put_bits_count(&src->pb) % 8 ==0); + assert(put_bits_count(&dst->pb) % 8 ==0); + ff_copy_bits(&dst->pb, src->pb.buf, put_bits_count(&src->pb)); + flush_put_bits(&dst->pb); +} + +static void encode_picture(MpegEncContext *s, int picture_number) +{ + int mb_x, mb_y; + int i, j; + int bits; + + s->picture_number = picture_number; + + /* Reset the average MB variance */ + s->mb_var_sum_temp = + s->mc_mb_var_sum_temp = 0; + +/* xine: do not need this for decode or MPEG-1 encoding modes */ +#if 0 +#ifdef CONFIG_RISKY + /* we need to initialize some time vars before we can encode b-frames */ + // RAL: Condition added for MPEG1VIDEO + if (s->codec_id == CODEC_ID_MPEG1VIDEO || s->codec_id == CODEC_ID_MPEG2VIDEO || (s->h263_pred && !s->h263_msmpeg4)) + ff_set_mpeg4_time(s, s->picture_number); //FIXME rename and use has_b_frames or similar +#endif +#endif /* #if 0 */ + + s->scene_change_score=0; + + s->lambda= s->current_picture_ptr->quality; //FIXME qscale / ... stuff for ME ratedistoration + + if(s->pict_type==I_TYPE){ + if(s->msmpeg4_version >= 3) s->no_rounding=1; + else s->no_rounding=0; + }else if(s->pict_type!=B_TYPE){ + if(s->flipflop_rounding || s->codec_id == CODEC_ID_H263P || s->codec_id == CODEC_ID_MPEG4) + s->no_rounding ^= 1; + } + + s->mb_intra=0; //for the rate distoration & bit compare functions + for(i=1; i<s->avctx->thread_count; i++){ + ff_update_duplicate_context(s->thread_context[i], s); + } + + /* Estimate motion for every MB */ + if(s->pict_type != I_TYPE){ +/* xine: do not need this for decode or MPEG-1 encoding modes */ +#if 0 + if(s->pict_type != B_TYPE){ + if((s->avctx->pre_me && s->last_non_b_pict_type==I_TYPE) || s->avctx->pre_me==2){ + s->avctx->execute(s->avctx, pre_estimate_motion_thread, (void**)&(s->thread_context[0]), NULL, s->avctx->thread_count); + } + } + + s->avctx->execute(s->avctx, estimate_motion_thread, (void**)&(s->thread_context[0]), NULL, s->avctx->thread_count); +#endif /* #if 0 */ + }else /* if(s->pict_type == I_TYPE) */{ + /* I-Frame */ + for(i=0; i<s->mb_stride*s->mb_height; i++) + s->mb_type[i]= CANDIDATE_MB_TYPE_INTRA; + + if(!s->fixed_qscale){ + /* finding spatial complexity for I-frame rate control */ + s->avctx->execute(s->avctx, mb_var_thread, (void**)&(s->thread_context[0]), NULL, s->avctx->thread_count); + } + } + for(i=1; i<s->avctx->thread_count; i++){ + merge_context_after_me(s, s->thread_context[i]); + } + s->current_picture.mc_mb_var_sum= s->current_picture_ptr->mc_mb_var_sum= s->mc_mb_var_sum_temp; + s->current_picture. mb_var_sum= s->current_picture_ptr-> mb_var_sum= s-> mb_var_sum_temp; + emms_c(); + + if(s->scene_change_score > s->avctx->scenechange_threshold && s->pict_type == P_TYPE){ + s->pict_type= I_TYPE; + for(i=0; i<s->mb_stride*s->mb_height; i++) + s->mb_type[i]= CANDIDATE_MB_TYPE_INTRA; +//printf("Scene change detected, encoding as I Frame %d %d\n", s->current_picture.mb_var_sum, s->current_picture.mc_mb_var_sum); + } + +/* xine: do not need this for decode or MPEG-1 encoding modes */ +#if 0 + if(!s->umvplus){ + if(s->pict_type==P_TYPE || s->pict_type==S_TYPE) { + s->f_code= ff_get_best_fcode(s, s->p_mv_table, CANDIDATE_MB_TYPE_INTER); + + if(s->flags & CODEC_FLAG_INTERLACED_ME){ + int a,b; + a= ff_get_best_fcode(s, s->p_field_mv_table[0][0], CANDIDATE_MB_TYPE_INTER_I); //FIXME field_select + b= ff_get_best_fcode(s, s->p_field_mv_table[1][1], CANDIDATE_MB_TYPE_INTER_I); + s->f_code= FFMAX(s->f_code, FFMAX(a,b)); + } + + ff_fix_long_p_mvs(s); + ff_fix_long_mvs(s, NULL, 0, s->p_mv_table, s->f_code, CANDIDATE_MB_TYPE_INTER, 0); + if(s->flags & CODEC_FLAG_INTERLACED_ME){ + for(i=0; i<2; i++){ + for(j=0; j<2; j++) + ff_fix_long_mvs(s, s->p_field_select_table[i], j, + s->p_field_mv_table[i][j], s->f_code, CANDIDATE_MB_TYPE_INTER_I, 0); + } + } + } + + if(s->pict_type==B_TYPE){ + int a, b; + + a = ff_get_best_fcode(s, s->b_forw_mv_table, CANDIDATE_MB_TYPE_FORWARD); + b = ff_get_best_fcode(s, s->b_bidir_forw_mv_table, CANDIDATE_MB_TYPE_BIDIR); + s->f_code = FFMAX(a, b); + + a = ff_get_best_fcode(s, s->b_back_mv_table, CANDIDATE_MB_TYPE_BACKWARD); + b = ff_get_best_fcode(s, s->b_bidir_back_mv_table, CANDIDATE_MB_TYPE_BIDIR); + s->b_code = FFMAX(a, b); + + ff_fix_long_mvs(s, NULL, 0, s->b_forw_mv_table, s->f_code, CANDIDATE_MB_TYPE_FORWARD, 1); + ff_fix_long_mvs(s, NULL, 0, s->b_back_mv_table, s->b_code, CANDIDATE_MB_TYPE_BACKWARD, 1); + ff_fix_long_mvs(s, NULL, 0, s->b_bidir_forw_mv_table, s->f_code, CANDIDATE_MB_TYPE_BIDIR, 1); + ff_fix_long_mvs(s, NULL, 0, s->b_bidir_back_mv_table, s->b_code, CANDIDATE_MB_TYPE_BIDIR, 1); + if(s->flags & CODEC_FLAG_INTERLACED_ME){ + int dir; + for(dir=0; dir<2; dir++){ + for(i=0; i<2; i++){ + for(j=0; j<2; j++){ + int type= dir ? (CANDIDATE_MB_TYPE_BACKWARD_I|CANDIDATE_MB_TYPE_BIDIR_I) + : (CANDIDATE_MB_TYPE_FORWARD_I |CANDIDATE_MB_TYPE_BIDIR_I); + ff_fix_long_mvs(s, s->b_field_select_table[dir][i], j, + s->b_field_mv_table[dir][i][j], dir ? s->b_code : s->f_code, type, 1); + } + } + } + } + } + } +#endif /* #if 0 */ + + if (!s->fixed_qscale) + s->current_picture.quality = ff_rate_estimate_qscale(s); //FIXME pic_ptr + + if(s->adaptive_quant){ +/* xine: do not need this for decode or MPEG-1 encoding modes */ +#if 0 +#ifdef CONFIG_RISKY + switch(s->codec_id){ + case CODEC_ID_MPEG4: + ff_clean_mpeg4_qscales(s); + break; + case CODEC_ID_H263: + case CODEC_ID_H263P: + case CODEC_ID_FLV1: + ff_clean_h263_qscales(s); + break; + } +#endif +#endif /* #if 0 */ + + s->lambda= s->lambda_table[0]; + //FIXME broken + }else + s->lambda= s->current_picture.quality; +//printf("%d %d\n", s->avctx->global_quality, s->current_picture.quality); + update_qscale(s); + + if(s->qscale < 3 && s->max_qcoeff<=128 && s->pict_type==I_TYPE && !(s->flags & CODEC_FLAG_QSCALE)) + s->qscale= 3; //reduce cliping problems + + if (s->out_format == FMT_MJPEG) { + /* for mjpeg, we do include qscale in the matrix */ + s->intra_matrix[0] = ff_mpeg1_default_intra_matrix[0]; + for(i=1;i<64;i++){ + int j= s->dsp.idct_permutation[i]; + + s->intra_matrix[j] = CLAMP_TO_8BIT((ff_mpeg1_default_intra_matrix[i] * s->qscale) >> 3); + } + convert_matrix(&s->dsp, s->q_intra_matrix, s->q_intra_matrix16, + s->intra_matrix, s->intra_quant_bias, 8, 8); + s->qscale= 8; + } + + //FIXME var duplication + s->current_picture.key_frame= s->pict_type == I_TYPE; //FIXME pic_ptr + s->current_picture.pict_type= s->pict_type; + + if(s->current_picture.key_frame) + s->picture_in_gop_number=0; + + s->last_bits= put_bits_count(&s->pb); + switch(s->out_format) { +/* xine: do not need this for decode or MPEG-1 encoding modes */ +#if 0 + case FMT_MJPEG: + mjpeg_picture_header(s); + break; +#ifdef CONFIG_RISKY + case FMT_H263: + if (s->codec_id == CODEC_ID_WMV2) + ff_wmv2_encode_picture_header(s, picture_number); + else if (s->h263_msmpeg4) + msmpeg4_encode_picture_header(s, picture_number); + else if (s->h263_pred) + mpeg4_encode_picture_header(s, picture_number); + else if (s->codec_id == CODEC_ID_RV10) + rv10_encode_picture_header(s, picture_number); + else if (s->codec_id == CODEC_ID_FLV1) + ff_flv_encode_picture_header(s, picture_number); + else + h263_encode_picture_header(s, picture_number); + break; +#endif +#endif /* #if 0 */ + case FMT_MPEG1: + mpeg1_encode_picture_header(s, picture_number); + break; +/* xine: do not need this for decode or MPEG-1 encoding modes */ +#if 0 + case FMT_H264: + break; +#endif /* #if 0 */ + default: + assert(0); + } + bits= put_bits_count(&s->pb); + s->header_bits= bits - s->last_bits; + + for(i=1; i<s->avctx->thread_count; i++){ + update_duplicate_context_after_me(s->thread_context[i], s); + } + s->avctx->execute(s->avctx, encode_thread, (void**)&(s->thread_context[0]), NULL, s->avctx->thread_count); + for(i=1; i<s->avctx->thread_count; i++){ + merge_context_after_encode(s, s->thread_context[i]); + } + emms_c(); } #endif //CONFIG_ENCODERS @@ -4659,7 +4868,7 @@ static void denoise_dct_c(MpegEncContext *s, DCTELEM *block){ } } -#if defined(CONFIG_ENCODERS) || defined(XINE_MPEG_ENCODER) +#ifdef CONFIG_ENCODERS static int dct_quantize_trellis_c(MpegEncContext *s, DCTELEM *block, int n, @@ -4949,6 +5158,406 @@ static int dct_quantize_trellis_c(MpegEncContext *s, return last_non_zero; } +//#define REFINE_STATS 1 +static int16_t basis[64][64]; + +static void build_basis(uint8_t *perm){ + int i, j, x, y; + emms_c(); + for(i=0; i<8; i++){ + for(j=0; j<8; j++){ + for(y=0; y<8; y++){ + for(x=0; x<8; x++){ + double s= 0.25*(1<<BASIS_SHIFT); + int index= 8*i + j; + int perm_index= perm[index]; + if(i==0) s*= sqrt(0.5); + if(j==0) s*= sqrt(0.5); + basis[perm_index][8*x + y]= lrintf(s * cos((M_PI/8.0)*i*(x+0.5)) * cos((M_PI/8.0)*j*(y+0.5))); + } + } + } + } +} + +static int dct_quantize_refine(MpegEncContext *s, //FIXME breaks denoise? + DCTELEM *block, int16_t *weight, DCTELEM *orig, + int n, int qscale){ + int16_t rem[64]; + DCTELEM d1[64]; + const int *qmat; + const uint8_t *scantable= s->intra_scantable.scantable; + const uint8_t *perm_scantable= s->intra_scantable.permutated; +// unsigned int threshold1, threshold2; +// int bias=0; + int run_tab[65]; + int prev_run=0; + int prev_level=0; + int qmul, qadd, start_i, last_non_zero, i, dc; + const int esc_length= s->ac_esc_length; + uint8_t * length; + uint8_t * last_length; + int lambda; + int rle_index, run, q, sum; +#ifdef REFINE_STATS +static int count=0; +static int after_last=0; +static int to_zero=0; +static int from_zero=0; +static int raise=0; +static int lower=0; +static int messed_sign=0; +#endif + + if(basis[0][0] == 0) + build_basis(s->dsp.idct_permutation); + + qmul= qscale*2; + qadd= (qscale-1)|1; + if (s->mb_intra) { + if (!s->h263_aic) { + if (n < 4) + q = s->y_dc_scale; + else + q = s->c_dc_scale; + } else{ + /* For AIC we skip quant/dequant of INTRADC */ + q = 1; + qadd=0; + } + q <<= RECON_SHIFT-3; + /* note: block[0] is assumed to be positive */ + dc= block[0]*q; +// block[0] = (block[0] + (q >> 1)) / q; + start_i = 1; + qmat = s->q_intra_matrix[qscale]; +// if(s->mpeg_quant || s->out_format == FMT_MPEG1) +// bias= 1<<(QMAT_SHIFT-1); + length = s->intra_ac_vlc_length; + last_length= s->intra_ac_vlc_last_length; + } else { + dc= 0; + start_i = 0; + qmat = s->q_inter_matrix[qscale]; + length = s->inter_ac_vlc_length; + last_length= s->inter_ac_vlc_last_length; + } + last_non_zero = s->block_last_index[n]; + +#ifdef REFINE_STATS +{START_TIMER +#endif + dc += (1<<(RECON_SHIFT-1)); + for(i=0; i<64; i++){ + rem[i]= dc - (orig[i]<<RECON_SHIFT); //FIXME use orig dirrectly insteadof copying to rem[] + } +#ifdef REFINE_STATS +STOP_TIMER("memset rem[]")} +#endif + sum=0; + for(i=0; i<64; i++){ + int one= 36; + int qns=4; + int w; + + w= ABS(weight[i]) + qns*one; + w= 15 + (48*qns*one + w/2)/w; // 16 .. 63 + + weight[i] = w; +// w=weight[i] = (63*qns + (w/2)) / w; + + assert(w>0); + assert(w<(1<<6)); + sum += w*w; + } + lambda= sum*(uint64_t)s->lambda2 >> (FF_LAMBDA_SHIFT - 6 + 6 + 6 + 6); +#ifdef REFINE_STATS +{START_TIMER +#endif + run=0; + rle_index=0; + for(i=start_i; i<=last_non_zero; i++){ + int j= perm_scantable[i]; + const int level= block[j]; + int coeff; + + if(level){ + if(level<0) coeff= qmul*level - qadd; + else coeff= qmul*level + qadd; + run_tab[rle_index++]=run; + run=0; + + s->dsp.add_8x8basis(rem, basis[j], coeff); + }else{ + run++; + } + } +#ifdef REFINE_STATS +if(last_non_zero>0){ +STOP_TIMER("init rem[]") +} +} + +{START_TIMER +#endif + for(;;){ + int best_score=s->dsp.try_8x8basis(rem, weight, basis[0], 0); + int nochange_score= best_score; + int best_coeff=0; + int best_change=0; + int run2, best_unquant_change, analyze_gradient; +#ifdef REFINE_STATS +{START_TIMER +#endif + analyze_gradient = last_non_zero > 2 || s->avctx->quantizer_noise_shaping >= 3; + + if(analyze_gradient){ +#ifdef REFINE_STATS +{START_TIMER +#endif + for(i=0; i<64; i++){ + int w= weight[i]; + + d1[i] = (rem[i]*w*w + (1<<(RECON_SHIFT+12-1)))>>(RECON_SHIFT+12); + } +#ifdef REFINE_STATS +STOP_TIMER("rem*w*w")} +{START_TIMER +#endif + s->dsp.fdct(d1); +#ifdef REFINE_STATS +STOP_TIMER("dct")} +#endif + } + + if(start_i){ + const int level= block[0]; + int change, old_coeff; + + assert(s->mb_intra); + + old_coeff= q*level; + + for(change=-1; change<=1; change+=2){ + int new_level= level + change; + int score, new_coeff; + + new_coeff= q*new_level; + if(new_coeff >= 2048 || new_coeff < 0) + continue; + + score= s->dsp.try_8x8basis(rem, weight, basis[0], new_coeff - old_coeff); + if(score<best_score){ + best_score= score; + best_coeff= 0; + best_change= change; + best_unquant_change= new_coeff - old_coeff; + } + } + } + + run=0; + rle_index=0; + run2= run_tab[rle_index++]; + prev_level=0; + prev_run=0; + + for(i=start_i; i<64; i++){ + int j= perm_scantable[i]; + const int level= block[j]; + int change, old_coeff; + + if(s->avctx->quantizer_noise_shaping < 3 && i > last_non_zero + 1) + break; + + if(level){ + if(level<0) old_coeff= qmul*level - qadd; + else old_coeff= qmul*level + qadd; + run2= run_tab[rle_index++]; //FIXME ! maybe after last + }else{ + old_coeff=0; + run2--; + assert(run2>=0 || i >= last_non_zero ); + } + + for(change=-1; change<=1; change+=2){ + int new_level= level + change; + int score, new_coeff, unquant_change; + + score=0; + if(s->avctx->quantizer_noise_shaping < 2 && ABS(new_level) > ABS(level)) + continue; + + if(new_level){ + if(new_level<0) new_coeff= qmul*new_level - qadd; + else new_coeff= qmul*new_level + qadd; + if(new_coeff >= 2048 || new_coeff <= -2048) + continue; + //FIXME check for overflow + + if(level){ + if(level < 63 && level > -63){ + if(i < last_non_zero) + score += length[UNI_AC_ENC_INDEX(run, new_level+64)] + - length[UNI_AC_ENC_INDEX(run, level+64)]; + else + score += last_length[UNI_AC_ENC_INDEX(run, new_level+64)] + - last_length[UNI_AC_ENC_INDEX(run, level+64)]; + } + }else{ + assert(ABS(new_level)==1); + + if(analyze_gradient){ + int g= d1[ scantable[i] ]; + if(g && (g^new_level) >= 0) + continue; + } + + if(i < last_non_zero){ + int next_i= i + run2 + 1; + int next_level= block[ perm_scantable[next_i] ] + 64; + + if(next_level&(~127)) + next_level= 0; + + if(next_i < last_non_zero) + score += length[UNI_AC_ENC_INDEX(run, 65)] + + length[UNI_AC_ENC_INDEX(run2, next_level)] + - length[UNI_AC_ENC_INDEX(run + run2 + 1, next_level)]; + else + score += length[UNI_AC_ENC_INDEX(run, 65)] + + last_length[UNI_AC_ENC_INDEX(run2, next_level)] + - last_length[UNI_AC_ENC_INDEX(run + run2 + 1, next_level)]; + }else{ + score += last_length[UNI_AC_ENC_INDEX(run, 65)]; + if(prev_level){ + score += length[UNI_AC_ENC_INDEX(prev_run, prev_level)] + - last_length[UNI_AC_ENC_INDEX(prev_run, prev_level)]; + } + } + } + }else{ + new_coeff=0; + assert(ABS(level)==1); + + if(i < last_non_zero){ + int next_i= i + run2 + 1; + int next_level= block[ perm_scantable[next_i] ] + 64; + + if(next_level&(~127)) + next_level= 0; + + if(next_i < last_non_zero) + score += length[UNI_AC_ENC_INDEX(run + run2 + 1, next_level)] + - length[UNI_AC_ENC_INDEX(run2, next_level)] + - length[UNI_AC_ENC_INDEX(run, 65)]; + else + score += last_length[UNI_AC_ENC_INDEX(run + run2 + 1, next_level)] + - last_length[UNI_AC_ENC_INDEX(run2, next_level)] + - length[UNI_AC_ENC_INDEX(run, 65)]; + }else{ + score += -last_length[UNI_AC_ENC_INDEX(run, 65)]; + if(prev_level){ + score += last_length[UNI_AC_ENC_INDEX(prev_run, prev_level)] + - length[UNI_AC_ENC_INDEX(prev_run, prev_level)]; + } + } + } + + score *= lambda; + + unquant_change= new_coeff - old_coeff; + assert((score < 100*lambda && score > -100*lambda) || lambda==0); + + score+= s->dsp.try_8x8basis(rem, weight, basis[j], unquant_change); + if(score<best_score){ + best_score= score; + best_coeff= i; + best_change= change; + best_unquant_change= unquant_change; + } + } + if(level){ + prev_level= level + 64; + if(prev_level&(~127)) + prev_level= 0; + prev_run= run; + run=0; + }else{ + run++; + } + } +#ifdef REFINE_STATS +STOP_TIMER("iterative step")} +#endif + + if(best_change){ + int j= perm_scantable[ best_coeff ]; + + block[j] += best_change; + + if(best_coeff > last_non_zero){ + last_non_zero= best_coeff; + assert(block[j]); +#ifdef REFINE_STATS +after_last++; +#endif + }else{ +#ifdef REFINE_STATS +if(block[j]){ + if(block[j] - best_change){ + if(ABS(block[j]) > ABS(block[j] - best_change)){ + raise++; + }else{ + lower++; + } + }else{ + from_zero++; + } +}else{ + to_zero++; +} +#endif + for(; last_non_zero>=start_i; last_non_zero--){ + if(block[perm_scantable[last_non_zero]]) + break; + } + } +#ifdef REFINE_STATS +count++; +if(256*256*256*64 % count == 0){ + printf("after_last:%d to_zero:%d from_zero:%d raise:%d lower:%d sign:%d xyp:%d/%d/%d\n", after_last, to_zero, from_zero, raise, lower, messed_sign, s->mb_x, s->mb_y, s->picture_number); +} +#endif + run=0; + rle_index=0; + for(i=start_i; i<=last_non_zero; i++){ + int j= perm_scantable[i]; + const int level= block[j]; + + if(level){ + run_tab[rle_index++]=run; + run=0; + }else{ + run++; + } + } + + s->dsp.add_8x8basis(rem, basis[j], best_unquant_change); + }else{ + break; + } + } +#ifdef REFINE_STATS +if(last_non_zero>0){ +STOP_TIMER("iterative search") +} +} +#endif + + return last_non_zero; +} + static int dct_quantize_c(MpegEncContext *s, DCTELEM *block, int n, int qscale, int *overflow) @@ -5290,7 +5899,7 @@ static const AVOption mpeg4_options[] = AVOPTION_END() }; -#if defined(CONFIG_ENCODERS) || defined(XINE_MPEG_ENCODER) +#ifdef CONFIG_ENCODERS #ifdef CONFIG_RISKY AVCodec h263_encoder = { "h263", |