diff options
Diffstat (limited to 'contrib/ffmpeg/libavcodec/vc1.c')
-rw-r--r-- | contrib/ffmpeg/libavcodec/vc1.c | 470 |
1 files changed, 363 insertions, 107 deletions
diff --git a/contrib/ffmpeg/libavcodec/vc1.c b/contrib/ffmpeg/libavcodec/vc1.c index cd3c0c2d6..84868904d 100644 --- a/contrib/ffmpeg/libavcodec/vc1.c +++ b/contrib/ffmpeg/libavcodec/vc1.c @@ -1,6 +1,6 @@ /* * VC-1 and WMV3 decoder - * Copyright (c) 2006 Konstantin Shishkov + * Copyright (c) 2006-2007 Konstantin Shishkov * Partly based on vc9.c (c) 2005 Anonymous, Alex Beregszaszi, Michael Niedermayer * * This file is part of FFmpeg. @@ -46,6 +46,18 @@ extern const uint16_t ff_msmp4_mb_i_table[64][2]; #define AC_VLC_BITS 9 static const uint16_t table_mb_intra[64][2]; +/** Markers used if VC-1 AP frame data */ +//@{ +enum VC1Code{ + VC1_CODE_RES0 = 0x00000100, + VC1_CODE_ENDOFSEQ = 0x0000010A, + VC1_CODE_SLICE, + VC1_CODE_FIELD, + VC1_CODE_FRAME, + VC1_CODE_ENTRYPOINT, + VC1_CODE_SEQHDR, +}; +//@} /** Available Profiles */ //@{ @@ -790,6 +802,10 @@ static void vc1_mc_1mv(VC1Context *v, int dir) } uvmx = (mx + ((mx & 3) == 3)) >> 1; uvmy = (my + ((my & 3) == 3)) >> 1; + if(v->fastuvmc) { + uvmx = uvmx + ((uvmx<0)?(uvmx&1):-(uvmx&1)); + uvmy = uvmy + ((uvmy<0)?(uvmy&1):-(uvmy&1)); + } if(!dir) { srcY = s->last_picture.data[0]; srcU = s->last_picture.data[1]; @@ -805,10 +821,17 @@ static void vc1_mc_1mv(VC1Context *v, int dir) uvsrc_x = s->mb_x * 8 + (uvmx >> 2); uvsrc_y = s->mb_y * 8 + (uvmy >> 2); - src_x = clip( src_x, -16, s->mb_width * 16); - src_y = clip( src_y, -16, s->mb_height * 16); - uvsrc_x = clip(uvsrc_x, -8, s->mb_width * 8); - uvsrc_y = clip(uvsrc_y, -8, s->mb_height * 8); + if(v->profile != PROFILE_ADVANCED){ + src_x = av_clip( src_x, -16, s->mb_width * 16); + src_y = av_clip( src_y, -16, s->mb_height * 16); + uvsrc_x = av_clip(uvsrc_x, -8, s->mb_width * 8); + uvsrc_y = av_clip(uvsrc_y, -8, s->mb_height * 8); + }else{ + src_x = av_clip( src_x, -17, s->avctx->coded_width); + src_y = av_clip( src_y, -18, s->avctx->coded_height + 1); + uvsrc_x = av_clip(uvsrc_x, -8, s->avctx->coded_width >> 1); + uvsrc_y = av_clip(uvsrc_y, -8, s->avctx->coded_height >> 1); + } srcY += src_y * s->linesize + src_x; srcU += uvsrc_y * s->uvlinesize + uvsrc_x; @@ -878,11 +901,6 @@ static void vc1_mc_1mv(VC1Context *v, int dir) srcY += s->mspel * (1 + s->linesize); } - if(v->fastuvmc) { - uvmx = uvmx + ((uvmx<0)?-(uvmx&1):(uvmx&1)); - uvmy = uvmy + ((uvmy<0)?-(uvmy&1):(uvmy&1)); - } - if(s->mspel) { dxy = ((my & 3) << 2) | (mx & 3); dsp->put_vc1_mspel_pixels_tab[dxy](s->dest[0] , srcY , s->linesize, v->rnd); @@ -933,8 +951,13 @@ static void vc1_mc_4mv_luma(VC1Context *v, int n) src_x = s->mb_x * 16 + (n&1) * 8 + (mx >> 2); src_y = s->mb_y * 16 + (n&2) * 4 + (my >> 2); - src_x = clip( src_x, -16, s->mb_width * 16); - src_y = clip( src_y, -16, s->mb_height * 16); + if(v->profile != PROFILE_ADVANCED){ + src_x = av_clip( src_x, -16, s->mb_width * 16); + src_y = av_clip( src_y, -16, s->mb_height * 16); + }else{ + src_x = av_clip( src_x, -17, s->avctx->coded_width); + src_y = av_clip( src_y, -18, s->avctx->coded_height + 1); + } srcY += src_y * s->linesize + src_x; @@ -1045,19 +1068,32 @@ static void vc1_mc_4mv_chroma(VC1Context *v) for(i= t1+1; i<4; i++)if(!intra[i]) {t2 = i; break;} tx = (mvx[t1] + mvx[t2]) / 2; ty = (mvy[t1] + mvy[t2]) / 2; - } else + } else { + s->current_picture.motion_val[1][s->block_index[0]][0] = 0; + s->current_picture.motion_val[1][s->block_index[0]][1] = 0; return; //no need to do MC for inter blocks + } s->current_picture.motion_val[1][s->block_index[0]][0] = tx; s->current_picture.motion_val[1][s->block_index[0]][1] = ty; uvmx = (tx + ((tx&3) == 3)) >> 1; uvmy = (ty + ((ty&3) == 3)) >> 1; + if(v->fastuvmc) { + uvmx = uvmx + ((uvmx<0)?(uvmx&1):-(uvmx&1)); + uvmy = uvmy + ((uvmy<0)?(uvmy&1):-(uvmy&1)); + } uvsrc_x = s->mb_x * 8 + (uvmx >> 2); uvsrc_y = s->mb_y * 8 + (uvmy >> 2); - uvsrc_x = clip(uvsrc_x, -8, s->mb_width * 8); - uvsrc_y = clip(uvsrc_y, -8, s->mb_height * 8); + if(v->profile != PROFILE_ADVANCED){ + uvsrc_x = av_clip(uvsrc_x, -8, s->mb_width * 8); + uvsrc_y = av_clip(uvsrc_y, -8, s->mb_height * 8); + }else{ + uvsrc_x = av_clip(uvsrc_x, -8, s->avctx->coded_width >> 1); + uvsrc_y = av_clip(uvsrc_y, -8, s->avctx->coded_height >> 1); + } + srcU = s->last_picture.data[1] + uvsrc_y * s->uvlinesize + uvsrc_x; srcV = s->last_picture.data[2] + uvsrc_y * s->uvlinesize + uvsrc_x; if(v->rangeredfrm || (v->mv_mode == MV_PMODE_INTENSITY_COMP) @@ -1102,11 +1138,6 @@ static void vc1_mc_4mv_chroma(VC1Context *v) } } - if(v->fastuvmc) { - uvmx = uvmx + ((uvmx<0)?-(uvmx&1):(uvmx&1)); - uvmy = uvmy + ((uvmy<0)?-(uvmy&1):(uvmy&1)); - } - /* Chroma MC always uses qpel bilinear */ uvdxy = ((uvmy & 3) << 2) | (uvmx & 3); uvmx = (uvmx&3)<<1; @@ -1135,10 +1166,9 @@ static int decode_sequence_header(AVCodecContext *avctx, GetBitContext *gb) av_log(avctx, AV_LOG_DEBUG, "Header: %0X\n", show_bits(gb, 32)); v->profile = get_bits(gb, 2); - if (v->profile == 2) + if (v->profile == PROFILE_COMPLEX) { - av_log(avctx, AV_LOG_ERROR, "Profile value 2 is forbidden (and WMV3 Complex Profile is unsupported)\n"); - return -1; + av_log(avctx, AV_LOG_ERROR, "WMV3 Complex Profile is not fully supported\n"); } if (v->profile == PROFILE_ADVANCED) @@ -1231,6 +1261,8 @@ static int decode_sequence_header(AVCodecContext *avctx, GetBitContext *gb) "Old WMV3 version detected, only I-frames will be decoded\n"); //return -1; } + //TODO: figure out what they mean (always 0x402F) + if(!v->res_fasttx) skip_bits(gb, 16); av_log(avctx, AV_LOG_DEBUG, "Profile %i:\nfrmrtq_postproc=%i, bitrtq_postproc=%i\n" "LoopFilter=%i, MultiRes=%i, FastUVMC=%i, Extended MV=%i\n" @@ -1268,36 +1300,60 @@ static int decode_sequence_header_adv(VC1Context *v, GetBitContext *gb) v->s.avctx->coded_width = (get_bits(gb, 12) + 1) << 1; v->s.avctx->coded_height = (get_bits(gb, 12) + 1) << 1; + v->s.avctx->width = v->s.avctx->coded_width; + v->s.avctx->height = v->s.avctx->coded_height; v->broadcast = get_bits1(gb); v->interlace = get_bits1(gb); v->tfcntrflag = get_bits1(gb); v->finterpflag = get_bits1(gb); get_bits1(gb); // reserved + + v->s.h_edge_pos = v->s.avctx->coded_width; + v->s.v_edge_pos = v->s.avctx->coded_height; + + av_log(v->s.avctx, AV_LOG_DEBUG, + "Advanced Profile level %i:\nfrmrtq_postproc=%i, bitrtq_postproc=%i\n" + "LoopFilter=%i, ChromaFormat=%i, Pulldown=%i, Interlace: %i\n" + "TFCTRflag=%i, FINTERPflag=%i\n", + v->level, v->frmrtq_postproc, v->bitrtq_postproc, + v->s.loop_filter, v->chromaformat, v->broadcast, v->interlace, + v->tfcntrflag, v->finterpflag + ); + v->psf = get_bits1(gb); if(v->psf) { //PsF, 6.1.13 av_log(v->s.avctx, AV_LOG_ERROR, "Progressive Segmented Frame mode: not supported (yet)\n"); return -1; } + v->s.max_b_frames = v->s.avctx->max_b_frames = 7; if(get_bits1(gb)) { //Display Info - decoding is not affected by it int w, h, ar = 0; - av_log(v->s.avctx, AV_LOG_INFO, "Display extended info:\n"); - w = get_bits(gb, 14); - h = get_bits(gb, 14); - av_log(v->s.avctx, AV_LOG_INFO, "Display dimensions: %ix%i\n", w, h); - //TODO: store aspect ratio in AVCodecContext + av_log(v->s.avctx, AV_LOG_DEBUG, "Display extended info:\n"); + v->s.avctx->width = v->s.width = w = get_bits(gb, 14) + 1; + v->s.avctx->height = v->s.height = h = get_bits(gb, 14) + 1; + av_log(v->s.avctx, AV_LOG_DEBUG, "Display dimensions: %ix%i\n", w, h); if(get_bits1(gb)) ar = get_bits(gb, 4); - if(ar == 15) { + if(ar && ar < 14){ + v->s.avctx->sample_aspect_ratio = vc1_pixel_aspect[ar]; + }else if(ar == 15){ w = get_bits(gb, 8); h = get_bits(gb, 8); + v->s.avctx->sample_aspect_ratio = (AVRational){w, h}; } if(get_bits1(gb)){ //framerate stuff if(get_bits1(gb)) { - get_bits(gb, 16); + v->s.avctx->time_base.num = 32; + v->s.avctx->time_base.den = get_bits(gb, 16) + 1; } else { - get_bits(gb, 8); - get_bits(gb, 4); + int nr, dr; + nr = get_bits(gb, 8); + dr = get_bits(gb, 4); + if(nr && nr < 8 && dr && dr < 3){ + v->s.avctx->time_base.num = fps_dr[dr - 1]; + v->s.avctx->time_base.den = fps_nr[nr - 1] * 1000; + } } } @@ -1325,13 +1381,13 @@ static int decode_sequence_header_adv(VC1Context *v, GetBitContext *gb) static int decode_entry_point(AVCodecContext *avctx, GetBitContext *gb) { VC1Context *v = avctx->priv_data; - int i; + int i, blink, clentry, refdist; av_log(avctx, AV_LOG_DEBUG, "Entry point: %08X\n", show_bits_long(gb, 32)); - get_bits1(gb); // broken link - avctx->max_b_frames = 1 - get_bits1(gb); // 'closed entry' also signalize possible B-frames + blink = get_bits1(gb); // broken link + clentry = get_bits1(gb); // closed entry v->panscanflag = get_bits1(gb); - get_bits1(gb); // refdist flag + refdist = get_bits1(gb); // refdist flag v->s.loop_filter = get_bits1(gb); v->fastuvmc = get_bits1(gb); v->extended_mv = get_bits1(gb); @@ -1361,6 +1417,13 @@ static int decode_entry_point(AVCodecContext *avctx, GetBitContext *gb) skip_bits(gb, 3); // UV range, ignored for now } + av_log(avctx, AV_LOG_DEBUG, "Entry point info:\n" + "BrokenLink=%i, ClosedEntry=%i, PanscanFlag=%i\n" + "RefDist=%i, Postproc=%i, FastUVMC=%i, ExtMV=%i\n" + "DQuant=%i, VSTransform=%i, Overlap=%i, Qmode=%i\n", + blink, clentry, v->panscanflag, refdist, v->s.loop_filter, + v->fastuvmc, v->extended_mv, v->dquant, v->vstransform, v->overlap, v->quantizer_mode); + return 0; } @@ -1427,6 +1490,9 @@ static int vc1_parse_frame_header(VC1Context *v, GetBitContext* gb) else if (v->multires && v->s.pict_type != B_TYPE) v->respic = get_bits(gb, 2); + if(v->res_x8 && (v->s.pict_type == I_TYPE || v->s.pict_type == BI_TYPE)){ + if(get_bits1(gb))return -1; + } //av_log(v->s.avctx, AV_LOG_INFO, "%c Frame: QP=[%i]%i (+%i/2) %i\n", // (v->s.pict_type == P_TYPE) ? 'P' : ((v->s.pict_type == I_TYPE) ? 'I' : 'B'), pqindex, v->pq, v->halfpq, v->rangeredfrm); @@ -1461,8 +1527,8 @@ static int vc1_parse_frame_header(VC1Context *v, GetBitContext* gb) shift = v->lumshift << 6; } for(i = 0; i < 256; i++) { - v->luty[i] = clip_uint8((scale * i + shift + 32) >> 6); - v->lutuv[i] = clip_uint8((scale * (i - 128) + 128*64 + 32) >> 6); + v->luty[i] = av_clip_uint8((scale * i + shift + 32) >> 6); + v->lutuv[i] = av_clip_uint8((scale * (i - 128) + 128*64 + 32) >> 6); } } if(v->mv_mode == MV_PMODE_1MV_HPEL || v->mv_mode == MV_PMODE_1MV_HPEL_BILIN) @@ -1577,14 +1643,15 @@ static int vc1_parse_frame_header(VC1Context *v, GetBitContext* gb) static int vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb) { - int fcm; int pqindex, lowquant; int status; v->p_frame_skipped = 0; - if(v->interlace) - fcm = decode012(gb); + if(v->interlace){ + v->fcm = decode012(gb); + if(v->fcm) return -1; // interlaced frames/fields are not implemented + } switch(get_prefix(gb, 0, 4)) { case 0: v->s.pict_type = P_TYPE; @@ -1606,11 +1673,11 @@ static int vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb) if(v->tfcntrflag) get_bits(gb, 8); if(v->broadcast) { - if(!v->interlace || v->panscanflag) { - get_bits(gb, 2); + if(!v->interlace || v->psf) { + v->rptfrm = get_bits(gb, 2); } else { - get_bits1(gb); - get_bits1(gb); + v->tff = get_bits1(gb); + v->rptfrm = get_bits1(gb); } } if(v->panscanflag) { @@ -1645,6 +1712,8 @@ static int vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb) if (v->quantizer_mode == QUANT_FRAME_EXPLICIT) v->pquantizer = get_bits(gb, 1); + if(v->s.pict_type == I_TYPE || v->s.pict_type == P_TYPE) v->use_ic = 0; + switch(v->s.pict_type) { case I_TYPE: case BI_TYPE: @@ -1699,9 +1768,10 @@ static int vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb) shift = v->lumshift << 6; } for(i = 0; i < 256; i++) { - v->luty[i] = clip_uint8((scale * i + shift + 32) >> 6); - v->lutuv[i] = clip_uint8((scale * (i - 128) + 128*64 + 32) >> 6); + v->luty[i] = av_clip_uint8((scale * i + shift + 32) >> 6); + v->lutuv[i] = av_clip_uint8((scale * (i - 128) + 128*64 + 32) >> 6); } + v->use_ic = 1; } if(v->mv_mode == MV_PMODE_1MV_HPEL || v->mv_mode == MV_PMODE_1MV_HPEL_BILIN) v->s.quarter_sample = 0; @@ -1813,7 +1883,7 @@ static int vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb) } /* DC Syntax */ v->s.dc_table_index = get_bits(gb, 1); - if (v->s.pict_type == I_TYPE && v->dquant) { + if ((v->s.pict_type == I_TYPE || v->s.pict_type == BI_TYPE) && v->dquant) { av_log(v->s.avctx, AV_LOG_DEBUG, "VOP DQuant info\n"); vop_dquant_decoding(v); } @@ -1939,6 +2009,8 @@ static inline void vc1_pred_mv(MpegEncContext *s, int n, int dmv_x, int dmv_y, i if(s->mb_intra){ s->mv[0][n][0] = s->current_picture.motion_val[0][xy][0] = 0; s->mv[0][n][1] = s->current_picture.motion_val[0][xy][1] = 0; + s->current_picture.motion_val[1][xy][0] = 0; + s->current_picture.motion_val[1][xy][1] = 0; if(mv1) { /* duplicate motion data for 1-MV block */ s->current_picture.motion_val[0][xy + 1][0] = 0; s->current_picture.motion_val[0][xy + 1][1] = 0; @@ -1946,6 +2018,12 @@ static inline void vc1_pred_mv(MpegEncContext *s, int n, int dmv_x, int dmv_y, i s->current_picture.motion_val[0][xy + wrap][1] = 0; s->current_picture.motion_val[0][xy + wrap + 1][0] = 0; s->current_picture.motion_val[0][xy + wrap + 1][1] = 0; + s->current_picture.motion_val[1][xy + 1][0] = 0; + s->current_picture.motion_val[1][xy + 1][1] = 0; + s->current_picture.motion_val[1][xy + wrap][0] = 0; + s->current_picture.motion_val[1][xy + wrap][1] = 0; + s->current_picture.motion_val[1][xy + wrap + 1][0] = 0; + s->current_picture.motion_val[1][xy + wrap + 1][1] = 0; } return; } @@ -2061,6 +2139,10 @@ static void vc1_interp_mc(VC1Context *v) my = s->mv[1][0][1]; uvmx = (mx + ((mx & 3) == 3)) >> 1; uvmy = (my + ((my & 3) == 3)) >> 1; + if(v->fastuvmc) { + uvmx = uvmx + ((uvmx<0)?-(uvmx&1):(uvmx&1)); + uvmy = uvmy + ((uvmy<0)?-(uvmy&1):(uvmy&1)); + } srcY = s->next_picture.data[0]; srcU = s->next_picture.data[1]; srcV = s->next_picture.data[2]; @@ -2070,10 +2152,17 @@ static void vc1_interp_mc(VC1Context *v) uvsrc_x = s->mb_x * 8 + (uvmx >> 2); uvsrc_y = s->mb_y * 8 + (uvmy >> 2); - src_x = clip( src_x, -16, s->mb_width * 16); - src_y = clip( src_y, -16, s->mb_height * 16); - uvsrc_x = clip(uvsrc_x, -8, s->mb_width * 8); - uvsrc_y = clip(uvsrc_y, -8, s->mb_height * 8); + if(v->profile != PROFILE_ADVANCED){ + src_x = av_clip( src_x, -16, s->mb_width * 16); + src_y = av_clip( src_y, -16, s->mb_height * 16); + uvsrc_x = av_clip(uvsrc_x, -8, s->mb_width * 8); + uvsrc_y = av_clip(uvsrc_y, -8, s->mb_height * 8); + }else{ + src_x = av_clip( src_x, -17, s->avctx->coded_width); + src_y = av_clip( src_y, -18, s->avctx->coded_height + 1); + uvsrc_x = av_clip(uvsrc_x, -8, s->avctx->coded_width >> 1); + uvsrc_y = av_clip(uvsrc_y, -8, s->avctx->coded_height >> 1); + } srcY += src_y * s->linesize + src_x; srcU += uvsrc_y * s->uvlinesize + uvsrc_x; @@ -2123,11 +2212,6 @@ static void vc1_interp_mc(VC1Context *v) srcY += s->mspel * (1 + s->linesize); } - if(v->fastuvmc) { - uvmx = uvmx + ((uvmx<0)?-(uvmx&1):(uvmx&1)); - uvmy = uvmy + ((uvmy<0)?-(uvmy&1):(uvmy&1)); - } - mx >>= 1; my >>= 1; dxy = ((my & 1) << 1) | (mx & 1); @@ -2143,7 +2227,7 @@ static void vc1_interp_mc(VC1Context *v) dsp->avg_h264_chroma_pixels_tab[0](s->dest[2], srcV, s->uvlinesize, 8, uvmx, uvmy); } -static always_inline int scale_mv(int value, int bfrac, int inv, int qs) +static av_always_inline int scale_mv(int value, int bfrac, int inv, int qs) { int n = bfrac; @@ -2870,9 +2954,11 @@ static int vc1_decode_i_block_adv(VC1Context *v, DCTELEM block[64], int n, int c ac_val -= 16 * s->block_wrap[n]; q1 = s->current_picture.qscale_table[mb_pos]; - if(dc_pred_dir && c_avail) q2 = s->current_picture.qscale_table[mb_pos - 1]; - if(!dc_pred_dir && a_avail) q2 = s->current_picture.qscale_table[mb_pos - s->mb_stride]; - if(n && n<4) q2 = q1; + if(dc_pred_dir && c_avail && mb_pos) q2 = s->current_picture.qscale_table[mb_pos - 1]; + if(!dc_pred_dir && a_avail && mb_pos >= s->mb_stride) q2 = s->current_picture.qscale_table[mb_pos - s->mb_stride]; + if(dc_pred_dir && n==1) q2 = q1; + if(!dc_pred_dir && n==2) q2 = q1; + if(n==3) q2 = q1; if(coded) { int last = 0, skip, value; @@ -3075,9 +3161,11 @@ static int vc1_decode_intra_block(VC1Context *v, DCTELEM block[64], int n, int c ac_val -= 16 * s->block_wrap[n]; q1 = s->current_picture.qscale_table[mb_pos]; - if(dc_pred_dir && c_avail) q2 = s->current_picture.qscale_table[mb_pos - 1]; - if(!dc_pred_dir && a_avail) q2 = s->current_picture.qscale_table[mb_pos - s->mb_stride]; - if(n && n<4) q2 = q1; + if(dc_pred_dir && c_avail && mb_pos) q2 = s->current_picture.qscale_table[mb_pos - 1]; + if(!dc_pred_dir && a_avail && mb_pos >= s->mb_stride) q2 = s->current_picture.qscale_table[mb_pos - s->mb_stride]; + if(dc_pred_dir && n==1) q2 = q1; + if(!dc_pred_dir && n==2) q2 = q1; + if(n==3) q2 = q1; if(coded) { int last = 0, skip, value; @@ -3394,6 +3482,7 @@ static int vc1_decode_p_mb(VC1Context *v) s->dsp.vc1_inv_trans_8x8(s->block[i]); if(v->rangeredfrm) for(j = 0; j < 64; j++) s->block[i][j] <<= 1; for(j = 0; j < 64; j++) s->block[i][j] += 128; + if(!v->res_fasttx && v->res_x8) for(j = 0; j < 64; j++) s->block[i][j] += 16; s->dsp.put_pixels_clamped(s->block[i], s->dest[dst_idx] + off, s->linesize >> ((i & 4) >> 2)); if(v->pq >= 9 && v->overlap) { if(v->c_avail) @@ -3497,6 +3586,7 @@ static int vc1_decode_p_mb(VC1Context *v) s->dsp.vc1_inv_trans_8x8(s->block[i]); if(v->rangeredfrm) for(j = 0; j < 64; j++) s->block[i][j] <<= 1; for(j = 0; j < 64; j++) s->block[i][j] += 128; + if(!v->res_fasttx && v->res_x8) for(j = 0; j < 64; j++) s->block[i][j] += 16; s->dsp.put_pixels_clamped(s->block[i], s->dest[dst_idx] + off, (i&4)?s->uvlinesize:s->linesize); if(v->pq >= 9 && v->overlap) { if(v->c_avail) @@ -3761,6 +3851,7 @@ static void vc1_decode_i_blocks(VC1Context *v) vc1_decode_i_block(v, s->block[k], k, val, (k<4)? v->codingset : v->codingset2); s->dsp.vc1_inv_trans_8x8(s->block[k]); + if(!v->res_fasttx && !v->res_x8) for(j = 0; j < 64; j++) s->block[k][j] -= 16; if(v->pq >= 9 && v->overlap) { for(j = 0; j < 64; j++) s->block[k][j] += 128; } @@ -4063,14 +4154,53 @@ static void vc1_decode_blocks(VC1Context *v) vc1_decode_p_blocks(v); break; case B_TYPE: - if(v->bi_type) - vc1_decode_i_blocks(v); - else + if(v->bi_type){ + if(v->profile == PROFILE_ADVANCED) + vc1_decode_i_blocks_adv(v); + else + vc1_decode_i_blocks(v); + }else vc1_decode_b_blocks(v); break; } } +#define IS_MARKER(x) (((x) & ~0xFF) == VC1_CODE_RES0) + +/** Find VC-1 marker in buffer + * @return position where next marker starts or end of buffer if no marker found + */ +static av_always_inline uint8_t* find_next_marker(uint8_t *src, uint8_t *end) +{ + uint32_t mrk = 0xFFFFFFFF; + + if(end-src < 4) return end; + while(src < end){ + mrk = (mrk << 8) | *src++; + if(IS_MARKER(mrk)) + return src-4; + } + return end; +} + +static av_always_inline int vc1_unescape_buffer(uint8_t *src, int size, uint8_t *dst) +{ + int dsize = 0, i; + + if(size < 4){ + for(dsize = 0; dsize < size; dsize++) *dst++ = *src++; + return size; + } + for(i = 0; i < size; i++, src++) { + if(src[0] == 3 && i >= 2 && !src[-1] && !src[-2] && i < size-1 && src[1] < 4) { + dst[dsize++] = src[1]; + src++; + i++; + } else + dst[dsize++] = *src; + } + return dsize; +} /** Initialize a VC1/WMV3 decoder * @todo TODO: Handle VC-1 IDUs (Transport level?) @@ -4122,44 +4252,47 @@ static int vc1_decode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_INFO, "Read %i bits in overflow\n", -count); } } else { // VC1/WVC1 - int edata_size = avctx->extradata_size; - uint8_t *edata = avctx->extradata; + uint8_t *start = avctx->extradata, *end = avctx->extradata + avctx->extradata_size; + uint8_t *next; int size, buf2_size; + uint8_t *buf2 = NULL; + int seq_inited = 0, ep_inited = 0; if(avctx->extradata_size < 16) { - av_log(avctx, AV_LOG_ERROR, "Extradata size too small: %i\n", edata_size); + av_log(avctx, AV_LOG_ERROR, "Extradata size too small: %i\n", avctx->extradata_size); return -1; } - while(edata_size > 8) { - // test if we've found header - if(BE_32(edata) == 0x0000010F) { - edata += 4; - edata_size -= 4; - break; - } - edata_size--; - edata++; - } - init_get_bits(&gb, edata, edata_size*8); - - if (decode_sequence_header(avctx, &gb) < 0) - return -1; - - while(edata_size > 8) { - // test if we've found entry point - if(BE_32(edata) == 0x0000010E) { - edata += 4; - edata_size -= 4; + buf2 = av_mallocz(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); + if(start[0]) start++; // in WVC1 extradata first byte is its size + next = start; + for(; next < end; start = next){ + next = find_next_marker(start + 4, end); + size = next - start - 4; + if(size <= 0) continue; + buf2_size = vc1_unescape_buffer(start + 4, size, buf2); + init_get_bits(&gb, buf2, buf2_size * 8); + switch(AV_RB32(start)){ + case VC1_CODE_SEQHDR: + if(decode_sequence_header(avctx, &gb) < 0){ + av_free(buf2); + return -1; + } + seq_inited = 1; + break; + case VC1_CODE_ENTRYPOINT: + if(decode_entry_point(avctx, &gb) < 0){ + av_free(buf2); + return -1; + } + ep_inited = 1; break; } - edata_size--; - edata++; } - - init_get_bits(&gb, edata, edata_size*8); - - if (decode_entry_point(avctx, &gb) < 0) - return -1; + av_free(buf2); + if(!seq_inited || !ep_inited){ + av_log(avctx, AV_LOG_ERROR, "Incomplete extradata\n"); + return -1; + } } avctx->has_b_frames= !!(avctx->max_b_frames); s->low_delay = !avctx->has_b_frames; @@ -4223,17 +4356,49 @@ static int vc1_decode_frame(AVCodecContext *avctx, s->current_picture_ptr= &s->picture[i]; } - //for advanced profile we need to unescape buffer + //for advanced profile we may need to parse and unescape data if (avctx->codec_id == CODEC_ID_VC1) { - int i, buf_size2; - buf2 = av_malloc(buf_size + FF_INPUT_BUFFER_PADDING_SIZE); - buf_size2 = 0; - for(i = 0; i < buf_size; i++) { - if(buf[i] == 3 && i >= 2 && !buf[i-1] && !buf[i-2] && i < buf_size-1 && buf[i+1] < 4) { - buf2[buf_size2++] = buf[i+1]; - i++; - } else - buf2[buf_size2++] = buf[i]; + int buf_size2 = 0; + buf2 = av_mallocz(buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + + if(IS_MARKER(AV_RB32(buf))){ /* frame starts with marker and needs to be parsed */ + uint8_t *dst = buf2, *start, *end, *next; + int size; + + next = buf; + for(start = buf, end = buf + buf_size; next < end; start = next){ + next = find_next_marker(start + 4, end); + size = next - start - 4; + if(size <= 0) continue; + switch(AV_RB32(start)){ + case VC1_CODE_FRAME: + buf_size2 = vc1_unescape_buffer(start + 4, size, buf2); + break; + case VC1_CODE_ENTRYPOINT: /* it should be before frame data */ + buf_size2 = vc1_unescape_buffer(start + 4, size, buf2); + init_get_bits(&s->gb, buf2, buf_size2*8); + decode_entry_point(avctx, &s->gb); + break; + case VC1_CODE_SLICE: + av_log(avctx, AV_LOG_ERROR, "Sliced decoding is not implemented (yet)\n"); + av_free(buf2); + return -1; + } + } + }else if(v->interlace && ((buf[0] & 0xC0) == 0xC0)){ /* WVC1 interlaced stores both fields divided by marker */ + uint8_t *divider; + + divider = find_next_marker(buf, buf + buf_size); + if((divider == (buf + buf_size)) || AV_RB32(divider) != VC1_CODE_FIELD){ + av_log(avctx, AV_LOG_ERROR, "Error in WVC1 interlaced frame\n"); + return -1; + } + + buf_size2 = vc1_unescape_buffer(buf, divider - buf, buf2); + // TODO + av_free(buf2);return -1; + }else{ + buf_size2 = vc1_unescape_buffer(buf, buf_size, buf2); } init_get_bits(&s->gb, buf2, buf_size2*8); } else @@ -4368,3 +4533,94 @@ AVCodec wmv3_decoder = { CODEC_CAP_DELAY, NULL }; + +#ifdef CONFIG_VC1_PARSER +/** + * finds the end of the current frame in the bitstream. + * @return the position of the first byte of the next frame, or -1 + */ +static int vc1_find_frame_end(ParseContext *pc, const uint8_t *buf, + int buf_size) { + int pic_found, i; + uint32_t state; + + pic_found= pc->frame_start_found; + state= pc->state; + + i=0; + if(!pic_found){ + for(i=0; i<buf_size; i++){ + state= (state<<8) | buf[i]; + if(state == VC1_CODE_FRAME || state == VC1_CODE_FIELD){ + i++; + pic_found=1; + break; + } + } + } + + if(pic_found){ + /* EOF considered as end of frame */ + if (buf_size == 0) + return 0; + for(; i<buf_size; i++){ + state= (state<<8) | buf[i]; + if(IS_MARKER(state) && state != VC1_CODE_FIELD && state != VC1_CODE_SLICE){ + pc->frame_start_found=0; + pc->state=-1; + return i-3; + } + } + } + pc->frame_start_found= pic_found; + pc->state= state; + return END_NOT_FOUND; +} + +static int vc1_parse(AVCodecParserContext *s, + AVCodecContext *avctx, + uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + ParseContext *pc = s->priv_data; + int next; + + if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){ + next= buf_size; + }else{ + next= vc1_find_frame_end(pc, buf, buf_size); + + if (ff_combine_frame(pc, next, (uint8_t **)&buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + *poutbuf = (uint8_t *)buf; + *poutbuf_size = buf_size; + return next; +} + +int vc1_split(AVCodecContext *avctx, + const uint8_t *buf, int buf_size) +{ + int i; + uint32_t state= -1; + + for(i=0; i<buf_size; i++){ + state= (state<<8) | buf[i]; + if(IS_MARKER(state) && state != VC1_CODE_SEQHDR && state != VC1_CODE_ENTRYPOINT) + return i-3; + } + return 0; +} + +AVCodecParser vc1_parser = { + { CODEC_ID_VC1 }, + sizeof(ParseContext1), + NULL, + vc1_parse, + ff_parse1_close, + vc1_split, +}; +#endif /* CONFIG_VC1_PARSER */ |