diff options
author | Ronald S. Bultje <rsbultje@gmail.com> | 2011-03-21 17:00:43 +0300 |
---|---|---|
committer | Ronald S. Bultje <rsbultje@gmail.com> | 2011-03-21 17:00:43 +0300 |
commit | f44d6445b7a189fde27ca0e95c7eb08f697e109f (patch) | |
tree | 5ee7347bcc824a4637fcaa3b68f13d45b29ef819 /libavcodec/vc1dec.c | |
parent | b81a935bd99c2664b07f717113e71d1aa32be991 (diff) |
vc1: slice support.
Also reset coded_block at each new slice, fixes problems in slice playback.
Diffstat (limited to 'libavcodec/vc1dec.c')
-rw-r--r-- | libavcodec/vc1dec.c | 81 |
1 files changed, 57 insertions, 24 deletions
diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index 98940714eb..cef26e159c 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -2686,7 +2686,7 @@ static void vc1_decode_i_blocks(VC1Context *v) /** Decode blocks of I-frame for advanced profile */ -static void vc1_decode_i_blocks_adv(VC1Context *v) +static void vc1_decode_i_blocks_adv(VC1Context *v, int mby_start, int mby_end) { int k; MpegEncContext *s = &v->s; @@ -2728,8 +2728,15 @@ static void vc1_decode_i_blocks_adv(VC1Context *v) s->mb_x = s->mb_y = 0; s->mb_intra = 1; s->first_slice_line = 1; + s->mb_y = mby_start; + if (mby_start) { + s->mb_x = 0; + ff_init_block_index(s); + memset(&s->coded_block[s->block_index[0]-s->b8_stride], 0, + s->b8_stride * sizeof(*s->coded_block)); + } idct8x8_fn = v->vc1dsp.vc1_inv_trans_8x8_put_signed[0]; - for(s->mb_y = 0; s->mb_y < s->mb_height; s->mb_y++) { + for(; s->mb_y < mby_end; s->mb_y++) { s->mb_x = 0; ff_init_block_index(s); for(;s->mb_x < s->mb_width; s->mb_x++) { @@ -2815,7 +2822,7 @@ static void vc1_decode_i_blocks_adv(VC1Context *v) if(v->s.loop_filter) vc1_loop_filter_iblk(v, v->pq); if(get_bits_count(&s->gb) > v->bits) { - ff_er_add_slice(s, 0, 0, s->mb_x, s->mb_y, (AC_END|DC_END|MV_END)); + ff_er_add_slice(s, 0, mby_start, s->mb_x, s->mb_y, (AC_END|DC_END|MV_END)); av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i\n", get_bits_count(&s->gb), v->bits); return; } @@ -2828,10 +2835,10 @@ static void vc1_decode_i_blocks_adv(VC1Context *v) } if (v->s.loop_filter) ff_draw_horiz_band(s, (s->mb_height-1)*16, 16); - ff_er_add_slice(s, 0, 0, s->mb_width - 1, s->mb_height - 1, (AC_END|DC_END|MV_END)); + ff_er_add_slice(s, 0, mby_start, s->mb_width - 1, mby_end - 1, (AC_END|DC_END|MV_END)); } -static void vc1_decode_p_blocks(VC1Context *v) +static void vc1_decode_p_blocks(VC1Context *v, int mby_start, int mby_end) { MpegEncContext *s = &v->s; @@ -2862,7 +2869,7 @@ static void vc1_decode_p_blocks(VC1Context *v) s->first_slice_line = 1; memset(v->cbp_base, 0, sizeof(v->cbp_base[0])*2*s->mb_stride); - for(s->mb_y = 0; s->mb_y < s->mb_height; s->mb_y++) { + for(s->mb_y = mby_start; s->mb_y < mby_end; s->mb_y++) { s->mb_x = 0; ff_init_block_index(s); for(; s->mb_x < s->mb_width; s->mb_x++) { @@ -2870,7 +2877,7 @@ static void vc1_decode_p_blocks(VC1Context *v) vc1_decode_p_mb(v); if(get_bits_count(&s->gb) > v->bits || get_bits_count(&s->gb) < 0) { - ff_er_add_slice(s, 0, 0, s->mb_x, s->mb_y, (AC_END|DC_END|MV_END)); + ff_er_add_slice(s, 0, mby_start, s->mb_x, s->mb_y, (AC_END|DC_END|MV_END)); av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i at %ix%i\n", get_bits_count(&s->gb), v->bits,s->mb_x,s->mb_y); return; } @@ -2879,10 +2886,10 @@ static void vc1_decode_p_blocks(VC1Context *v) ff_draw_horiz_band(s, s->mb_y * 16, 16); s->first_slice_line = 0; } - ff_er_add_slice(s, 0, 0, s->mb_width - 1, s->mb_height - 1, (AC_END|DC_END|MV_END)); + ff_er_add_slice(s, 0, mby_start, s->mb_width - 1, mby_end - 1, (AC_END|DC_END|MV_END)); } -static void vc1_decode_b_blocks(VC1Context *v) +static void vc1_decode_b_blocks(VC1Context *v, int mby_start, int mby_end) { MpegEncContext *s = &v->s; @@ -2912,7 +2919,7 @@ static void vc1_decode_b_blocks(VC1Context *v) } s->first_slice_line = 1; - for(s->mb_y = 0; s->mb_y < s->mb_height; s->mb_y++) { + for(s->mb_y = mby_start; s->mb_y < mby_end; s->mb_y++) { s->mb_x = 0; ff_init_block_index(s); for(; s->mb_x < s->mb_width; s->mb_x++) { @@ -2920,7 +2927,7 @@ static void vc1_decode_b_blocks(VC1Context *v) vc1_decode_b_mb(v); if(get_bits_count(&s->gb) > v->bits || get_bits_count(&s->gb) < 0) { - ff_er_add_slice(s, 0, 0, s->mb_x, s->mb_y, (AC_END|DC_END|MV_END)); + ff_er_add_slice(s, 0, mby_start, s->mb_x, s->mb_y, (AC_END|DC_END|MV_END)); av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i at %ix%i\n", get_bits_count(&s->gb), v->bits,s->mb_x,s->mb_y); return; } @@ -2934,7 +2941,7 @@ static void vc1_decode_b_blocks(VC1Context *v) } if (v->s.loop_filter) ff_draw_horiz_band(s, (s->mb_height-1)*16, 16); - ff_er_add_slice(s, 0, 0, s->mb_width - 1, s->mb_height - 1, (AC_END|DC_END|MV_END)); + ff_er_add_slice(s, 0, mby_start, s->mb_width - 1, mby_end - 1, (AC_END|DC_END|MV_END)); } static void vc1_decode_skip_blocks(VC1Context *v) @@ -2956,18 +2963,17 @@ static void vc1_decode_skip_blocks(VC1Context *v) s->pict_type = FF_P_TYPE; } -static void vc1_decode_blocks(VC1Context *v) +static void vc1_decode_blocks(VC1Context *v, int mby_start, int mby_end) { v->s.esc3_level_length = 0; if(v->x8_type){ ff_intrax8_decode_picture(&v->x8, 2*v->pq+v->halfpq, v->pq*(!v->pquantizer) ); }else{ - switch(v->s.pict_type) { case FF_I_TYPE: if(v->profile == PROFILE_ADVANCED) - vc1_decode_i_blocks_adv(v); + vc1_decode_i_blocks_adv(v, mby_start, mby_end); else vc1_decode_i_blocks(v); break; @@ -2975,16 +2981,16 @@ static void vc1_decode_blocks(VC1Context *v) if(v->p_frame_skipped) vc1_decode_skip_blocks(v); else - vc1_decode_p_blocks(v); + vc1_decode_p_blocks(v, mby_start, mby_end); break; case FF_B_TYPE: if(v->bi_type){ if(v->profile == PROFILE_ADVANCED) - vc1_decode_i_blocks_adv(v); + vc1_decode_i_blocks_adv(v, mby_start, mby_end); else vc1_decode_i_blocks(v); }else - vc1_decode_b_blocks(v); + vc1_decode_b_blocks(v, mby_start, mby_end); break; } } @@ -3145,12 +3151,17 @@ static int vc1_decode_frame(AVCodecContext *avctx, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; - int buf_size = avpkt->size; + int buf_size = avpkt->size, n_slices = 0, i; VC1Context *v = avctx->priv_data; MpegEncContext *s = &v->s; AVFrame *pict = data; uint8_t *buf2 = NULL; const uint8_t *buf_start = buf; + struct { + uint8_t *buf; + GetBitContext gb; + int mby_start; + } *slices = NULL; /* no supplementary picture */ if (buf_size == 0 || (buf_size == 4 && AV_RB32(buf) == VC1_CODE_ENDOFSEQ)) { @@ -3205,10 +3216,20 @@ static int vc1_decode_frame(AVCodecContext *avctx, init_get_bits(&s->gb, buf2, buf_size2*8); vc1_decode_entry_point(avctx, v, &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; + case VC1_CODE_SLICE: { + int buf_size3; + slices = av_realloc(slices, sizeof(*slices) * (n_slices+1)); + if (!slices) goto err; + slices[n_slices].buf = av_mallocz(buf_size + FF_INPUT_BUFFER_PADDING_SIZE); + if (!slices[n_slices].buf) goto err; + buf_size3 = vc1_unescape_buffer(start + 4, size, + slices[n_slices].buf); + init_get_bits(&slices[n_slices].gb, slices[n_slices].buf, + buf_size3 << 3); + slices[n_slices].mby_start = get_bits(&slices[n_slices].gb, 9); + n_slices++; + break; + } } } }else if(v->interlace && ((buf[0] & 0xC0) == 0xC0)){ /* WVC1 interlaced stores both fields divided by marker */ @@ -3294,7 +3315,13 @@ static int vc1_decode_frame(AVCodecContext *avctx, ff_er_frame_start(s); v->bits = buf_size * 8; - vc1_decode_blocks(v); + for (i = 0; i <= n_slices; i++) { + if (i && get_bits1(&s->gb)) + vc1_parse_frame_header_adv(v, &s->gb); + vc1_decode_blocks(v, i == 0 ? 0 : FFMAX(0, slices[i-1].mby_start), + i == n_slices ? s->mb_height : FFMIN(s->mb_height, slices[i].mby_start)); + if (i != n_slices) s->gb = slices[i].gb; + } //av_log(s->avctx, AV_LOG_INFO, "Consumed %i/%i bits\n", get_bits_count(&s->gb), s->gb.size_in_bits); // if(get_bits_count(&s->gb) > buf_size * 8) // return -1; @@ -3318,10 +3345,16 @@ assert(s->current_picture.pict_type == s->pict_type); end: av_free(buf2); + for (i = 0; i < n_slices; i++) + av_free(slices[i].buf); + av_free(slices); return buf_size; err: av_free(buf2); + for (i = 0; i < n_slices; i++) + av_free(slices[i].buf); + av_free(slices); return -1; } |