diff --git a/libavcodec/h263.c b/libavcodec/h263.c index fdebcab47a..3b183830b9 100644 --- a/libavcodec/h263.c +++ b/libavcodec/h263.c @@ -1348,6 +1348,8 @@ void mpeg4_encode_picture_header(MpegEncContext * s, int picture_number) s->y_dc_scale_table= ff_mpeg4_y_dc_scale_table; //FIXME add short header support s->c_dc_scale_table= ff_mpeg4_c_dc_scale_table; + s->h_edge_pos= s->width; + s->v_edge_pos= s->height; } static void h263_dc_scale(MpegEncContext * s) @@ -3851,11 +3853,15 @@ int mpeg4_decode_picture_header(MpegEncContext * s) printf("Error, header damaged or not MPEG4 header (f_code=0)\n"); return -1; // makes no sense to continue, as the MV decoding will break very quickly } - } + }else + s->f_code=1; + if (s->pict_type == B_TYPE) { s->b_code = get_bits(&s->gb, 3); //printf("b-code %d\n", s->b_code); - } + }else + s->b_code=1; + //printf("quant:%d fcode:%d bcode:%d type:%d\n", s->qscale, s->f_code, s->b_code, s->pict_type); if(!s->scalability){ if (s->shape!=RECT_SHAPE && s->pict_type!=I_TYPE) { @@ -3884,6 +3890,10 @@ int mpeg4_decode_picture_header(MpegEncContext * s) s->y_dc_scale_table= ff_mpeg4_y_dc_scale_table; //FIXME add short header support s->c_dc_scale_table= ff_mpeg4_c_dc_scale_table; + if(s->divx_version==0 || s->divx_version < 500){ + s->h_edge_pos= s->width; + s->v_edge_pos= s->height; + } return 0; } diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 0cbe85934a..be4e1dc0a9 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -145,6 +145,11 @@ int MPV_common_init(MpegEncContext *s) s->mb_width = (s->width + 15) / 16; s->mb_height = (s->height + 15) / 16; + + /* set default edge pos, will be overriden in decode_header if needed */ + s->h_edge_pos= s->mb_width*16; + s->v_edge_pos= s->mb_height*16; + s->mb_num = s->mb_width * s->mb_height; if(!(s->flags&CODEC_FLAG_DR1)){ s->linesize = s->mb_width * 16 + 2 * EDGE_WIDTH; @@ -624,7 +629,6 @@ void MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) avctx->mbskip_table= s->mbskip_table; if(avctx->flags&CODEC_FLAG_DR1){ - int i; avctx->get_buffer_callback(avctx, s->width, s->height, s->pict_type); s->linesize = avctx->dr_stride; @@ -676,16 +680,9 @@ void MPV_frame_end(MpegEncContext *s) /* draw edge for correct motion prediction if outside */ if (s->pict_type != B_TYPE && !s->intra_only && !(s->flags&CODEC_FLAG_EMU_EDGE)) { - 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->uvlinesize, s->mb_width*8, s->mb_height*8, EDGE_WIDTH/2); - draw_edges(s->current_picture[2], s->uvlinesize, s->mb_width*8, s->mb_height*8, EDGE_WIDTH/2); - }else{ - /* mpeg4? / opendivx / xvid */ - draw_edges(s->current_picture[0], s->linesize, s->width, s->height, EDGE_WIDTH); - draw_edges(s->current_picture[1], s->uvlinesize, s->width/2, s->height/2, EDGE_WIDTH/2); - draw_edges(s->current_picture[2], s->uvlinesize, s->width/2, s->height/2, EDGE_WIDTH/2); - } + draw_edges(s->current_picture[0], s->linesize , s->h_edge_pos , s->v_edge_pos , EDGE_WIDTH ); + draw_edges(s->current_picture[1], s->uvlinesize, s->h_edge_pos>>1, s->v_edge_pos>>1, EDGE_WIDTH/2); + draw_edges(s->current_picture[2], s->uvlinesize, s->h_edge_pos>>1, s->v_edge_pos>>1, EDGE_WIDTH/2); } emms_c(); @@ -908,9 +905,9 @@ static inline void gmc1_motion(MpegEncContext *s, dest_y+=dest_offset; if(s->flags&CODEC_FLAG_EMU_EDGE){ - if(src_x<0 || src_y<0 || src_x + (motion_x&15) + 16 > s->width - || src_y + (motion_y&15) + h > s->height){ - emulated_edge_mc(s, ptr, linesize, 17, h+1, src_x, src_y, s->width, s->height); + if(src_x<0 || src_y<0 || src_x + (motion_x&15) + 16 > s->h_edge_pos + || src_y + (motion_y&15) + h > s->v_edge_pos){ + emulated_edge_mc(s, ptr, linesize, 17, h+1, src_x, src_y, s->h_edge_pos, s->v_edge_pos); ptr= s->edge_emu_buffer; emu=1; } @@ -934,14 +931,14 @@ static inline void gmc1_motion(MpegEncContext *s, offset = (src_y * uvlinesize) + src_x + (src_offset>>1); ptr = ref_picture[1] + offset; if(emu){ - emulated_edge_mc(s, ptr, uvlinesize, 9, (h>>1)+1, src_x, src_y, s->width>>1, s->height>>1); + emulated_edge_mc(s, ptr, uvlinesize, 9, (h>>1)+1, src_x, src_y, s->h_edge_pos>>1, s->v_edge_pos>>1); ptr= s->edge_emu_buffer; } gmc1(dest_cb + (dest_offset>>1), ptr, uvlinesize, h>>1, motion_x&15, motion_y&15, s->no_rounding); ptr = ref_picture[2] + offset; if(emu){ - emulated_edge_mc(s, ptr, uvlinesize, 9, (h>>1)+1, src_x, src_y, s->width>>1, s->height>>1); + emulated_edge_mc(s, ptr, uvlinesize, 9, (h>>1)+1, src_x, src_y, s->h_edge_pos>>1, s->v_edge_pos>>1); ptr= s->edge_emu_buffer; } gmc1(dest_cr + (dest_offset>>1), ptr, uvlinesize, h>>1, motion_x&15, motion_y&15, s->no_rounding); @@ -954,17 +951,7 @@ static void emulated_edge_mc(MpegEncContext *s, UINT8 *src, int linesize, int bl int x, y; int start_y, start_x, end_y, end_x; UINT8 *buf= s->edge_emu_buffer; -#if 0 - if(s->codec_id!=CODEC_ID_MPEG4 || s->divx_version>=500){ - if(block_w < 10){ - w= (w+7)&(~7); - h= (h+7)&(~7); - }else{ - w= (w+15)&(~15); - h= (h+15)&(~15); - } - } -#endif + if(src_y>= h){ src+= (h-1-src_y)*linesize; src_y=h-1; @@ -1029,7 +1016,7 @@ static inline void mpeg_motion(MpegEncContext *s, int motion_x, int motion_y, int h) { UINT8 *ptr; - int dxy, offset, mx, my, src_x, src_y, height, linesize, uvlinesize; + int dxy, offset, mx, my, src_x, src_y, height, v_edge_pos, linesize, uvlinesize; int emu=0; if(s->quarter_sample) @@ -1043,6 +1030,7 @@ if(s->quarter_sample) /* WARNING: do no forget half pels */ 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 &= ~1; @@ -1055,9 +1043,9 @@ if(s->quarter_sample) dest_y += dest_offset; if(s->flags&CODEC_FLAG_EMU_EDGE){ - if(src_x<0 || src_y<0 || src_x + (motion_x&1) + 16 > s->width - || src_y + (motion_y&1) + h > height){ - emulated_edge_mc(s, ptr, linesize, 17, h+1, src_x, src_y, s->width, height); + if(src_x<0 || src_y<0 || src_x + (motion_x&1) + 16 > s->h_edge_pos + || src_y + (motion_y&1) + h > v_edge_pos){ + emulated_edge_mc(s, ptr, linesize, 17, h+1, src_x, src_y, s->h_edge_pos, v_edge_pos); ptr= s->edge_emu_buffer; emu=1; } @@ -1094,14 +1082,14 @@ if(s->quarter_sample) offset = (src_y * uvlinesize) + src_x + (src_offset >> 1); ptr = ref_picture[1] + offset; if(emu){ - emulated_edge_mc(s, ptr, uvlinesize, 9, (h>>1)+1, src_x, src_y, s->width>>1, height>>1); + emulated_edge_mc(s, ptr, uvlinesize, 9, (h>>1)+1, src_x, src_y, s->h_edge_pos>>1, v_edge_pos>>1); ptr= s->edge_emu_buffer; } pix_op[dxy](dest_cb + (dest_offset >> 1), ptr, uvlinesize, h >> 1); ptr = ref_picture[2] + offset; if(emu){ - emulated_edge_mc(s, ptr, uvlinesize, 9, (h>>1)+1, src_x, src_y, s->width>>1, height>>1); + emulated_edge_mc(s, ptr, uvlinesize, 9, (h>>1)+1, src_x, src_y, s->h_edge_pos>>1, v_edge_pos>>1); ptr= s->edge_emu_buffer; } pix_op[dxy](dest_cr + (dest_offset >> 1), ptr, uvlinesize, h >> 1); @@ -1116,7 +1104,7 @@ static inline void qpel_motion(MpegEncContext *s, int motion_x, int motion_y, int h) { UINT8 *ptr; - int dxy, offset, mx, my, src_x, src_y, height, linesize; + int dxy, offset, mx, my, src_x, src_y, height, v_edge_pos, linesize; int emu=0; dxy = ((motion_y & 3) << 2) | (motion_x & 3); @@ -1124,6 +1112,7 @@ static inline void qpel_motion(MpegEncContext *s, 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; @@ -1136,9 +1125,9 @@ static inline void qpel_motion(MpegEncContext *s, //printf("%d %d %d\n", src_x, src_y, dxy); if(s->flags&CODEC_FLAG_EMU_EDGE){ - if(src_x<0 || src_y<0 || src_x + (motion_x&3) + 16 > s->width - || src_y + (motion_y&3) + h > height){ - emulated_edge_mc(s, ptr, linesize, 17, h+1, src_x, src_y, s->width, height); + if(src_x<0 || src_y<0 || src_x + (motion_x&3) + 16 > s->h_edge_pos + || src_y + (motion_y&3) + h > v_edge_pos){ + emulated_edge_mc(s, ptr, linesize, 17, h+1, src_x, src_y, s->h_edge_pos, v_edge_pos); ptr= s->edge_emu_buffer; emu=1; } @@ -1173,14 +1162,14 @@ static inline void qpel_motion(MpegEncContext *s, offset = (src_y * s->uvlinesize) + src_x + (src_offset >> 1); ptr = ref_picture[1] + offset; if(emu){ - emulated_edge_mc(s, ptr, s->uvlinesize, 9, (h>>1)+1, src_x, src_y, s->width>>1, height>>1); + emulated_edge_mc(s, ptr, s->uvlinesize, 9, (h>>1)+1, src_x, src_y, s->h_edge_pos>>1, v_edge_pos>>1); ptr= s->edge_emu_buffer; } pix_op[dxy](dest_cb + (dest_offset >> 1), ptr, s->uvlinesize, h >> 1); ptr = ref_picture[2] + offset; if(emu){ - emulated_edge_mc(s, ptr, s->uvlinesize, 9, (h>>1)+1, src_x, src_y, s->width>>1, height>>1); + emulated_edge_mc(s, ptr, s->uvlinesize, 9, (h>>1)+1, src_x, src_y, s->h_edge_pos>>1, v_edge_pos>>1); ptr= s->edge_emu_buffer; } pix_op[dxy](dest_cr + (dest_offset >> 1), ptr, s->uvlinesize, h >> 1); @@ -1246,9 +1235,9 @@ static inline void MPV_motion(MpegEncContext *s, ptr = ref_picture[0] + (src_y * s->linesize) + (src_x); if(s->flags&CODEC_FLAG_EMU_EDGE){ - if(src_x<0 || src_y<0 || src_x + (motion_x&1) + 8 > s->width - || src_y + (motion_y&1) + 8 > s->height){ - emulated_edge_mc(s, ptr, s->linesize, 9, 9, src_x, src_y, s->width, s->height); + if(src_x<0 || src_y<0 || src_x + (motion_x&1) + 8 > s->h_edge_pos + || src_y + (motion_y&1) + 8 > s->v_edge_pos){ + emulated_edge_mc(s, ptr, s->linesize, 9, 9, src_x, src_y, s->h_edge_pos, s->v_edge_pos); ptr= s->edge_emu_buffer; } } @@ -1293,9 +1282,9 @@ static inline void MPV_motion(MpegEncContext *s, offset = (src_y * (s->uvlinesize)) + src_x; ptr = ref_picture[1] + offset; if(s->flags&CODEC_FLAG_EMU_EDGE){ - if(src_x<0 || src_y<0 || src_x + (dxy &1) + 8 > s->width >>1 - || src_y + (dxy>>1) + 8 > s->height>>1){ - emulated_edge_mc(s, ptr, s->uvlinesize, 9, 9, src_x, src_y, s->width>>1, s->height>>1); + if(src_x<0 || src_y<0 || src_x + (dxy &1) + 8 > s->h_edge_pos>>1 + || src_y + (dxy>>1) + 8 > s->v_edge_pos>>1){ + emulated_edge_mc(s, ptr, s->uvlinesize, 9, 9, src_x, src_y, s->h_edge_pos>>1, s->v_edge_pos>>1); ptr= s->edge_emu_buffer; emu=1; } @@ -1304,7 +1293,7 @@ static inline void MPV_motion(MpegEncContext *s, ptr = ref_picture[2] + offset; if(emu){ - emulated_edge_mc(s, ptr, s->uvlinesize, 9, 9, src_x, src_y, s->width>>1, s->height>>1); + emulated_edge_mc(s, ptr, s->uvlinesize, 9, 9, src_x, src_y, s->h_edge_pos>>1, s->v_edge_pos>>1); ptr= s->edge_emu_buffer; } pix_op[dxy](dest_cr, ptr, s->uvlinesize, 8); @@ -2022,7 +2011,6 @@ static void encode_picture(MpegEncContext *s, int picture_number) //printf("f_code %d ///\n", s->f_code); // printf("%d %d\n", s->avg_mb_var, s->mc_mb_var); - if(s->flags&CODEC_FLAG_PASS2) s->qscale = ff_rate_estimate_qscale_pass2(s); else if (!s->fixed_qscale) diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index b04d4f74cd..820f1100ec 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -130,6 +130,7 @@ typedef struct MpegEncContext { int picture_in_gop_number; /* 0-> first pic in gop, ... */ int b_frames_since_non_b; /* used for encoding, relative to not yet reordered input */ int mb_width, mb_height; /* number of MBs horizontally & vertically */ + int h_edge_pos, v_edge_pos;/* horizontal / vertical position of the right/bottom edge (pixel replicateion)*/ int mb_num; /* number of MBs of a picture */ int linesize; /* line size, in bytes, may be different from width */ int uvlinesize; /* line size, for chroma in bytes, may be different from width */