diff options
Diffstat (limited to 'src/libffmpeg/libavcodec/mpeg12.c')
-rw-r--r-- | src/libffmpeg/libavcodec/mpeg12.c | 455 |
1 files changed, 289 insertions, 166 deletions
diff --git a/src/libffmpeg/libavcodec/mpeg12.c b/src/libffmpeg/libavcodec/mpeg12.c index aecfd35f1..e39356c9d 100644 --- a/src/libffmpeg/libavcodec/mpeg12.c +++ b/src/libffmpeg/libavcodec/mpeg12.c @@ -34,6 +34,13 @@ //#include <assert.h> +/* if xine's MPEG encoder is enabled, enable the encoding features in + * this particular module */ +#ifdef XINE_MPEG_ENCODER +#define CONFIG_ENCODERS +#endif + + /* Start codes. */ #define SEQ_END_CODE 0x000001b7 #define SEQ_START_CODE 0x000001b3 @@ -52,7 +59,7 @@ #define MB_BTYPE_VLC_BITS 6 #define TEX_VLC_BITS 9 -#if defined(CONFIG_ENCODERS) || defined(XINE_MPEG_ENCODER) +#ifdef CONFIG_ENCODERS static void mpeg1_encode_block(MpegEncContext *s, DCTELEM *block, int component); @@ -80,7 +87,14 @@ extern void XVMC_pack_pblocks(MpegEncContext *s,int cbp); extern void XVMC_init_block(MpegEncContext *s);//set s->block #endif -#if defined(CONFIG_ENCODERS) || defined(XINE_MPEG_ENCODER) +const enum PixelFormat pixfmt_yuv_420[]= {PIX_FMT_YUV420P,-1}; +const enum PixelFormat pixfmt_yuv_422[]= {PIX_FMT_YUV422P,-1}; +const enum PixelFormat pixfmt_yuv_444[]= {PIX_FMT_YUV444P,-1}; +const enum PixelFormat pixfmt_xvmc_mpg2_420[] = { + PIX_FMT_XVMC_MPEG2_IDCT, + PIX_FMT_XVMC_MPEG2_MC, + -1}; +#ifdef CONFIG_ENCODERS static uint8_t (*mv_penalty)[MAX_MV*2+1]= NULL; static uint8_t fcode_tab[MAX_MV*2+1]; @@ -134,7 +148,7 @@ static void init_2d_vlc_rl(RLTable *rl) } } -#if defined(CONFIG_ENCODERS) || defined(XINE_MPEG_ENCODER) +#ifdef CONFIG_ENCODERS static void init_uni_ac_vlc(RLTable *rl, uint32_t *uni_ac_vlc_bits, uint8_t *uni_ac_vlc_len){ int i; @@ -188,9 +202,11 @@ static int find_frame_rate_index(MpegEncContext *s){ int64_t d; for(i=1;i<14;i++) { + int64_t n0= 1001LL/frame_rate_tab[i].den*frame_rate_tab[i].num*s->avctx->frame_rate_base; + int64_t n1= 1001LL*s->avctx->frame_rate; if(s->avctx->strict_std_compliance >= 0 && i>=9) break; - - d = ABS(MPEG1_FRAME_RATE_BASE*(int64_t)s->avctx->frame_rate - frame_rate_tab[i]*(int64_t)s->avctx->frame_rate_base); + + d = ABS(n0 - n1); if(d < dmin){ dmin=d; s->frame_rate_index= i; @@ -242,6 +258,8 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) if(aspect_ratio==0.0) aspect_ratio= 1.0; //pixel aspect 1:1 (VGA) if (s->current_picture.key_frame) { + AVRational framerate= frame_rate_tab[s->frame_rate_index]; + /* mpeg1 header repeated every gop */ put_header(s, SEQ_START_CODE); @@ -288,8 +306,8 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) constraint_parameter_flag= s->width <= 768 && s->height <= 576 && s->mb_width * s->mb_height <= 396 && - s->mb_width * s->mb_height * frame_rate_tab[s->frame_rate_index] <= MPEG1_FRAME_RATE_BASE*396*25 && - frame_rate_tab[s->frame_rate_index] <= MPEG1_FRAME_RATE_BASE*30 && + s->mb_width * s->mb_height * framerate.num <= framerate.den*396*25 && + framerate.num <= framerate.den*30 && vbv_buffer_size <= 20 && v <= 1856000/400 && s->codec_id == CODEC_ID_MPEG1VIDEO; @@ -321,7 +339,7 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) put_bits(&s->pb, 1, 0); /* do drop frame */ /* time code : we must convert from the real frame rate to a fake mpeg frame rate in case of low frame rate */ - fps = (frame_rate_tab[s->frame_rate_index] + MPEG1_FRAME_RATE_BASE/2)/ MPEG1_FRAME_RATE_BASE; + fps = (framerate.num + framerate.den/2)/ framerate.den; time_code = s->current_picture_ptr->coded_picture_number; s->gop_picture_number = time_code; @@ -358,7 +376,7 @@ void ff_mpeg1_clean_buffers(MpegEncContext *s){ memset(s->last_mv, 0, sizeof(s->last_mv)); } -#if defined(CONFIG_ENCODERS) || defined(XINE_MPEG_ENCODER) +#ifdef CONFIG_ENCODERS void ff_mpeg1_encode_slice_header(MpegEncContext *s){ put_header(s, SLICE_MIN_START_CODE + s->mb_y); @@ -379,7 +397,7 @@ void mpeg1_encode_picture_header(MpegEncContext *s, int picture_number) s->gop_picture_number) & 0x3ff); put_bits(&s->pb, 3, s->pict_type); - s->vbv_delay_ptr= s->pb.buf + get_bit_count(&s->pb)/8; + s->vbv_delay_ptr= s->pb.buf + put_bits_count(&s->pb)/8; put_bits(&s->pb, 16, 0xFFFF); /* vbv_delay */ // RAL: Forward f_code also needed for B frames @@ -419,7 +437,9 @@ void mpeg1_encode_picture_header(MpegEncContext *s, int picture_number) put_bits(&s->pb, 8, 255); } put_bits(&s->pb, 2, s->intra_dc_precision); - put_bits(&s->pb, 2, s->picture_structure= PICT_FRAME); + + assert(s->picture_structure == PICT_FRAME); + put_bits(&s->pb, 2, s->picture_structure); if (s->progressive_sequence) { put_bits(&s->pb, 1, 0); /* no repeat */ } else { @@ -583,7 +603,7 @@ void mpeg1_encode_mb(MpegEncContext *s, s->mv_bits+= get_bits_diff(s); } if(cbp) - put_bits(&s->pb, mbPatTable[cbp - 1][1], mbPatTable[cbp - 1][0]); + put_bits(&s->pb, mbPatTable[cbp][1], mbPatTable[cbp][0]); s->f_count++; } else{ static const int mb_type_len[4]={0,3,4,2}; //bak,for,bi @@ -662,7 +682,7 @@ void mpeg1_encode_mb(MpegEncContext *s, } s->mv_bits += get_bits_diff(s); if(cbp) - put_bits(&s->pb, mbPatTable[cbp - 1][1], mbPatTable[cbp - 1][0]); + put_bits(&s->pb, mbPatTable[cbp][1], mbPatTable[cbp][0]); } for(i=0;i<6;i++) { if (cbp & (1 << (5 - i))) { @@ -954,7 +974,7 @@ static void init_vlcs() init_vlc(&mbincr_vlc, MBINCR_VLC_BITS, 36, &mbAddrIncrTable[0][1], 2, 1, &mbAddrIncrTable[0][0], 2, 1); - init_vlc(&mb_pat_vlc, MB_PAT_VLC_BITS, 63, + init_vlc(&mb_pat_vlc, MB_PAT_VLC_BITS, 64, &mbPatTable[0][1], 2, 1, &mbPatTable[0][0], 2, 1); @@ -997,7 +1017,7 @@ static inline int get_qscale(MpegEncContext *s) #define MT_DMV 3 static int mpeg_decode_mb(MpegEncContext *s, - DCTELEM block[6][64]) + DCTELEM block[12][64]) { int i, j, k, cbp, val, mb_type, motion_type; @@ -1013,15 +1033,19 @@ static int mpeg_decode_mb(MpegEncContext *s, /* skip mb */ s->mb_intra = 0; - for(i=0;i<6;i++) + for(i=0;i<12;i++) s->block_last_index[i] = -1; - s->mv_type = MV_TYPE_16X16; + if(s->picture_structure == PICT_FRAME) + s->mv_type = MV_TYPE_16X16; + else + s->mv_type = MV_TYPE_FIELD; if (s->pict_type == P_TYPE) { /* if P type, zero motion vector is implied */ s->mv_dir = MV_DIR_FORWARD; s->mv[0][0][0] = s->mv[0][0][1] = 0; s->last_mv[0][0][0] = s->last_mv[0][0][1] = 0; s->last_mv[0][1][0] = s->last_mv[0][1][1] = 0; + s->field_select[0][0]= s->picture_structure - 1; s->mb_skiped = 1; s->current_picture.mb_type[ s->mb_x + s->mb_y*s->mb_stride ]= MB_TYPE_SKIP | MB_TYPE_L0 | MB_TYPE_16x16; } else { @@ -1109,7 +1133,7 @@ static int mpeg_decode_mb(MpegEncContext *s, #endif if (s->codec_id == CODEC_ID_MPEG2VIDEO) { - for(i=0;i<6;i++) { + for(i=0;i<4+(1<<s->chroma_format);i++) { if (mpeg2_decode_block_intra(s, s->pblocks[i], i) < 0) return -1; } @@ -1133,7 +1157,13 @@ static int mpeg_decode_mb(MpegEncContext *s, s->qscale = get_qscale(s); s->mv_dir = MV_DIR_FORWARD; - s->mv_type = MV_TYPE_16X16; + if(s->picture_structure == PICT_FRAME) + s->mv_type = MV_TYPE_16X16; + else{ + s->mv_type = MV_TYPE_FIELD; + mb_type |= MB_TYPE_INTERLACED; + s->field_select[0][0]= s->picture_structure - 1; + } s->last_mv[0][0][0] = 0; s->last_mv[0][0][1] = 0; s->last_mv[0][1][0] = 0; @@ -1283,11 +1313,16 @@ static int mpeg_decode_mb(MpegEncContext *s, if (HAS_CBP(mb_type)) { cbp = get_vlc2(&s->gb, mb_pat_vlc.table, MB_PAT_VLC_BITS, 1); - if (cbp < 0){ + if (cbp < 0 || ((cbp == 0) && (s->chroma_format < 2)) ){ av_log(s->avctx, AV_LOG_ERROR, "invalid cbp at %d %d\n", s->mb_x, s->mb_y); return -1; } - cbp++; + if(s->chroma_format == 2){//CHROMA422 + cbp|= ( get_bits(&s->gb,2) ) << 6; + }else + if(s->chroma_format > 2){//CHROMA444 + cbp|= ( get_bits(&s->gb,6) ) << 6; + } #ifdef HAVE_XVMC //on 1 we memcpy blocks in xvmcvideo @@ -1301,13 +1336,33 @@ static int mpeg_decode_mb(MpegEncContext *s, if (s->codec_id == CODEC_ID_MPEG2VIDEO) { for(i=0;i<6;i++) { - if (cbp & 32) { + if (cbp & (1<<(5-i)) ) { if (mpeg2_decode_block_non_intra(s, s->pblocks[i], i) < 0) return -1; } else { s->block_last_index[i] = -1; } - cbp+=cbp; + } + if (s->chroma_format >= 2) { + if (s->chroma_format == 2) {//CHROMA_422) + for(i=6;i<8;i++) { + if (cbp & (1<<(6+7-i)) ) { + if (mpeg2_decode_block_non_intra(s, s->pblocks[i], i) < 0) + return -1; + } else { + s->block_last_index[i] = -1; + } + } + }else{ /*CHROMA_444*/ + for(i=6;i<12;i++) { + if (cbp & (1<<(6+11-i)) ) { + if (mpeg2_decode_block_non_intra(s, s->pblocks[i], i) < 0) + return -1; + } else { + s->block_last_index[i] = -1; + } + } + } } } else { for(i=0;i<6;i++) { @@ -1631,7 +1686,7 @@ static inline int mpeg2_decode_block_intra(MpegEncContext *s, component = 0; }else{ quant_matrix = s->chroma_intra_matrix; - component = n - 3; + component = (n&1) + 1; } diff = decode_dc(&s->gb, component); if (diff >= 0xffff) @@ -1698,6 +1753,7 @@ typedef struct Mpeg1Context { int mpeg_enc_ctx_allocated; /* true if decoding context allocated */ int repeat_field; /* true if we must repeat the field */ AVPanScan pan_scan; /** some temporary storage for the panscan */ + int slice_count; } Mpeg1Context; static int mpeg_decode_init(AVCodecContext *avctx) @@ -1719,30 +1775,33 @@ static int mpeg_decode_init(AVCodecContext *avctx) /* return the 8 bit start code value and update the search state. Return -1 if no start code found */ -static int find_start_code(uint8_t **pbuf_ptr, uint8_t *buf_end) +static int find_start_code(const uint8_t **pbuf_ptr, const uint8_t *buf_end) { - uint8_t *buf_ptr; - unsigned int state=0xFFFFFFFF, v; - int val; + const uint8_t *buf_ptr= *pbuf_ptr; + + buf_ptr++; //gurantees that -1 is within the array + buf_end -= 2; // gurantees that +2 is within the array - buf_ptr = *pbuf_ptr; while (buf_ptr < buf_end) { - v = *buf_ptr++; - if (state == 0x000001) { - state = ((state << 8) | v) & 0xffffff; - val = state; - goto found; + if(*buf_ptr==0){ + while(buf_ptr < buf_end && buf_ptr[1]==0) + buf_ptr++; + + if(buf_ptr[-1] == 0 && buf_ptr[1] == 1){ + *pbuf_ptr = buf_ptr+3; + return buf_ptr[2] + 0x100; + } } - state = ((state << 8) | v) & 0xffffff; + buf_ptr += 2; } - val = -1; - found: - *pbuf_ptr = buf_ptr; - return val; + buf_end += 2; //undo the hack above + + *pbuf_ptr = buf_end; + return -1; } static int mpeg1_decode_picture(AVCodecContext *avctx, - uint8_t *buf, int buf_size) + const uint8_t *buf, int buf_size) { Mpeg1Context *s1 = avctx->priv_data; MpegEncContext *s = &s1->mpeg_enc_ctx; @@ -1793,13 +1852,13 @@ static void mpeg_decode_sequence_extension(MpegEncContext *s) profile= get_bits(&s->gb, 3); level= get_bits(&s->gb, 4); s->progressive_sequence = get_bits1(&s->gb); /* progressive_sequence */ - skip_bits(&s->gb, 2); /* chroma_format */ + s->chroma_format = get_bits(&s->gb, 2); /* chroma_format 1=420, 2=422, 3=444 */ horiz_size_ext = get_bits(&s->gb, 2); vert_size_ext = get_bits(&s->gb, 2); s->width |= (horiz_size_ext << 12); s->height |= (vert_size_ext << 12); bit_rate_ext = get_bits(&s->gb, 12); /* XXX: handle it */ - s->bit_rate = ((s->bit_rate / 400) | (bit_rate_ext << 12)) * 400; + s->bit_rate += (bit_rate_ext << 12) * 400; skip_bits1(&s->gb); /* marker */ s->avctx->rc_buffer_size += get_bits(&s->gb, 8)*1024*16<<10; @@ -1811,8 +1870,8 @@ static void mpeg_decode_sequence_extension(MpegEncContext *s) av_reduce( &s->avctx->frame_rate, &s->avctx->frame_rate_base, - frame_rate_tab[s->frame_rate_index] * (frame_rate_ext_n+1), - MPEG1_FRAME_RATE_BASE * (frame_rate_ext_d+1), + frame_rate_tab[s->frame_rate_index].num * (frame_rate_ext_n+1), + frame_rate_tab[s->frame_rate_index].den * (frame_rate_ext_d+1), 1<<30); dprintf("sequence extension\n"); @@ -1970,7 +2029,7 @@ static void mpeg_decode_picture_coding_extension(MpegEncContext *s) } static void mpeg_decode_extension(AVCodecContext *avctx, - uint8_t *buf, int buf_size) + const uint8_t *buf, int buf_size) { Mpeg1Context *s1 = avctx->priv_data; MpegEncContext *s = &s1->mpeg_enc_ctx; @@ -2006,43 +2065,14 @@ short * tmp; s->pblocks[5] = tmp; } -#define DECODE_SLICE_FATAL_ERROR -2 -#define DECODE_SLICE_ERROR -1 -#define DECODE_SLICE_OK 0 +static int mpeg_field_start(MpegEncContext *s){ + AVCodecContext *avctx= s->avctx; + Mpeg1Context *s1 = (Mpeg1Context*)s; -/** - * decodes a slice. - * @return DECODE_SLICE_FATAL_ERROR if a non recoverable error occured<br> - * DECODE_SLICE_ERROR if the slice is damaged<br> - * DECODE_SLICE_OK if this slice is ok<br> - */ -static int mpeg_decode_slice(AVCodecContext *avctx, - AVFrame *pict, - int start_code, - uint8_t **buf, int buf_size) -{ - Mpeg1Context *s1 = avctx->priv_data; - MpegEncContext *s = &s1->mpeg_enc_ctx; - int ret; - const int field_pic= s->picture_structure != PICT_FRAME; - - s->resync_mb_x= s->mb_x = - s->resync_mb_y= s->mb_y = -1; - - start_code = (start_code - 1) & 0xff; - if (start_code >= s->mb_height){ - av_log(s->avctx, AV_LOG_ERROR, "slice below image (%d >= %d)\n", start_code, s->mb_height); - return -1; - } - - ff_mpeg1_clean_buffers(s); - s->interlaced_dct = 0; - /* start frame decoding */ - if (s->first_slice) { - if(s->first_field || s->picture_structure==PICT_FRAME){ + if(s->first_field || s->picture_structure==PICT_FRAME){ if(MPV_frame_start(s, avctx) < 0) - return DECODE_SLICE_FATAL_ERROR; + return -1; ff_er_frame_start(s); @@ -2060,7 +2090,7 @@ static int mpeg_decode_slice(AVCodecContext *avctx, } *s->current_picture_ptr->pan_scan= s1->pan_scan; - }else{ //second field + }else{ //second field int i; if(!s->current_picture_ptr){ @@ -2074,30 +2104,48 @@ static int mpeg_decode_slice(AVCodecContext *avctx, s->current_picture.data[i] += s->current_picture_ptr->linesize[i]; } } - } + } #ifdef HAVE_XVMC // MPV_frame_start will call this function too, // but we need to call it on every field - if(s->avctx->xvmc_acceleration) + if(s->avctx->xvmc_acceleration) XVMC_field_start(s,avctx); #endif - }//fi(s->first_slice) + return 0; +} + +#define DECODE_SLICE_ERROR -1 +#define DECODE_SLICE_OK 0 + +/** + * decodes a slice. MpegEncContext.mb_y must be set to the MB row from the startcode + * @return DECODE_SLICE_ERROR if the slice is damaged<br> + * DECODE_SLICE_OK if this slice is ok<br> + */ +static int mpeg_decode_slice(Mpeg1Context *s1, int mb_y, + const uint8_t **buf, int buf_size) +{ + MpegEncContext *s = &s1->mpeg_enc_ctx; + AVCodecContext *avctx= s->avctx; + int ret; + const int field_pic= s->picture_structure != PICT_FRAME; + + s->resync_mb_x= + s->resync_mb_y= -1; + + if (mb_y >= s->mb_height){ + av_log(s->avctx, AV_LOG_ERROR, "slice below image (%d >= %d)\n", s->mb_y, s->mb_height); + return -1; + } + init_get_bits(&s->gb, *buf, buf_size*8); + ff_mpeg1_clean_buffers(s); + s->interlaced_dct = 0; + s->qscale = get_qscale(s); - if (s->first_slice && (s->first_field || s->picture_structure==PICT_FRAME)) { - if(s->avctx->debug&FF_DEBUG_PICT_INFO){ - av_log(s->avctx, AV_LOG_DEBUG, "qp:%d fc:%2d%2d%2d%2d %s %s %s %s %s dc:%d pstruct:%d fdct:%d cmv:%d qtype:%d ivlc:%d rff:%d %s\n", - s->qscale, s->mpeg_f_code[0][0],s->mpeg_f_code[0][1],s->mpeg_f_code[1][0],s->mpeg_f_code[1][1], - s->pict_type == I_TYPE ? "I" : (s->pict_type == P_TYPE ? "P" : (s->pict_type == B_TYPE ? "B" : "S")), - s->progressive_sequence ? "ps" :"", s->progressive_frame ? "pf" : "", s->alternate_scan ? "alt" :"", s->top_field_first ? "top" :"", - s->intra_dc_precision, s->picture_structure, s->frame_pred_frame_dct, s->concealment_motion_vectors, - s->q_scale_type, s->intra_vlc_format, s->repeat_first_field, s->chroma_420_type ? "420" :""); - } - } - s->first_slice = 0; if(s->qscale == 0){ av_log(s->avctx, AV_LOG_ERROR, "qscale == 0\n"); return -1; @@ -2126,12 +2174,23 @@ static int mpeg_decode_slice(AVCodecContext *avctx, break; } } - + s->resync_mb_x= s->mb_x; - s->resync_mb_y= s->mb_y = start_code; + s->resync_mb_y= s->mb_y= mb_y; s->mb_skip_run= 0; ff_init_block_index(s); + if (s->mb_y==0 && s->mb_x==0 && (s->first_field || s->picture_structure==PICT_FRAME)) { + if(s->avctx->debug&FF_DEBUG_PICT_INFO){ + av_log(s->avctx, AV_LOG_DEBUG, "qp:%d fc:%2d%2d%2d%2d %s %s %s %s %s dc:%d pstruct:%d fdct:%d cmv:%d qtype:%d ivlc:%d rff:%d %s\n", + s->qscale, s->mpeg_f_code[0][0],s->mpeg_f_code[0][1],s->mpeg_f_code[1][0],s->mpeg_f_code[1][1], + s->pict_type == I_TYPE ? "I" : (s->pict_type == P_TYPE ? "P" : (s->pict_type == B_TYPE ? "B" : "S")), + s->progressive_sequence ? "ps" :"", s->progressive_frame ? "pf" : "", s->alternate_scan ? "alt" :"", s->top_field_first ? "top" :"", + s->intra_dc_precision, s->picture_structure, s->frame_pred_frame_dct, s->concealment_motion_vectors, + s->q_scale_type, s->intra_vlc_format, s->repeat_first_field, s->chroma_420_type ? "420" :""); + } + } + for(;;) { #ifdef HAVE_XVMC //one 1 we memcpy blocks in xvmcvideo @@ -2151,51 +2210,29 @@ static int mpeg_decode_slice(AVCodecContext *avctx, if(s->current_picture.motion_val[0] && !s->encoding){ //note motion_val is normally NULL unless we want to extract the MVs const int wrap = field_pic ? 2*s->block_wrap[0] : s->block_wrap[0]; int xy = s->mb_x*2 + 1 + (s->mb_y*2 +1)*wrap; - int motion_for_top_x, motion_for_top_y, motion_back_top_x, motion_back_top_y; - int motion_for_bottom_x, motion_for_bottom_y, motion_back_bottom_x, motion_back_bottom_y; + int motion_x, motion_y, dir, i; if(field_pic && !s->first_field) xy += wrap/2; - if (s->mb_intra) { - motion_for_top_x = motion_for_top_y = motion_back_top_x = motion_back_top_y = - motion_for_bottom_x = motion_for_bottom_y = motion_back_bottom_x = motion_back_bottom_y = 0; - }else if (s->mv_type == MV_TYPE_16X16){ - motion_for_top_x = motion_for_bottom_x = s->mv[0][0][0]; - motion_for_top_y = motion_for_bottom_y = s->mv[0][0][1]; - motion_back_top_x = motion_back_bottom_x = s->mv[1][0][0]; - motion_back_top_y = motion_back_bottom_y = s->mv[1][0][1]; - } else /*if ((s->mv_type == MV_TYPE_FIELD) || (s->mv_type == MV_TYPE_16X8))*/ { - motion_for_top_x = s->mv[0][0][0]; - motion_for_top_y = s->mv[0][0][1]; - motion_for_bottom_x = s->mv[0][1][0]; - motion_for_bottom_y = s->mv[0][1][1]; - motion_back_top_x = s->mv[1][0][0]; - motion_back_top_y = s->mv[1][0][1]; - motion_back_bottom_x = s->mv[1][1][0]; - motion_back_bottom_y = s->mv[1][1][1]; - } - - s->current_picture.motion_val[0][xy][0] = motion_for_top_x; - s->current_picture.motion_val[0][xy][1] = motion_for_top_y; - s->current_picture.motion_val[0][xy + 1][0] = motion_for_top_x; - s->current_picture.motion_val[0][xy + 1][1] = motion_for_top_y; - s->current_picture.motion_val[0][xy + wrap][0] = motion_for_bottom_x; - s->current_picture.motion_val[0][xy + wrap][1] = motion_for_bottom_y; - s->current_picture.motion_val[0][xy + 1 + wrap][0] = motion_for_bottom_x; - s->current_picture.motion_val[0][xy + 1 + wrap][1] = motion_for_bottom_y; - - if(s->pict_type != B_TYPE){ - motion_back_top_x = motion_back_top_y = motion_back_bottom_x = motion_back_bottom_y = 0; + for(i=0; i<2; i++){ + for(dir=0; dir<2; dir++){ + if (s->mb_intra || (dir==1 && s->pict_type != B_TYPE)) { + motion_x = motion_y = 0; + }else if (s->mv_type == MV_TYPE_16X16){ + motion_x = s->mv[dir][0][0]; + motion_y = s->mv[dir][0][1]; + } else /*if ((s->mv_type == MV_TYPE_FIELD) || (s->mv_type == MV_TYPE_16X8))*/ { + motion_x = s->mv[dir][i][0]; + motion_y = s->mv[dir][i][1]; + } + + s->current_picture.motion_val[dir][xy ][0] = motion_x; + s->current_picture.motion_val[dir][xy ][1] = motion_y; + s->current_picture.motion_val[dir][xy + 1][0] = motion_x; + s->current_picture.motion_val[dir][xy + 1][1] = motion_y; + } + xy += wrap; } - - s->current_picture.motion_val[1][xy][0] = motion_back_top_x; - s->current_picture.motion_val[1][xy][1] = motion_back_top_y; - s->current_picture.motion_val[1][xy + 1][0] = motion_back_top_x; - s->current_picture.motion_val[1][xy + 1][1] = motion_back_top_y; - s->current_picture.motion_val[1][xy + wrap][0] = motion_back_bottom_x; - s->current_picture.motion_val[1][xy + wrap][1] = motion_back_bottom_y; - s->current_picture.motion_val[1][xy + 1 + wrap][0] = motion_back_bottom_x; - s->current_picture.motion_val[1][xy + 1 + wrap][1] = motion_back_bottom_y; } s->dest[0] += 16; @@ -2259,6 +2296,39 @@ eos: // end of slice return 0; } +static int slice_decode_thread(AVCodecContext *c, void *arg){ + MpegEncContext *s= arg; + const uint8_t *buf= s->gb.buffer; + int mb_y= s->start_mb_y; + + s->error_count= 3*(s->end_mb_y - s->start_mb_y)*s->mb_width; + + for(;;){ + int start_code, ret; + + ret= mpeg_decode_slice((Mpeg1Context*)s, mb_y, &buf, s->gb.buffer_end - buf); + emms_c(); +//av_log(c, AV_LOG_DEBUG, "ret:%d resync:%d/%d mb:%d/%d ts:%d/%d ec:%d\n", +//ret, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, s->start_mb_y, s->end_mb_y, s->error_count); + if(ret < 0){ + if(s->resync_mb_x>=0 && s->resync_mb_y>=0) + ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, AC_ERROR|DC_ERROR|MV_ERROR); + }else{ + ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, AC_END|DC_END|MV_END); + } + + if(s->mb_y == s->end_mb_y) + return 0; + + start_code = find_start_code(&buf, s->gb.buffer_end); + mb_y= start_code - SLICE_MIN_START_CODE; + if(mb_y < 0 || mb_y >= s->end_mb_y) + return -1; + } + + return 0; //not reached +} + /** * handles slice ends. * @return 1 if it seems to be the last slice of @@ -2305,7 +2375,7 @@ static int slice_end(AVCodecContext *avctx, AVFrame *pict) } static int mpeg1_decode_sequence(AVCodecContext *avctx, - uint8_t *buf, int buf_size) + const uint8_t *buf, int buf_size) { Mpeg1Context *s1 = avctx->priv_data; MpegEncContext *s = &s1->mpeg_enc_ctx; @@ -2323,7 +2393,7 @@ static int mpeg1_decode_sequence(AVCodecContext *avctx, avctx->sample_aspect_ratio= av_d2q(aspect, 255); s->frame_rate_index = get_bits(&s->gb, 4); - if (s->frame_rate_index == 0) + if (s->frame_rate_index == 0 || s->frame_rate_index > 13) return -1; s->bit_rate = get_bits(&s->gb, 18) * 400; if (get_bits1(&s->gb) == 0) /* marker */ @@ -2343,17 +2413,16 @@ static int mpeg1_decode_sequence(AVCodecContext *avctx, avctx->has_b_frames= 1; avctx->width = width; avctx->height = height; - av_reduce( - &avctx->frame_rate, - &avctx->frame_rate_base, - frame_rate_tab[s->frame_rate_index], - MPEG1_FRAME_RATE_BASE, //FIXME store in allready reduced form - 1<<30 - ); + avctx->frame_rate = frame_rate_tab[s->frame_rate_index].num; + avctx->frame_rate_base= frame_rate_tab[s->frame_rate_index].den; avctx->bit_rate = s->bit_rate; - //get_format() or set_video(width,height,aspect,pix_fmt); - //until then pix_fmt may be changed right after codec init + if(avctx->xvmc_acceleration){ + avctx->pix_fmt = avctx->get_format(avctx,pixfmt_xvmc_mpg2_420); + }else{ + avctx->pix_fmt = avctx->get_format(avctx,pixfmt_yuv_420); + } + if( avctx->pix_fmt == PIX_FMT_XVMC_MPEG2_IDCT ) if( avctx->idct_algo == FF_IDCT_AUTO ) avctx->idct_algo = FF_IDCT_SIMPLE; @@ -2371,6 +2440,10 @@ static int mpeg1_decode_sequence(AVCodecContext *avctx, if (get_bits1(&s->gb)) { for(i=0;i<64;i++) { v = get_bits(&s->gb, 8); + if(v==0){ + av_log(s->avctx, AV_LOG_ERROR, "intra matrix damaged\n"); + return -1; + } j = s->intra_scantable.permutated[i]; s->intra_matrix[j] = v; s->chroma_intra_matrix[j] = v; @@ -2392,6 +2465,10 @@ static int mpeg1_decode_sequence(AVCodecContext *avctx, if (get_bits1(&s->gb)) { for(i=0;i<64;i++) { v = get_bits(&s->gb, 8); + if(v==0){ + av_log(s->avctx, AV_LOG_ERROR, "inter matrix damaged\n"); + return -1; + } j = s->intra_scantable.permutated[i]; s->inter_matrix[j] = v; s->chroma_inter_matrix[j] = v; @@ -2410,12 +2487,18 @@ static int mpeg1_decode_sequence(AVCodecContext *avctx, s->chroma_inter_matrix[j] = v; } } + + if(show_bits(&s->gb, 23) != 0){ + av_log(s->avctx, AV_LOG_ERROR, "sequence header damaged\n"); + return -1; + } /* we set mpeg2 parameters so that it emulates mpeg1 */ s->progressive_sequence = 1; s->progressive_frame = 1; s->picture_structure = PICT_FRAME; s->frame_pred_frame_dct = 1; + s->chroma_format = 1; s->codec_id= s->avctx->codec_id= CODEC_ID_MPEG1VIDEO; avctx->sub_id = 1; /* indicates mpeg1 */ if(s->flags & CODEC_FLAG_LOW_DELAY) s->low_delay=1; @@ -2443,8 +2526,12 @@ static int vcr2_init_sequence(AVCodecContext *avctx) avctx->has_b_frames= 0; //true? s->low_delay= 1; - //get_format() or set_video(width,height,aspect,pix_fmt); - //until then pix_fmt may be changed right after codec init + if(avctx->xvmc_acceleration){ + avctx->pix_fmt = avctx->get_format(avctx,pixfmt_xvmc_mpg2_420); + }else{ + avctx->pix_fmt = avctx->get_format(avctx,pixfmt_yuv_420); + } + if( avctx->pix_fmt == PIX_FMT_XVMC_MPEG2_IDCT ) if( avctx->idct_algo == FF_IDCT_AUTO ) avctx->idct_algo = FF_IDCT_SIMPLE; @@ -2470,6 +2557,7 @@ static int vcr2_init_sequence(AVCodecContext *avctx) s->progressive_frame = 1; s->picture_structure = PICT_FRAME; s->frame_pred_frame_dct = 1; + s->chroma_format = 1; s->codec_id= s->avctx->codec_id= CODEC_ID_MPEG2VIDEO; avctx->sub_id = 2; /* indicates mpeg2 */ return 0; @@ -2550,7 +2638,8 @@ static int mpeg_decode_frame(AVCodecContext *avctx, uint8_t *buf, int buf_size) { Mpeg1Context *s = avctx->priv_data; - uint8_t *buf_end, *buf_ptr; + const uint8_t *buf_end; + const uint8_t *buf_ptr; int ret, start_code, input_size; AVFrame *picture = data; MpegEncContext *s2 = &s->mpeg_enc_ctx; @@ -2591,12 +2680,21 @@ static int mpeg_decode_frame(AVCodecContext *avctx, if(s->mpeg_enc_ctx_allocated==0 && avctx->codec_tag == ff_get_fourcc("VCR2")) vcr2_init_sequence(avctx); - + + s->slice_count= 0; + for(;;) { /* find start next code */ start_code = find_start_code(&buf_ptr, buf_end); if (start_code < 0){ if(s2->pict_type != B_TYPE || avctx->hurry_up==0){ + if(avctx->thread_count > 1){ + int i; + + avctx->execute(avctx, slice_decode_thread, (void**)&(s2->thread_context[0]), NULL, s->slice_count); + for(i=0; i<s->slice_count; i++) + s2->error_count += s2->thread_context[i]->error_count; + } if (slice_end(avctx, picture)) { if(s2->last_picture_ptr || s2->low_delay) //FIXME merge with the stuff in mpeg_decode_slice *data_size = sizeof(AVPicture); @@ -2615,13 +2713,13 @@ static int mpeg_decode_frame(AVCodecContext *avctx, switch(start_code) { case SEQ_START_CODE: mpeg1_decode_sequence(avctx, buf_ptr, - input_size); + input_size); break; case PICTURE_START_CODE: /* we have a complete image : we try to decompress it */ mpeg1_decode_picture(avctx, - buf_ptr, input_size); + buf_ptr, input_size); break; case EXT_START_CODE: mpeg_decode_extension(avctx, @@ -2637,6 +2735,7 @@ static int mpeg_decode_frame(AVCodecContext *avctx, default: if (start_code >= SLICE_MIN_START_CODE && start_code <= SLICE_MAX_START_CODE) { + int mb_y= start_code - SLICE_MIN_START_CODE; /* skip b frames if we dont have reference frames */ if(s2->last_picture_ptr==NULL && s2->pict_type==B_TYPE) break; @@ -2646,17 +2745,38 @@ static int mpeg_decode_frame(AVCodecContext *avctx, if(avctx->hurry_up>=5) break; if (!s->mpeg_enc_ctx_allocated) break; - - ret = mpeg_decode_slice(avctx, picture, - start_code, &buf_ptr, input_size); - emms_c(); - - if(ret < 0){ - if(s2->resync_mb_x>=0 && s2->resync_mb_y>=0) - ff_er_add_slice(s2, s2->resync_mb_x, s2->resync_mb_y, s2->mb_x, s2->mb_y, AC_ERROR|DC_ERROR|MV_ERROR); - if(ret==DECODE_SLICE_FATAL_ERROR) return -1; + + if(s2->first_slice){ + s2->first_slice=0; + if(mpeg_field_start(s2) < 0) + return -1; + } + + if(avctx->thread_count > 1){ + int threshold= (s2->mb_height*s->slice_count + avctx->thread_count/2) / avctx->thread_count; + if(threshold <= mb_y){ + MpegEncContext *thread_context= s2->thread_context[s->slice_count]; + + thread_context->start_mb_y= mb_y; + thread_context->end_mb_y = s2->mb_height; + if(s->slice_count){ + s2->thread_context[s->slice_count-1]->end_mb_y= mb_y; + ff_update_duplicate_context(thread_context, s2); + } + init_get_bits(&thread_context->gb, buf_ptr, input_size*8); + s->slice_count++; + } + buf_ptr += 2; //FIXME add minimum num of bytes per slice }else{ - ff_er_add_slice(s2, s2->resync_mb_x, s2->resync_mb_y, s2->mb_x-1, s2->mb_y, AC_END|DC_END|MV_END); + ret = mpeg_decode_slice(s, mb_y, &buf_ptr, input_size); + emms_c(); + + if(ret < 0){ + if(s2->resync_mb_x>=0 && s2->resync_mb_y>=0) + ff_er_add_slice(s2, s2->resync_mb_x, s2->resync_mb_y, s2->mb_x, s2->mb_y, AC_ERROR|DC_ERROR|MV_ERROR); + }else{ + ff_er_add_slice(s2, s2->resync_mb_x, s2->resync_mb_y, s2->mb_x-1, s2->mb_y, AC_END|DC_END|MV_END); + } } } break; @@ -2713,7 +2833,7 @@ AVCodec mpegvideo_decoder = { .flush= ff_mpeg_flush, }; -#if defined(CONFIG_ENCODERS) || defined(XINE_MPEG_ENCODER) +#ifdef CONFIG_ENCODERS AVCodec mpeg1video_encoder = { "mpeg1video", @@ -2723,6 +2843,7 @@ AVCodec mpeg1video_encoder = { encode_init, MPV_encode_picture, MPV_encode_end, + .supported_framerates= frame_rate_tab+1, }; #ifdef CONFIG_RISKY @@ -2735,6 +2856,7 @@ AVCodec mpeg2video_encoder = { encode_init, MPV_encode_picture, MPV_encode_end, + .supported_framerates= frame_rate_tab+1, }; #endif #endif @@ -2766,7 +2888,8 @@ AVCodec mpeg_xvmc_decoder = { NULL, mpeg_decode_end, mpeg_decode_frame, - CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED, + CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED| CODEC_CAP_HWACCEL, + .flush= ff_mpeg_flush, }; #endif |