mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-13 21:28:01 +02:00
vc1: slice support.
Also reset coded_block at each new slice, fixes problems in slice playback.
This commit is contained in:
parent
b81a935bd9
commit
f44d6445b7
@ -2686,7 +2686,7 @@ static void vc1_decode_i_blocks(VC1Context *v)
|
|||||||
|
|
||||||
/** Decode blocks of I-frame for advanced profile
|
/** 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;
|
int k;
|
||||||
MpegEncContext *s = &v->s;
|
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_x = s->mb_y = 0;
|
||||||
s->mb_intra = 1;
|
s->mb_intra = 1;
|
||||||
s->first_slice_line = 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];
|
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;
|
s->mb_x = 0;
|
||||||
ff_init_block_index(s);
|
ff_init_block_index(s);
|
||||||
for(;s->mb_x < s->mb_width; s->mb_x++) {
|
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(v->s.loop_filter) vc1_loop_filter_iblk(v, v->pq);
|
||||||
|
|
||||||
if(get_bits_count(&s->gb) > v->bits) {
|
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);
|
av_log(s->avctx, AV_LOG_ERROR, "Bits overconsumption: %i > %i\n", get_bits_count(&s->gb), v->bits);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2828,10 +2835,10 @@ static void vc1_decode_i_blocks_adv(VC1Context *v)
|
|||||||
}
|
}
|
||||||
if (v->s.loop_filter)
|
if (v->s.loop_filter)
|
||||||
ff_draw_horiz_band(s, (s->mb_height-1)*16, 16);
|
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;
|
MpegEncContext *s = &v->s;
|
||||||
|
|
||||||
@ -2862,7 +2869,7 @@ static void vc1_decode_p_blocks(VC1Context *v)
|
|||||||
|
|
||||||
s->first_slice_line = 1;
|
s->first_slice_line = 1;
|
||||||
memset(v->cbp_base, 0, sizeof(v->cbp_base[0])*2*s->mb_stride);
|
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;
|
s->mb_x = 0;
|
||||||
ff_init_block_index(s);
|
ff_init_block_index(s);
|
||||||
for(; s->mb_x < s->mb_width; s->mb_x++) {
|
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);
|
vc1_decode_p_mb(v);
|
||||||
if(get_bits_count(&s->gb) > v->bits || get_bits_count(&s->gb) < 0) {
|
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);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
@ -2879,10 +2886,10 @@ static void vc1_decode_p_blocks(VC1Context *v)
|
|||||||
ff_draw_horiz_band(s, s->mb_y * 16, 16);
|
ff_draw_horiz_band(s, s->mb_y * 16, 16);
|
||||||
s->first_slice_line = 0;
|
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;
|
MpegEncContext *s = &v->s;
|
||||||
|
|
||||||
@ -2912,7 +2919,7 @@ static void vc1_decode_b_blocks(VC1Context *v)
|
|||||||
}
|
}
|
||||||
|
|
||||||
s->first_slice_line = 1;
|
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;
|
s->mb_x = 0;
|
||||||
ff_init_block_index(s);
|
ff_init_block_index(s);
|
||||||
for(; s->mb_x < s->mb_width; s->mb_x++) {
|
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);
|
vc1_decode_b_mb(v);
|
||||||
if(get_bits_count(&s->gb) > v->bits || get_bits_count(&s->gb) < 0) {
|
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);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
@ -2934,7 +2941,7 @@ static void vc1_decode_b_blocks(VC1Context *v)
|
|||||||
}
|
}
|
||||||
if (v->s.loop_filter)
|
if (v->s.loop_filter)
|
||||||
ff_draw_horiz_band(s, (s->mb_height-1)*16, 16);
|
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)
|
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;
|
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;
|
v->s.esc3_level_length = 0;
|
||||||
if(v->x8_type){
|
if(v->x8_type){
|
||||||
ff_intrax8_decode_picture(&v->x8, 2*v->pq+v->halfpq, v->pq*(!v->pquantizer) );
|
ff_intrax8_decode_picture(&v->x8, 2*v->pq+v->halfpq, v->pq*(!v->pquantizer) );
|
||||||
}else{
|
}else{
|
||||||
|
|
||||||
switch(v->s.pict_type) {
|
switch(v->s.pict_type) {
|
||||||
case FF_I_TYPE:
|
case FF_I_TYPE:
|
||||||
if(v->profile == PROFILE_ADVANCED)
|
if(v->profile == PROFILE_ADVANCED)
|
||||||
vc1_decode_i_blocks_adv(v);
|
vc1_decode_i_blocks_adv(v, mby_start, mby_end);
|
||||||
else
|
else
|
||||||
vc1_decode_i_blocks(v);
|
vc1_decode_i_blocks(v);
|
||||||
break;
|
break;
|
||||||
@ -2975,16 +2981,16 @@ static void vc1_decode_blocks(VC1Context *v)
|
|||||||
if(v->p_frame_skipped)
|
if(v->p_frame_skipped)
|
||||||
vc1_decode_skip_blocks(v);
|
vc1_decode_skip_blocks(v);
|
||||||
else
|
else
|
||||||
vc1_decode_p_blocks(v);
|
vc1_decode_p_blocks(v, mby_start, mby_end);
|
||||||
break;
|
break;
|
||||||
case FF_B_TYPE:
|
case FF_B_TYPE:
|
||||||
if(v->bi_type){
|
if(v->bi_type){
|
||||||
if(v->profile == PROFILE_ADVANCED)
|
if(v->profile == PROFILE_ADVANCED)
|
||||||
vc1_decode_i_blocks_adv(v);
|
vc1_decode_i_blocks_adv(v, mby_start, mby_end);
|
||||||
else
|
else
|
||||||
vc1_decode_i_blocks(v);
|
vc1_decode_i_blocks(v);
|
||||||
}else
|
}else
|
||||||
vc1_decode_b_blocks(v);
|
vc1_decode_b_blocks(v, mby_start, mby_end);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3145,12 +3151,17 @@ static int vc1_decode_frame(AVCodecContext *avctx,
|
|||||||
AVPacket *avpkt)
|
AVPacket *avpkt)
|
||||||
{
|
{
|
||||||
const uint8_t *buf = avpkt->data;
|
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;
|
VC1Context *v = avctx->priv_data;
|
||||||
MpegEncContext *s = &v->s;
|
MpegEncContext *s = &v->s;
|
||||||
AVFrame *pict = data;
|
AVFrame *pict = data;
|
||||||
uint8_t *buf2 = NULL;
|
uint8_t *buf2 = NULL;
|
||||||
const uint8_t *buf_start = buf;
|
const uint8_t *buf_start = buf;
|
||||||
|
struct {
|
||||||
|
uint8_t *buf;
|
||||||
|
GetBitContext gb;
|
||||||
|
int mby_start;
|
||||||
|
} *slices = NULL;
|
||||||
|
|
||||||
/* no supplementary picture */
|
/* no supplementary picture */
|
||||||
if (buf_size == 0 || (buf_size == 4 && AV_RB32(buf) == VC1_CODE_ENDOFSEQ)) {
|
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);
|
init_get_bits(&s->gb, buf2, buf_size2*8);
|
||||||
vc1_decode_entry_point(avctx, v, &s->gb);
|
vc1_decode_entry_point(avctx, v, &s->gb);
|
||||||
break;
|
break;
|
||||||
case VC1_CODE_SLICE:
|
case VC1_CODE_SLICE: {
|
||||||
av_log(avctx, AV_LOG_ERROR, "Sliced decoding is not implemented (yet)\n");
|
int buf_size3;
|
||||||
av_free(buf2);
|
slices = av_realloc(slices, sizeof(*slices) * (n_slices+1));
|
||||||
return -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 */
|
}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);
|
ff_er_frame_start(s);
|
||||||
|
|
||||||
v->bits = buf_size * 8;
|
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);
|
//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)
|
// if(get_bits_count(&s->gb) > buf_size * 8)
|
||||||
// return -1;
|
// return -1;
|
||||||
@ -3318,10 +3345,16 @@ assert(s->current_picture.pict_type == s->pict_type);
|
|||||||
|
|
||||||
end:
|
end:
|
||||||
av_free(buf2);
|
av_free(buf2);
|
||||||
|
for (i = 0; i < n_slices; i++)
|
||||||
|
av_free(slices[i].buf);
|
||||||
|
av_free(slices);
|
||||||
return buf_size;
|
return buf_size;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
av_free(buf2);
|
av_free(buf2);
|
||||||
|
for (i = 0; i < n_slices; i++)
|
||||||
|
av_free(slices[i].buf);
|
||||||
|
av_free(slices);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user