diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index e6e03389c2..b29653ec9f 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -291,6 +291,8 @@ extern int motion_estimation_method; used */ #define CODEC_CAP_PARSE_ONLY 0x0004 #define CODEC_CAP_TRUNCATED 0x0008 +/* codec can export data for HW decoding (XvMC) */ +#define CODEC_CAP_HWACCEL 0x0010 //the following defines might change, so dont expect compatibility if u use them #define MB_TYPE_INTRA4x4 0x0001 diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c index 98fca0a3ea..ee99bd1671 100644 --- a/libavcodec/mpeg12.c +++ b/libavcodec/mpeg12.c @@ -1010,7 +1010,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; @@ -1026,7 +1026,7 @@ 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; if(s->picture_structure == PICT_FRAME) s->mv_type = MV_TYPE_16X16; @@ -1126,7 +1126,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<chroma_format);i++) { if (mpeg2_decode_block_intra(s, s->pblocks[i], i) < 0) return -1; } @@ -1311,6 +1311,12 @@ static int mpeg_decode_mb(MpegEncContext *s, 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 @@ -1324,13 +1330,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++) { @@ -1654,7 +1680,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) @@ -1817,13 +1843,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; @@ -2556,6 +2582,37 @@ static void mpeg_decode_user_data(AVCodecContext *avctx, } } +static void mpeg_decode_gop(AVCodecContext *avctx, + uint8_t *buf, int buf_size){ + Mpeg1Context *s1 = avctx->priv_data; + MpegEncContext *s = &s1->mpeg_enc_ctx; + + int drop_frame_flag; + int time_code_hours, time_code_minutes; + int time_code_seconds, time_code_pictures; + int broken_link; + + s->first_field = 0; + + init_get_bits(&s->gb, buf, buf_size*8); + + drop_frame_flag = get_bits1(&s->gb); + + time_code_hours=get_bits(&s->gb,5); + time_code_minutes = get_bits(&s->gb,6); + skip_bits1(&s->gb);//marker bit + time_code_seconds = get_bits(&s->gb,6); + time_code_pictures = get_bits(&s->gb,6); + /*broken_link indicate that after editing the + reference frames of the first B-Frames after GOP I-Frame + are missing (open gop)*/ + broken_link = get_bits1(&s->gb); + if(broken_link == 1){ +// avcodec_flush_buffers(avctx); + ff_mpeg_flush(avctx); + } +} + /** * finds the end of the current frame in the bitstream. * @return the position of the first byte of the next frame, or -1 @@ -2692,7 +2749,7 @@ static int mpeg_decode_frame(AVCodecContext *avctx, buf_ptr, input_size); break; case GOP_START_CODE: - s2->first_field=0; + mpeg_decode_gop(avctx, buf_ptr, input_size); break; default: if (start_code >= SLICE_MIN_START_CODE && @@ -2850,7 +2907,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 diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 828e74a668..7a9889b83a 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -267,8 +267,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; } @@ -424,7 +422,7 @@ static int init_duplicate_context(MpegEncContext *s, MpegEncContext *base){ CHECKED_ALLOCZ(s->dct_error_sum, 2 * 64 * sizeof(int)) } } - CHECKED_ALLOCZ(s->blocks, 64*6*2 * sizeof(DCTELEM)) + CHECKED_ALLOCZ(s->blocks, 64*12*2 * sizeof(DCTELEM)) s->block= s->blocks[0]; for(i=0;i<12;i++){ @@ -539,9 +537,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); diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 51cc5e1001..3c3dcdb112 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -355,6 +355,9 @@ typedef struct MpegEncContext { int last_pict_type; int last_non_b_pict_type; ///< used for mpeg4 gmc b-frames & ratecontrol int frame_rate_index; + int frame_rate_ext_n; ///< MPEG-2 specific framerate modificators (numerator) + int frame_rate_ext_d; ///< MPEG-2 specific framerate modificators (denominator) + /* motion compensation */ int unrestricted_mv; ///< mv can point outside of the coded picture int h263_long_vectors; ///< use horrible h263v1 long vector mode @@ -465,7 +468,7 @@ typedef struct MpegEncContext { /** identical to the above but for MMX & these are not permutated, second 64 entries are bias*/ uint16_t (*q_intra_matrix16)[2][64]; uint16_t (*q_inter_matrix16)[2][64]; - int block_last_index[6]; ///< last non zero coefficient in block + int block_last_index[12]; ///< last non zero coefficient in block /* scantables */ ScanTable __align8 intra_scantable; ScanTable intra_h_scantable; @@ -653,6 +656,11 @@ typedef struct MpegEncContext { int alternate_scan; int repeat_first_field; int chroma_420_type; + int chroma_format; +#define CHROMA_420 1 +#define CHROMA_422 2 +#define CHROMA_444 3 + int progressive_frame; int full_pel[2]; int interlaced_dct; diff --git a/libavcodec/xvmcvideo.c b/libavcodec/xvmcvideo.c index eed9860338..cd64f4c3af 100644 --- a/libavcodec/xvmcvideo.c +++ b/libavcodec/xvmcvideo.c @@ -55,27 +55,66 @@ xvmc_render_state_t * render; void XVMC_pack_pblocks(MpegEncContext *s, int cbp){ int i,j; -#define numblocks 6 j=0; - for(i=0;ipblocks[i] = (short *)(&s->block[(j++)]); }else{ s->pblocks[i] = NULL; } // printf("s->pblocks[%d]=%p ,s->block=%p cbp=%d\n",i,s->pblocks[i],s->block,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)) ){ + s->pblocks[i] = (short *)(&s->block[(j++)]); + }else{ + s->pblocks[i] = NULL; + } + } + }else{//CHROMA_444 + for(i=6; i<12; i++){ + if(cbp & (1<<(6+11-i)) ){ + s->pblocks[i] = (short *)(&s->block[(j++)]); + }else{ + s->pblocks[i] = NULL; + } + } + } + } } -static int calc_cbp(MpegEncContext *s, int blocknum){ +static int calc_cbp(MpegEncContext *s){ /* compute cbp */ -// for I420 bit_offset=5 int i,cbp = 0; - for(i=0; iblock_last_index[i] >= 0) cbp |= 1 << (5 - i); } + if(s->flags & CODEC_FLAG_GRAY) + return cbp; //4 block for grayscale one done + + + for(i=4; i<6; i++) { + if(s->block_last_index[i] >= 0) + cbp |= 1 << (5 - i); + } + if(s->chroma_format < 2) return cbp; + + + if(s->chroma_format == 2){/*CHROMA_422*/ + for(i=6; i<8; i++) { + if(s->block_last_index[i] >= 0) + cbp |= 1 << (6+7 - i); + } + }else{/*CHROMA_444*/ + for(i=6; i<12; i++) { + if(s->block_last_index[i] >= 0) + cbp |= 1 << (6+11 - i); + } + } return cbp; } @@ -121,7 +160,7 @@ xvmc_render_state_t * render,* last, * next; assert(last->state & MP_XVMC_STATE_PREDICTION); render->p_past_surface = last->p_surface; return 0; - } + } return -1; } @@ -256,17 +295,12 @@ const int mb_xy = s->mb_y * s->mb_stride + s->mb_x; }//!intra //time to handle data blocks; mv_block->index = render->next_free_data_block_num; + blocks_per_mb = 6; -/* - switch( s->chroma_format){ - case CHROMA_422: - blocks_per_mb = 8; - break; - case CHROMA_444: - blocks_per_mb = 12; - break; + if( s->chroma_format >= 2){ + block_per_mb = 4 + (1 << (s->chroma_format)); } -*/ + if(s->flags & CODEC_FLAG_GRAY){ if(s->mb_intra){//intra frames are alwasy full chroma block for(i=4; imb_y * s->mb_stride + s->mb_x; }else blocks_per_mb = 4;//Luminance blocks only } - cbp = calc_cbp(s,blocks_per_mb); + cbp = calc_cbp(s); mv_block->coded_block_pattern = cbp; if(cbp == 0) mv_block->macroblock_type &= ~XVMC_MB_TYPE_PATTERN;