X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fmpeg12.c;h=7eddabcaca56fb3c0b9c9ec105addea681d6aa2d;hb=7cd7d19e86f98a0806429a623bb0b010a24ce93a;hp=8d97103ca5eee8179977a979633c666ff2b0a95e;hpb=e7edb2ea93360a6a10c188724cd7489068add26c;p=ffmpeg diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c index 8d97103ca5e..7eddabcaca5 100644 --- a/libavcodec/mpeg12.c +++ b/libavcodec/mpeg12.c @@ -1,6 +1,6 @@ /* * MPEG-1/2 decoder - * Copyright (c) 2000,2001 Fabrice Bellard. + * Copyright (c) 2000,2001 Fabrice Bellard * Copyright (c) 2002-2004 Michael Niedermayer * * This file is part of FFmpeg. @@ -21,11 +21,12 @@ */ /** - * @file mpeg12.c + * @file libavcodec/mpeg12.c * MPEG-1/2 decoder */ //#define DEBUG +#include "internal.h" #include "avcodec.h" #include "dsputil.h" #include "mpegvideo.h" @@ -35,6 +36,7 @@ #include "mpeg12decdata.h" #include "bytestream.h" #include "vdpau_internal.h" +#include "xvmc_internal.h" //#undef NDEBUG //#include @@ -46,10 +48,10 @@ #define MB_PTYPE_VLC_BITS 6 #define MB_BTYPE_VLC_BITS 6 -static inline int mpeg1_decode_block_inter(MpegEncContext *s, +static inline int mpeg1_decode_block_intra(MpegEncContext *s, DCTELEM *block, int n); -static inline int mpeg1_decode_block_intra(MpegEncContext *s, +static inline int mpeg1_decode_block_inter(MpegEncContext *s, DCTELEM *block, int n); static inline int mpeg1_fast_decode_block_inter(MpegEncContext *s, DCTELEM *block, int n); @@ -64,11 +66,6 @@ static inline int mpeg2_fast_decode_block_intra(MpegEncContext *s, DCTELEM *bloc static int mpeg_decode_motion(MpegEncContext *s, int fcode, int pred); static void exchange_uv(MpegEncContext *s); -int XVMC_field_start(MpegEncContext *s, AVCodecContext *avctx); -int XVMC_field_end(MpegEncContext *s); -void XVMC_pack_pblocks(MpegEncContext *s,int cbp); -void XVMC_init_block(MpegEncContext *s);//set s->block - static const enum PixelFormat pixfmt_xvmc_mpg2_420[] = { PIX_FMT_XVMC_MPEG2_IDCT, PIX_FMT_XVMC_MPEG2_MC, @@ -304,30 +301,28 @@ static int mpeg_decode_mb(MpegEncContext *s, }else memset(s->last_mv, 0, sizeof(s->last_mv)); /* reset mv prediction */ s->mb_intra = 1; -#if CONFIG_XVMC //if 1, we memcpy blocks in xvmcvideo - if(s->avctx->xvmc_acceleration > 1){ - XVMC_pack_pblocks(s,-1);//inter are always full blocks + if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration > 1){ + ff_xvmc_pack_pblocks(s,-1);//inter are always full blocks if(s->swap_uv){ exchange_uv(s); } } -#endif if (s->codec_id == CODEC_ID_MPEG2VIDEO) { if(s->flags2 & CODEC_FLAG2_FAST){ for(i=0;i<6;i++) { - mpeg2_fast_decode_block_intra(s, s->pblocks[i], i); + mpeg2_fast_decode_block_intra(s, *s->pblocks[i], i); } }else{ for(i=0;ipblocks[i], i) < 0) + if (mpeg2_decode_block_intra(s, *s->pblocks[i], i) < 0) return -1; } } } else { for(i=0;i<6;i++) { - if (mpeg1_decode_block_intra(s, s->pblocks[i], i) < 0) + if (mpeg1_decode_block_intra(s, *s->pblocks[i], i) < 0) return -1; } } @@ -453,18 +448,20 @@ static int mpeg_decode_mb(MpegEncContext *s, for(i=0;i<2;i++) { if (USES_LIST(mb_type, i)) { int dmx, dmy, mx, my, m; + const int my_shift= s->picture_structure == PICT_FRAME; + mx = mpeg_decode_motion(s, s->mpeg_f_code[i][0], s->last_mv[i][0][0]); s->last_mv[i][0][0] = mx; s->last_mv[i][1][0] = mx; dmx = get_dmv(s); my = mpeg_decode_motion(s, s->mpeg_f_code[i][1], - s->last_mv[i][0][1] >> 1); + s->last_mv[i][0][1] >> my_shift); dmy = get_dmv(s); - s->last_mv[i][0][1] = my<<1; - s->last_mv[i][1][1] = my<<1; + s->last_mv[i][0][1] = my<last_mv[i][1][1] = my<mv[i][0][0] = mx; s->mv[i][0][1] = my; @@ -517,21 +514,19 @@ static int mpeg_decode_mb(MpegEncContext *s, return -1; } -#if CONFIG_XVMC //if 1, we memcpy blocks in xvmcvideo - if(s->avctx->xvmc_acceleration > 1){ - XVMC_pack_pblocks(s,cbp); + if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration > 1){ + ff_xvmc_pack_pblocks(s,cbp); if(s->swap_uv){ exchange_uv(s); } } -#endif if (s->codec_id == CODEC_ID_MPEG2VIDEO) { if(s->flags2 & CODEC_FLAG2_FAST){ for(i=0;i<6;i++) { if(cbp & 32) { - mpeg2_fast_decode_block_non_intra(s, s->pblocks[i], i); + mpeg2_fast_decode_block_non_intra(s, *s->pblocks[i], i); } else { s->block_last_index[i] = -1; } @@ -542,7 +537,7 @@ static int mpeg_decode_mb(MpegEncContext *s, for(i=0;ipblocks[i], i) < 0) + if (mpeg2_decode_block_non_intra(s, *s->pblocks[i], i) < 0) return -1; } else { s->block_last_index[i] = -1; @@ -554,7 +549,7 @@ static int mpeg_decode_mb(MpegEncContext *s, if(s->flags2 & CODEC_FLAG2_FAST){ for(i=0;i<6;i++) { if (cbp & 32) { - mpeg1_fast_decode_block_inter(s, s->pblocks[i], i); + mpeg1_fast_decode_block_inter(s, *s->pblocks[i], i); } else { s->block_last_index[i] = -1; } @@ -563,7 +558,7 @@ static int mpeg_decode_mb(MpegEncContext *s, }else{ for(i=0;i<6;i++) { if (cbp & 32) { - if (mpeg1_decode_block_inter(s, s->pblocks[i], i) < 0) + if (mpeg1_decode_block_inter(s, *s->pblocks[i], i) < 0) return -1; } else { s->block_last_index[i] = -1; @@ -633,7 +628,7 @@ static inline int mpeg1_decode_block_intra(MpegEncContext *s, dc = s->last_dc[component]; dc += diff; s->last_dc[component] = dc; - block[0] = dc<<3; + block[0] = dc*quant_matrix[0]; dprintf(s->avctx, "dc=%d diff=%d\n", dc, diff); i = 0; { @@ -687,6 +682,13 @@ static inline int mpeg1_decode_block_intra(MpegEncContext *s, return 0; } +int ff_mpeg1_decode_block_intra(MpegEncContext *s, + DCTELEM *block, + int n) +{ + return mpeg1_decode_block_intra(s, block, n); +} + static inline int mpeg1_decode_block_inter(MpegEncContext *s, DCTELEM *block, int n) @@ -1170,9 +1172,9 @@ typedef struct Mpeg1Context { int slice_count; int swap_uv;//indicate VCR2 int save_aspect_info; - int save_width, save_height; + int save_width, save_height, save_progressive_seq; AVRational frame_rate_ext; ///< MPEG-2 specific framerate modificator - + int sync; ///< Did we reach a sync point like a GOP/SEQ/KEYFrame? } Mpeg1Context; static av_cold int mpeg_decode_init(AVCodecContext *avctx) @@ -1198,6 +1200,11 @@ static av_cold int mpeg_decode_init(AVCodecContext *avctx) s->mpeg_enc_ctx.picture_number = 0; s->repeat_field = 0; s->mpeg_enc_ctx.codec_id= avctx->codec->id; + avctx->color_range= AVCOL_RANGE_MPEG; + if (avctx->codec->id == CODEC_ID_MPEG1VIDEO) + avctx->chroma_sample_location = AVCHROMA_LOC_CENTER; + else + avctx->chroma_sample_location = AVCHROMA_LOC_LEFT; return 0; } @@ -1226,7 +1233,7 @@ static enum PixelFormat mpeg_get_pixelformat(AVCodecContext *avctx){ return PIX_FMT_VDPAU_MPEG2; }else{ if(s->chroma_format < 2) - return PIX_FMT_YUV420P; + return avctx->get_format(avctx,ff_hwaccel_pixfmt_list_420); else if(s->chroma_format == 2) return PIX_FMT_YUV422P; else @@ -1248,6 +1255,7 @@ static int mpeg_decode_postinit(AVCodecContext *avctx){ s1->save_width != s->width || s1->save_height != s->height || s1->save_aspect_info != s->aspect_ratio_info|| + s1->save_progressive_seq != s->progressive_sequence || 0) { @@ -1266,6 +1274,7 @@ static int mpeg_decode_postinit(AVCodecContext *avctx){ s1->save_aspect_info = s->aspect_ratio_info; s1->save_width = s->width; s1->save_height = s->height; + s1->save_progressive_seq = s->progressive_sequence; /* low_delay may be forced, in this case we will have B-frames * that behave like P-frames. */ @@ -1279,15 +1288,16 @@ static int mpeg_decode_postinit(AVCodecContext *avctx){ //MPEG-1 aspect avctx->sample_aspect_ratio= av_d2q( 1.0/ff_mpeg1_aspect[s->aspect_ratio_info], 255); - + avctx->ticks_per_frame=1; }else{//MPEG-2 //MPEG-2 fps av_reduce( &s->avctx->time_base.den, &s->avctx->time_base.num, - ff_frame_rate_tab[s->frame_rate_index].num * s1->frame_rate_ext.num, + ff_frame_rate_tab[s->frame_rate_index].num * s1->frame_rate_ext.num*2, ff_frame_rate_tab[s->frame_rate_index].den * s1->frame_rate_ext.den, 1<<30); + avctx->ticks_per_frame=2; //MPEG-2 aspect if(s->aspect_ratio_info > 1){ //we ignore the spec here as reality does not match the spec, see for example @@ -1312,8 +1322,10 @@ static int mpeg_decode_postinit(AVCodecContext *avctx){ }//MPEG-2 avctx->pix_fmt = mpeg_get_pixelformat(avctx); + avctx->hwaccel = ff_find_hwaccel(avctx->codec->id, avctx->pix_fmt); //until then pix_fmt may be changed right after codec init if( avctx->pix_fmt == PIX_FMT_XVMC_MPEG2_IDCT || + avctx->hwaccel || s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU ) if( avctx->idct_algo == FF_IDCT_AUTO ) avctx->idct_algo = FF_IDCT_SIMPLE; @@ -1342,9 +1354,6 @@ static int mpeg1_decode_picture(AVCodecContext *avctx, MpegEncContext *s = &s1->mpeg_enc_ctx; int ref, f_code, vbv_delay; - if(mpeg_decode_postinit(s->avctx) < 0) - return -2; - init_get_bits(&s->gb, buf, buf_size*8); ref = get_bits(&s->gb, 10); /* temporal ref */ @@ -1377,7 +1386,6 @@ static int mpeg1_decode_picture(AVCodecContext *avctx, s->y_dc_scale = 8; s->c_dc_scale = 8; - s->first_slice = 1; return 0; } @@ -1425,9 +1433,9 @@ static void mpeg_decode_sequence_display_extension(Mpeg1Context *s1) skip_bits(&s->gb, 3); /* video format */ color_description= get_bits1(&s->gb); if(color_description){ - skip_bits(&s->gb, 8); /* color primaries */ - skip_bits(&s->gb, 8); /* transfer_characteristics */ - skip_bits(&s->gb, 8); /* matrix_coefficients */ + s->avctx->color_primaries= get_bits(&s->gb, 8); + s->avctx->color_trc = get_bits(&s->gb, 8); + s->avctx->colorspace = get_bits(&s->gb, 8); } w= get_bits(&s->gb, 14); skip_bits(&s->gb, 1); //marker @@ -1475,42 +1483,35 @@ static void mpeg_decode_picture_display_extension(Mpeg1Context *s1) ); } -static void mpeg_decode_quant_matrix_extension(MpegEncContext *s) -{ - int i, v, j; - - dprintf(s->avctx, "matrix extension\n"); +static int load_matrix(MpegEncContext *s, uint16_t matrix0[64], uint16_t matrix1[64], int intra){ + int i; - if (get_bits1(&s->gb)) { - for(i=0;i<64;i++) { - v = get_bits(&s->gb, 8); - j= s->dsp.idct_permutation[ ff_zigzag_direct[i] ]; - s->intra_matrix[j] = v; - s->chroma_intra_matrix[j] = v; - } - } - if (get_bits1(&s->gb)) { - for(i=0;i<64;i++) { - v = get_bits(&s->gb, 8); - j= s->dsp.idct_permutation[ ff_zigzag_direct[i] ]; - s->inter_matrix[j] = v; - s->chroma_inter_matrix[j] = v; - } - } - if (get_bits1(&s->gb)) { - for(i=0;i<64;i++) { - v = get_bits(&s->gb, 8); - j= s->dsp.idct_permutation[ ff_zigzag_direct[i] ]; - s->chroma_intra_matrix[j] = v; + for(i=0; i<64; i++) { + int j = s->dsp.idct_permutation[ ff_zigzag_direct[i] ]; + int v = get_bits(&s->gb, 8); + if(v==0){ + av_log(s->avctx, AV_LOG_ERROR, "matrix damaged\n"); + return -1; } - } - if (get_bits1(&s->gb)) { - for(i=0;i<64;i++) { - v = get_bits(&s->gb, 8); - j= s->dsp.idct_permutation[ ff_zigzag_direct[i] ]; - s->chroma_inter_matrix[j] = v; + if(intra && i==0 && v!=8){ + av_log(s->avctx, AV_LOG_ERROR, "intra matrix invalid, ignoring\n"); + v= 8; // needed by pink.mpg / issue1046 } + matrix0[j] = v; + if(matrix1) + matrix1[j] = v; } + return 0; +} + +static void mpeg_decode_quant_matrix_extension(MpegEncContext *s) +{ + dprintf(s->avctx, "matrix extension\n"); + + if(get_bits1(&s->gb)) load_matrix(s, s->chroma_intra_matrix, s->intra_matrix, 1); + if(get_bits1(&s->gb)) load_matrix(s, s->chroma_inter_matrix, s->inter_matrix, 0); + if(get_bits1(&s->gb)) load_matrix(s, s->chroma_intra_matrix, NULL , 1); + if(get_bits1(&s->gb)) load_matrix(s, s->chroma_inter_matrix, NULL , 0); } static void mpeg_decode_picture_coding_extension(Mpeg1Context *s1) @@ -1533,7 +1534,6 @@ static void mpeg_decode_picture_coding_extension(Mpeg1Context *s1) s->pict_type= FF_B_TYPE; s->current_picture.pict_type= s->pict_type; s->current_picture.key_frame= s->pict_type == FF_I_TYPE; - s->first_slice= 1; } s->intra_dc_precision = get_bits(&s->gb, 2); s->picture_structure = get_bits(&s->gb, 2); @@ -1547,6 +1547,21 @@ static void mpeg_decode_picture_coding_extension(Mpeg1Context *s1) s->chroma_420_type = get_bits1(&s->gb); s->progressive_frame = get_bits1(&s->gb); + if(s->progressive_sequence && !s->progressive_frame){ + s->progressive_frame= 1; + av_log(s->avctx, AV_LOG_ERROR, "interlaced frame in progressive sequence, ignoring\n"); + } + + if(s->picture_structure==0 || (s->progressive_frame && s->picture_structure!=PICT_FRAME)){ + av_log(s->avctx, AV_LOG_ERROR, "picture_structure %d invalid, ignoring\n", s->picture_structure); + s->picture_structure= PICT_FRAME; + } + + if(s->progressive_sequence && !s->frame_pred_frame_dct){ + av_log(s->avctx, AV_LOG_ERROR, "invalid frame_pred_frame_dct\n"); + s->frame_pred_frame_dct= 1; + } + if(s->picture_structure == PICT_FRAME){ s->first_field=0; s->v_edge_pos= 16*s->mb_height; @@ -1576,42 +1591,15 @@ static void mpeg_decode_picture_coding_extension(Mpeg1Context *s1) dprintf(s->avctx, "progressive_frame=%d\n", s->progressive_frame); } -static void mpeg_decode_extension(AVCodecContext *avctx, - const uint8_t *buf, int buf_size) -{ - Mpeg1Context *s1 = avctx->priv_data; - MpegEncContext *s = &s1->mpeg_enc_ctx; - int ext_type; - - init_get_bits(&s->gb, buf, buf_size*8); - - ext_type = get_bits(&s->gb, 4); - switch(ext_type) { - case 0x1: - mpeg_decode_sequence_extension(s1); - break; - case 0x2: - mpeg_decode_sequence_display_extension(s1); - break; - case 0x3: - mpeg_decode_quant_matrix_extension(s); - break; - case 0x7: - mpeg_decode_picture_display_extension(s1); - break; - case 0x8: - mpeg_decode_picture_coding_extension(s1); - break; - } -} - static void exchange_uv(MpegEncContext *s){ - short * tmp = s->pblocks[4]; + DCTELEM (*tmp)[64]; + + tmp = s->pblocks[4]; s->pblocks[4] = s->pblocks[5]; s->pblocks[5] = tmp; } -static int mpeg_field_start(MpegEncContext *s){ +static int mpeg_field_start(MpegEncContext *s, const uint8_t *buf, int buf_size){ AVCodecContext *avctx= s->avctx; Mpeg1Context *s1 = (Mpeg1Context*)s; @@ -1651,12 +1639,17 @@ static int mpeg_field_start(MpegEncContext *s){ } } } -#if CONFIG_XVMC + + if (avctx->hwaccel) { + if (avctx->hwaccel->start_frame(avctx, buf, buf_size) < 0) + return -1; + } + // MPV_frame_start will call this function too, // but we need to call it on every field - if(s->avctx->xvmc_acceleration) - XVMC_field_start(s,avctx); -#endif + if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration) + if(ff_xvmc_field_start(s,avctx) < 0) + return -1; return 0; } @@ -1680,10 +1673,7 @@ static int mpeg_decode_slice(Mpeg1Context *s1, int mb_y, 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", mb_y, s->mb_height); - return -1; - } + assert(mb_y < s->mb_height); init_get_bits(&s->gb, *buf, buf_size*8); @@ -1704,27 +1694,45 @@ static int mpeg_decode_slice(Mpeg1Context *s1, int mb_y, s->mb_x=0; - for(;;) { - int code = get_vlc2(&s->gb, mbincr_vlc.table, MBINCR_VLC_BITS, 2); - if (code < 0){ - av_log(s->avctx, AV_LOG_ERROR, "first mb_incr damaged\n"); - return -1; - } - if (code >= 33) { - if (code == 33) { - s->mb_x += 33; + if(mb_y==0 && s->codec_tag == AV_RL32("SLIF")){ + skip_bits1(&s->gb); + }else{ + for(;;) { + int code = get_vlc2(&s->gb, mbincr_vlc.table, MBINCR_VLC_BITS, 2); + if (code < 0){ + av_log(s->avctx, AV_LOG_ERROR, "first mb_incr damaged\n"); + return -1; + } + if (code >= 33) { + if (code == 33) { + s->mb_x += 33; + } + /* otherwise, stuffing, nothing to do */ + } else { + s->mb_x += code; + break; } - /* otherwise, stuffing, nothing to do */ - } else { - s->mb_x += code; - break; } } + if(s->mb_x >= (unsigned)s->mb_width){ av_log(s->avctx, AV_LOG_ERROR, "initial skip overflow\n"); return -1; } + if (avctx->hwaccel) { + const uint8_t *buf_end, *buf_start = *buf - 4; /* include start_code */ + int start_code = -1; + buf_end = ff_find_start_code(buf_start + 2, *buf + buf_size, &start_code); + if (buf_end < *buf + buf_size) + buf_end -= 4; + s->mb_y = mb_y; + if (avctx->hwaccel->decode_slice(avctx, buf_start, buf_end - buf_start) < 0) + return DECODE_SLICE_ERROR; + *buf = buf_end; + return DECODE_SLICE_OK; + } + s->resync_mb_x= s->mb_x; s->resync_mb_y= s->mb_y= mb_y; s->mb_skip_run= 0; @@ -1742,21 +1750,17 @@ static int mpeg_decode_slice(Mpeg1Context *s1, int mb_y, } for(;;) { -#if CONFIG_XVMC //If 1, we memcpy blocks in xvmcvideo. - if(s->avctx->xvmc_acceleration > 1) - XVMC_init_block(s);//set s->block -#endif + if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration > 1) + ff_xvmc_init_block(s);//set s->block if(mpeg_decode_mb(s, s->block) < 0) return -1; 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->b8_stride : s->b8_stride; + const int wrap = s->b8_stride; int xy = s->mb_x*2 + s->mb_y*2*wrap; int motion_x, motion_y, dir, i; - if(field_pic && !s->first_field) - xy += wrap/2; for(i=0; i<2; i++){ for(dir=0; dir<2; dir++){ @@ -1791,13 +1795,13 @@ static int mpeg_decode_slice(Mpeg1Context *s1, int mb_y, if (++s->mb_x >= s->mb_width) { const int mb_size= 16>>s->avctx->lowres; - ff_draw_horiz_band(s, mb_size*s->mb_y, mb_size); + ff_draw_horiz_band(s, mb_size*(s->mb_y>>field_pic), mb_size); s->mb_x = 0; - s->mb_y++; + s->mb_y += 1<mb_y<= s->mb_height){ - int left= s->gb.size_in_bits - get_bits_count(&s->gb); + if(s->mb_y >= s->mb_height){ + int left= get_bits_left(&s->gb); int is_d10= s->chroma_format==2 && s->pict_type==FF_I_TYPE && avctx->profile==0 && avctx->level==5 && s->intra_dc_precision == 2 && s->q_scale_type == 1 && s->alternate_scan == 0 && s->progressive_frame == 0 /* vbv_delay == 0xBBB || 0xE10*/; @@ -1860,7 +1864,7 @@ static int mpeg_decode_slice(Mpeg1Context *s1, int mb_y, 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->field_select[0][0]= (s->picture_structure - 1) & 1; } else { /* if B type, reuse previous vectors and directions */ s->mv[0][0][0] = s->last_mv[0][0][0]; @@ -1881,8 +1885,9 @@ static int slice_decode_thread(AVCodecContext *c, void *arg){ MpegEncContext *s= *(void**)arg; const uint8_t *buf= s->gb.buffer; int mb_y= s->start_mb_y; + const int field_pic= s->picture_structure != PICT_FRAME; - s->error_count= 3*(s->end_mb_y - s->start_mb_y)*s->mb_width; + s->error_count= (3*(s->end_mb_y - s->start_mb_y)*s->mb_width) >> field_pic; for(;;){ uint32_t start_code; @@ -1924,10 +1929,14 @@ static int slice_end(AVCodecContext *avctx, AVFrame *pict) if (!s1->mpeg_enc_ctx_allocated || !s->current_picture_ptr) return 0; -#if CONFIG_XVMC - if(s->avctx->xvmc_acceleration) - XVMC_field_end(s); -#endif + if (s->avctx->hwaccel) { + if (s->avctx->hwaccel->end_frame(s->avctx) < 0) + av_log(avctx, AV_LOG_ERROR, "hardware accelerator failed to decode picture\n"); + } + + if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration) + ff_xvmc_field_end(s); + /* end of slice reached */ if (/*s->mb_y<mb_height &&*/ !s->first_field) { /* end of image */ @@ -1991,22 +2000,7 @@ static int mpeg1_decode_sequence(AVCodecContext *avctx, /* get matrix */ 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->dsp.idct_permutation[ ff_zigzag_direct[i] ]; - s->intra_matrix[j] = v; - s->chroma_intra_matrix[j] = v; - } -#ifdef DEBUG - dprintf(s->avctx, "intra matrix present\n"); - for(i=0;i<64;i++) - dprintf(s->avctx, " %d", s->intra_matrix[s->dsp.idct_permutation[i]]); - dprintf(s->avctx, "\n"); -#endif + load_matrix(s, s->chroma_intra_matrix, s->intra_matrix, 1); } else { for(i=0;i<64;i++) { j = s->dsp.idct_permutation[i]; @@ -2016,22 +2010,7 @@ 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->dsp.idct_permutation[ ff_zigzag_direct[i] ]; - s->inter_matrix[j] = v; - s->chroma_inter_matrix[j] = v; - } -#ifdef DEBUG - dprintf(s->avctx, "non-intra matrix present\n"); - for(i=0;i<64;i++) - dprintf(s->avctx, " %d", s->inter_matrix[s->dsp.idct_permutation[i]]); - dprintf(s->avctx, "\n"); -#endif + load_matrix(s, s->chroma_inter_matrix, s->inter_matrix, 0); } else { for(i=0;i<64;i++) { int j= s->dsp.idct_permutation[i]; @@ -2082,8 +2061,9 @@ static int vcr2_init_sequence(AVCodecContext *avctx) s->low_delay= 1; avctx->pix_fmt = mpeg_get_pixelformat(avctx); + avctx->hwaccel = ff_find_hwaccel(avctx->codec->id, avctx->pix_fmt); - if( avctx->pix_fmt == PIX_FMT_XVMC_MPEG2_IDCT || + if( avctx->pix_fmt == PIX_FMT_XVMC_MPEG2_IDCT || avctx->hwaccel || s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU ) if( avctx->idct_algo == FF_IDCT_AUTO ) avctx->idct_algo = FF_IDCT_SIMPLE; @@ -2112,33 +2092,29 @@ static int vcr2_init_sequence(AVCodecContext *avctx) s->chroma_format = 1; s->codec_id= s->avctx->codec_id= CODEC_ID_MPEG2VIDEO; avctx->sub_id = 2; /* indicates MPEG-2 */ + s1->save_width = s->width; + s1->save_height = s->height; + s1->save_progressive_seq = s->progressive_sequence; return 0; } static void mpeg_decode_user_data(AVCodecContext *avctx, - const uint8_t *buf, int buf_size) + const uint8_t *p, int buf_size) { - const uint8_t *p; - int len, flags; - p = buf; - len = buf_size; + const uint8_t *buf_end = p+buf_size; /* we parse the DTG active format information */ - if (len >= 5 && + if (buf_end - p >= 5 && p[0] == 'D' && p[1] == 'T' && p[2] == 'G' && p[3] == '1') { - flags = p[4]; + int flags = p[4]; p += 5; - len -= 5; if (flags & 0x80) { /* skip event id */ - if (len < 2) - return; p += 2; - len -= 2; } if (flags & 0x40) { - if (len < 1) + if (buf_end - p < 1) return; avctx->dtg_active_format = p[0] & 0x0f; } @@ -2153,7 +2129,7 @@ static void mpeg_decode_gop(AVCodecContext *avctx, int drop_frame_flag; int time_code_hours, time_code_minutes; int time_code_seconds, time_code_pictures; - int closed_gop, broken_link; + int broken_link; init_get_bits(&s->gb, buf, buf_size*8); @@ -2165,7 +2141,7 @@ static void mpeg_decode_gop(AVCodecContext *avctx, time_code_seconds = get_bits(&s->gb,6); time_code_pictures = get_bits(&s->gb,6); - closed_gop = get_bits1(&s->gb); + s->closed_gop = get_bits1(&s->gb); /*broken_link indicate that after editing the reference frames of the first B-Frames after GOP I-Frame are missing (open gop)*/ @@ -2174,13 +2150,13 @@ static void mpeg_decode_gop(AVCodecContext *avctx, if(s->avctx->debug & FF_DEBUG_PICT_INFO) av_log(s->avctx, AV_LOG_DEBUG, "GOP (%2d:%02d:%02d.[%02d]) closed_gop=%d broken_link=%d\n", time_code_hours, time_code_minutes, time_code_seconds, - time_code_pictures, closed_gop, broken_link); + time_code_pictures, s->closed_gop, broken_link); } /** * Finds the end of the current frame in the bitstream. * @return the position of the first byte of the next frame, or -1 */ -int ff_mpeg1_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size) +int ff_mpeg1_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size, AVCodecParserContext *s) { int i; uint32_t state= pc->state; @@ -2228,6 +2204,9 @@ int ff_mpeg1_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size) return i-3; } } + if(s && state == PICTURE_START_CODE){ + ff_fetch_timestamp(s, i-3, 1); + } } } pc->state= state; @@ -2241,8 +2220,10 @@ static int decode_chunks(AVCodecContext *avctx, /* handle buffering and image synchronisation */ static int mpeg_decode_frame(AVCodecContext *avctx, void *data, int *data_size, - const uint8_t *buf, int buf_size) + AVPacket *avpkt) { + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; Mpeg1Context *s = avctx->priv_data; AVFrame *picture = data; MpegEncContext *s2 = &s->mpeg_enc_ctx; @@ -2260,7 +2241,7 @@ static int mpeg_decode_frame(AVCodecContext *avctx, } if(s2->flags&CODEC_FLAG_TRUNCATED){ - int next= ff_mpeg1_find_frame_end(&s2->parse_context, buf, buf_size); + int next= ff_mpeg1_find_frame_end(&s2->parse_context, buf, buf_size, NULL); if( ff_combine_frame(&s2->parse_context, next, (const uint8_t **)&buf, &buf_size) < 0 ) return buf_size; @@ -2278,7 +2259,7 @@ static int mpeg_decode_frame(AVCodecContext *avctx, } #endif - if(s->mpeg_enc_ctx_allocated==0 && avctx->codec_tag == ff_get_fourcc("VCR2")) + if(s->mpeg_enc_ctx_allocated==0 && avctx->codec_tag == AV_RL32("VCR2")) vcr2_init_sequence(avctx); s->slice_count= 0; @@ -2298,6 +2279,7 @@ static int decode_chunks(AVCodecContext *avctx, const uint8_t *buf_ptr = buf; const uint8_t *buf_end = buf + buf_size; int ret, input_size; + int last_code= 0; for(;;) { /* find next start code */ @@ -2308,7 +2290,7 @@ static int decode_chunks(AVCodecContext *avctx, if(avctx->thread_count > 1){ int i; - avctx->execute(avctx, slice_decode_thread, (void**)&(s2->thread_context[0]), NULL, s->slice_count, sizeof(void*)); + avctx->execute(avctx, slice_decode_thread, &s2->thread_context[0], NULL, s->slice_count, sizeof(void*)); for(i=0; islice_count; i++) s2->error_count += s2->thread_context[i]->error_count; } @@ -2334,41 +2316,102 @@ static int decode_chunks(AVCodecContext *avctx, /* prepare data for next start code */ switch(start_code) { case SEQ_START_CODE: + if(last_code == 0){ mpeg1_decode_sequence(avctx, buf_ptr, input_size); + s->sync=1; + }else{ + av_log(avctx, AV_LOG_ERROR, "ignoring SEQ_START_CODE after %X\n", last_code); + } break; case PICTURE_START_CODE: + if(last_code == 0 || last_code == SLICE_MIN_START_CODE){ + if(mpeg_decode_postinit(avctx) < 0){ + av_log(avctx, AV_LOG_ERROR, "mpeg_decode_postinit() failure\n"); + return -1; + } + /* we have a complete image: we try to decompress it */ if(mpeg1_decode_picture(avctx, buf_ptr, input_size) < 0) s2->pict_type=0; + s2->first_slice = 1; + last_code= PICTURE_START_CODE; + }else{ + av_log(avctx, AV_LOG_ERROR, "ignoring pic after %X\n", last_code); + } break; case EXT_START_CODE: - mpeg_decode_extension(avctx, - buf_ptr, input_size); + init_get_bits(&s2->gb, buf_ptr, input_size*8); + + switch(get_bits(&s2->gb, 4)) { + case 0x1: + if(last_code == 0){ + mpeg_decode_sequence_extension(s); + }else{ + av_log(avctx, AV_LOG_ERROR, "ignoring seq ext after %X\n", last_code); + } + break; + case 0x2: + mpeg_decode_sequence_display_extension(s); + break; + case 0x3: + mpeg_decode_quant_matrix_extension(s2); + break; + case 0x7: + mpeg_decode_picture_display_extension(s); + break; + case 0x8: + if(last_code == PICTURE_START_CODE){ + mpeg_decode_picture_coding_extension(s); + }else{ + av_log(avctx, AV_LOG_ERROR, "ignoring pic cod ext after %X\n", last_code); + } + break; + } break; case USER_START_CODE: mpeg_decode_user_data(avctx, buf_ptr, input_size); break; case GOP_START_CODE: + if(last_code == 0){ s2->first_field=0; mpeg_decode_gop(avctx, buf_ptr, input_size); + s->sync=1; + }else{ + av_log(avctx, AV_LOG_ERROR, "ignoring GOP_START_CODE after %X\n", last_code); + } break; default: if (start_code >= SLICE_MIN_START_CODE && - start_code <= SLICE_MAX_START_CODE) { - int mb_y= start_code - SLICE_MIN_START_CODE; + start_code <= SLICE_MAX_START_CODE && last_code!=0) { + const int field_pic= s2->picture_structure != PICT_FRAME; + int mb_y= (start_code - SLICE_MIN_START_CODE) << field_pic; + last_code= SLICE_MIN_START_CODE; + + if(s2->picture_structure == PICT_BOTTOM_FIELD) + mb_y++; + + if (mb_y >= s2->mb_height){ + av_log(s2->avctx, AV_LOG_ERROR, "slice below image (%d >= %d)\n", mb_y, s2->mb_height); + return -1; + } if(s2->last_picture_ptr==NULL){ - /* Skip B-frames if we do not have reference frames. */ - if(s2->pict_type==FF_B_TYPE) break; + /* Skip B-frames if we do not have reference frames and gop is not closed */ + if(s2->pict_type==FF_B_TYPE){ + if(!s2->closed_gop) + break; + } } + if(s2->pict_type==FF_I_TYPE) + s->sync=1; if(s2->next_picture_ptr==NULL){ /* Skip P-frames if we do not have a reference frame or we have an invalid header. */ - if(s2->pict_type==FF_P_TYPE && (s2->first_field || s2->picture_structure==PICT_FRAME)) break; + if(s2->pict_type==FF_P_TYPE && !s->sync) break; } /* Skip B-frames if we are in a hurry. */ if(avctx->hurry_up && s2->pict_type==FF_B_TYPE) break; @@ -2393,9 +2436,9 @@ static int decode_chunks(AVCodecContext *avctx, if(s2->first_slice){ s2->first_slice=0; - if(mpeg_field_start(s2) < 0) + if(mpeg_field_start(s2, buf, buf_size) < 0) return -1; - } + } if(!s2->current_picture_ptr){ av_log(avctx, AV_LOG_ERROR, "current_picture not initialized\n"); return -1; @@ -2438,6 +2481,14 @@ static int decode_chunks(AVCodecContext *avctx, } } +static void flush(AVCodecContext *avctx){ + Mpeg1Context *s = avctx->priv_data; + + s->sync=0; + + ff_mpeg_flush(avctx); +} + static int mpeg_decode_end(AVCodecContext *avctx) { Mpeg1Context *s = avctx->priv_data; @@ -2457,7 +2508,7 @@ AVCodec mpeg1video_decoder = { mpeg_decode_end, mpeg_decode_frame, CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED | CODEC_CAP_DELAY, - .flush= ff_mpeg_flush, + .flush= flush, .long_name= NULL_IF_CONFIG_SMALL("MPEG-1 video"), }; @@ -2471,7 +2522,7 @@ AVCodec mpeg2video_decoder = { mpeg_decode_end, mpeg_decode_frame, CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED | CODEC_CAP_DELAY, - .flush= ff_mpeg_flush, + .flush= flush, .long_name= NULL_IF_CONFIG_SMALL("MPEG-2 video"), }; @@ -2486,14 +2537,12 @@ AVCodec mpegvideo_decoder = { mpeg_decode_end, mpeg_decode_frame, CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED | CODEC_CAP_DELAY, - .flush= ff_mpeg_flush, + .flush= flush, .long_name= NULL_IF_CONFIG_SMALL("MPEG-1 video"), }; -#if CONFIG_XVMC +#if CONFIG_MPEG_XVMC_DECODER static av_cold int mpeg_mc_decode_init(AVCodecContext *avctx){ - Mpeg1Context *s; - if( avctx->thread_count > 1) return -1; if( !(avctx->slice_flags & SLICE_FLAG_CODED_ORDER) ) @@ -2502,7 +2551,6 @@ static av_cold int mpeg_mc_decode_init(AVCodecContext *avctx){ dprintf(avctx, "mpeg12.c: XvMC decoder will work better if SLICE_FLAG_ALLOW_FIELD is set\n"); } mpeg_decode_init(avctx); - s = avctx->priv_data; avctx->pix_fmt = PIX_FMT_XVMC_MPEG2_IDCT; avctx->xvmc_acceleration = 2;//2 - the blocks are packed! @@ -2520,8 +2568,8 @@ AVCodec mpeg_xvmc_decoder = { mpeg_decode_end, mpeg_decode_frame, CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED| CODEC_CAP_HWACCEL | CODEC_CAP_DELAY, - .flush= ff_mpeg_flush, - .long_name = NULL_IF_CONFIG_SMALL("MPEG-1 video XvMC (X-Video Motion Compensation)"), + .flush= flush, + .long_name = NULL_IF_CONFIG_SMALL("MPEG-1/2 video XvMC (X-Video Motion Compensation)"), }; #endif @@ -2537,8 +2585,24 @@ AVCodec mpeg_vdpau_decoder = { mpeg_decode_end, mpeg_decode_frame, CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED | CODEC_CAP_HWACCEL_VDPAU | CODEC_CAP_DELAY, - .flush= ff_mpeg_flush, + .flush= flush, .long_name = NULL_IF_CONFIG_SMALL("MPEG-1/2 video (VDPAU acceleration)"), }; #endif +#if CONFIG_MPEG1_VDPAU_DECODER +AVCodec mpeg1_vdpau_decoder = { + "mpeg1video_vdpau", + CODEC_TYPE_VIDEO, + CODEC_ID_MPEG1VIDEO, + sizeof(Mpeg1Context), + mpeg_decode_init, + NULL, + mpeg_decode_end, + mpeg_decode_frame, + CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED | CODEC_CAP_HWACCEL_VDPAU | CODEC_CAP_DELAY, + .flush= flush, + .long_name = NULL_IF_CONFIG_SMALL("MPEG-1 video (VDPAU acceleration)"), +}; +#endif +