summaryrefslogtreecommitdiffstats
path: root/libavcodec/vc1dec.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/vc1dec.c')
-rw-r--r--libavcodec/vc1dec.c214
1 files changed, 160 insertions, 54 deletions
diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c
index 81b0966..80eaca9 100644
--- a/libavcodec/vc1dec.c
+++ b/libavcodec/vc1dec.c
@@ -4,20 +4,20 @@
* Copyright (c) 2006-2007 Konstantin Shishkov
* Partly based on vc9.c (c) 2005 Anonymous, Alex Beregszaszi, Michael Niedermayer
*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
*
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -38,6 +38,7 @@
#include "unary.h"
#include "mathops.h"
#include "vdpau_internal.h"
+#include "libavutil/avassert.h"
#undef NDEBUG
#include <assert.h>
@@ -79,7 +80,7 @@ static void vc1_put_signed_blocks_clamped(VC1Context *v)
{
MpegEncContext *s = &v->s;
int topleft_mb_pos, top_mb_pos;
- int stride_y, fieldtx;
+ int stride_y, fieldtx = 0;
int v_dist;
/* The put pixels loop is always one MB row behind the decoding loop,
@@ -92,7 +93,8 @@ static void vc1_put_signed_blocks_clamped(VC1Context *v)
if (!s->first_slice_line) {
if (s->mb_x) {
topleft_mb_pos = (s->mb_y - 1) * s->mb_stride + s->mb_x - 1;
- fieldtx = v->fieldtx_plane[topleft_mb_pos];
+ if (v->fcm == ILACE_FRAME)
+ fieldtx = v->fieldtx_plane[topleft_mb_pos];
stride_y = s->linesize << fieldtx;
v_dist = (16 - fieldtx) >> (fieldtx == 0);
s->dsp.put_signed_pixels_clamped(v->block[v->topleft_blk_idx][0],
@@ -116,7 +118,8 @@ static void vc1_put_signed_blocks_clamped(VC1Context *v)
}
if (s->mb_x == s->mb_width - 1) {
top_mb_pos = (s->mb_y - 1) * s->mb_stride + s->mb_x;
- fieldtx = v->fieldtx_plane[top_mb_pos];
+ if (v->fcm == ILACE_FRAME)
+ fieldtx = v->fieldtx_plane[top_mb_pos];
stride_y = s->linesize << fieldtx;
v_dist = fieldtx ? 15 : 8;
s->dsp.put_signed_pixels_clamped(v->block[v->top_blk_idx][0],
@@ -368,7 +371,7 @@ static void vc1_mc_1mv(VC1Context *v, int dir)
}
if (v->field_mode) { // interlaced field picture
if (!dir) {
- if ((v->cur_field_type != v->ref_field_type[dir]) && v->cur_field_type) {
+ if ((v->cur_field_type != v->ref_field_type[dir]) && v->second_field) {
srcY = s->current_picture.f.data[0];
srcU = s->current_picture.f.data[1];
srcV = s->current_picture.f.data[2];
@@ -394,6 +397,9 @@ static void vc1_mc_1mv(VC1Context *v, int dir)
}
}
+ if(!srcY)
+ return;
+
src_x = s->mb_x * 16 + (mx >> 2);
src_y = s->mb_y * 16 + (my >> 2);
uvsrc_x = s->mb_x * 8 + (uvmx >> 2);
@@ -492,7 +498,7 @@ static void vc1_mc_1mv(VC1Context *v, int dir)
srcY += s->mspel * (1 + s->linesize);
}
- if (v->field_mode && v->cur_field_type) {
+ if (v->field_mode && v->second_field) {
off = s->current_picture_ptr->f.linesize[0];
off_uv = s->current_picture_ptr->f.linesize[1];
} else {
@@ -560,7 +566,7 @@ static void vc1_mc_4mv_luma(VC1Context *v, int n, int dir)
if (!dir) {
if (v->field_mode) {
- if ((v->cur_field_type != v->ref_field_type[dir]) && v->cur_field_type)
+ if ((v->cur_field_type != v->ref_field_type[dir]) && v->second_field)
srcY = s->current_picture.f.data[0];
else
srcY = s->last_picture.f.data[0];
@@ -569,6 +575,9 @@ static void vc1_mc_4mv_luma(VC1Context *v, int n, int dir)
} else
srcY = s->next_picture.f.data[0];
+ if(!srcY)
+ return;
+
if (v->field_mode) {
if (v->cur_field_type != v->ref_field_type[dir])
my = my - 2 + 4 * v->cur_field_type;
@@ -601,6 +610,8 @@ static void vc1_mc_4mv_luma(VC1Context *v, int n, int dir)
tx = (chosen_mv[f][0][0] + chosen_mv[f][1][0]) / 2;
ty = (chosen_mv[f][0][1] + chosen_mv[f][1][1]) / 2;
break;
+ default:
+ av_assert2(0);
}
s->current_picture.f.motion_val[1][s->block_index[0] + v->blocks_off][0] = tx;
s->current_picture.f.motion_val[1][s->block_index[0] + v->blocks_off][1] = ty;
@@ -629,7 +640,7 @@ static void vc1_mc_4mv_luma(VC1Context *v, int n, int dir)
off = ((n > 1) ? s->linesize : 0) + (n & 1) * 8;
else
off = s->linesize * 4 * (n & 2) + (n & 1) * 8;
- if (v->field_mode && v->cur_field_type)
+ if (v->field_mode && v->second_field)
off += s->current_picture_ptr->f.linesize[0];
src_x = s->mb_x * 16 + (n & 1) * 8 + (mx >> 2);
@@ -841,27 +852,33 @@ static void vc1_mc_4mv_chroma(VC1Context *v, int dir)
if (!dir) {
if (v->field_mode) {
if ((v->cur_field_type != chroma_ref_type) && v->cur_field_type) {
- srcU = s->current_picture.f.data[1] + uvsrc_y * s->uvlinesize + uvsrc_x;
- srcV = s->current_picture.f.data[2] + uvsrc_y * s->uvlinesize + uvsrc_x;
+ srcU = s->current_picture.f.data[1];
+ srcV = s->current_picture.f.data[2];
} else {
- srcU = s->last_picture.f.data[1] + uvsrc_y * s->uvlinesize + uvsrc_x;
- srcV = s->last_picture.f.data[2] + uvsrc_y * s->uvlinesize + uvsrc_x;
+ srcU = s->last_picture.f.data[1];
+ srcV = s->last_picture.f.data[2];
}
} else {
- srcU = s->last_picture.f.data[1] + uvsrc_y * s->uvlinesize + uvsrc_x;
- srcV = s->last_picture.f.data[2] + uvsrc_y * s->uvlinesize + uvsrc_x;
+ srcU = s->last_picture.f.data[1];
+ srcV = s->last_picture.f.data[2];
}
} else {
- srcU = s->next_picture.f.data[1] + uvsrc_y * s->uvlinesize + uvsrc_x;
- srcV = s->next_picture.f.data[2] + uvsrc_y * s->uvlinesize + uvsrc_x;
+ srcU = s->next_picture.f.data[1];
+ srcV = s->next_picture.f.data[2];
}
+ if(!srcU)
+ return;
+
+ srcU += uvsrc_y * s->uvlinesize + uvsrc_x;
+ srcV += uvsrc_y * s->uvlinesize + uvsrc_x;
+
if (v->field_mode) {
if (chroma_ref_type) {
srcU += s->current_picture_ptr->f.linesize[1];
srcV += s->current_picture_ptr->f.linesize[2];
}
- off = v->cur_field_type ? s->current_picture_ptr->f.linesize[1] : 0;
+ off = v->second_field ? s->current_picture_ptr->f.linesize[1] : 0;
}
if (v->rangeredfrm || (v->mv_mode == MV_PMODE_INTENSITY_COMP)
@@ -966,7 +983,8 @@ static void vc1_mc_4mv_chroma4(VC1Context *v)
uvmy_field[i] = (uvmy_field[i] & 3) << 1;
if (fieldmv && !(uvsrc_y & 1))
- v_edge_pos--;
+ v_edge_pos = (s->v_edge_pos >> 1) - 1;
+
if (fieldmv && (uvsrc_y & 1) && uvsrc_y < 2)
uvsrc_y--;
if ((v->mv_mode == MV_PMODE_INTENSITY_COMP)
@@ -1142,6 +1160,7 @@ static av_always_inline void get_mvdata_interlaced(VC1Context *v, int *dmv_x,
}
}
else {
+ av_assert0(index < esc);
if (extend_x)
offs_tab = offset_table2;
else
@@ -1738,9 +1757,10 @@ static inline void vc1_pred_mv_intfr(VC1Context *v, int n, int dmv_x, int dmv_y,
px = mid_pred(A[0], B[0], C[0]);
py = mid_pred(A[1], B[1], C[1]);
} else if (total_valid) {
- if (a_valid) { px = A[0]; py = A[1]; }
- if (b_valid) { px = B[0]; py = B[1]; }
- if (c_valid) { px = C[0]; py = C[1]; }
+ if (a_valid) { px = A[0]; py = A[1]; }
+ else if (b_valid) { px = B[0]; py = B[1]; }
+ else if (c_valid) { px = C[0]; py = C[1]; }
+ else av_assert2(0);
} else
px = py = 0;
}
@@ -1795,7 +1815,7 @@ static inline void vc1_pred_mv_intfr(VC1Context *v, int n, int dmv_x, int dmv_y,
} else if (c_valid) {
px = C[0];
py = C[1];
- }
+ } else px = py = 0;
}
} else if (total_valid == 1) {
px = (a_valid) ? A[0] : ((b_valid) ? B[0] : C[0]);
@@ -1928,7 +1948,7 @@ static void vc1_interp_mc(VC1Context *v)
srcY += s->mspel * (1 + s->linesize);
}
- if (v->field_mode && v->cur_field_type) {
+ if (v->field_mode && v->second_field) {
off = s->current_picture_ptr->f.linesize[0];
off_uv = s->current_picture_ptr->f.linesize[1];
} else {
@@ -2708,7 +2728,7 @@ static int vc1_decode_i_block_adv(VC1Context *v, int16_t block[64], int n,
MpegEncContext *s = &v->s;
int dc_pred_dir = 0; /* Direction of the DC prediction used */
int i;
- int16_t *dc_val;
+ int16_t *dc_val = NULL;
int16_t *ac_val, *ac_val2;
int dcdiff;
int a_avail = v->a_avail, c_avail = v->c_avail;
@@ -2920,7 +2940,7 @@ static int vc1_decode_intra_block(VC1Context *v, int16_t block[64], int n,
MpegEncContext *s = &v->s;
int dc_pred_dir = 0; /* Direction of the DC prediction used */
int i;
- int16_t *dc_val;
+ int16_t *dc_val = NULL;
int16_t *ac_val, *ac_val2;
int dcdiff;
int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
@@ -3695,7 +3715,7 @@ static int vc1_decode_p_mb_intfr(VC1Context *v)
int idx_mbmode = 0, mvbp;
int stride_y, fieldtx;
- mquant = v->pq; /* Loosy initialization */
+ mquant = v->pq; /* Lossy initialization */
if (v->skip_is_raw)
skipped = get_bits1(gb);
@@ -3899,11 +3919,11 @@ static int vc1_decode_p_mb_intfi(VC1Context *v)
int val; /* temp values */
int first_block = 1;
int dst_idx, off;
- int pred_flag;
+ int pred_flag = 0;
int block_cbp = 0, pat, block_tt = 0;
int idx_mbmode = 0;
- mquant = v->pq; /* Loosy initialization */
+ mquant = v->pq; /* Lossy initialization */
idx_mbmode = get_vlc2(gb, v->mbmode_vlc->table, VC1_IF_MBMODE_VLC_BITS, 2);
if (idx_mbmode <= 1) { // intra MB
@@ -3938,7 +3958,7 @@ static int vc1_decode_p_mb_intfi(VC1Context *v)
continue;
v->vc1dsp.vc1_inv_trans_8x8(s->block[i]);
off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize);
- off += v->cur_field_type ? ((i & 4) ? s->current_picture_ptr->f.linesize[1] : s->current_picture_ptr->f.linesize[0]) : 0;
+ off += v->second_field ? ((i & 4) ? s->current_picture_ptr->f.linesize[1] : s->current_picture_ptr->f.linesize[0]) : 0;
s->dsp.put_signed_pixels_clamped(s->block[i], s->dest[dst_idx] + off, (i & 4) ? s->uvlinesize : s->linesize);
// TODO: loop filter
}
@@ -3985,7 +4005,7 @@ static int vc1_decode_p_mb_intfi(VC1Context *v)
dst_idx += i >> 2;
val = ((cbp >> (5 - i)) & 1);
off = (i & 4) ? 0 : (i & 1) * 8 + (i & 2) * 4 * s->linesize;
- if (v->cur_field_type)
+ if (v->second_field)
off += (i & 4) ? s->current_picture_ptr->f.linesize[1] : s->current_picture_ptr->f.linesize[0];
if (val) {
pat = vc1_decode_p_block(v, s->block[i], i, mquant, ttmb,
@@ -4176,7 +4196,7 @@ static void vc1_decode_b_mb_intfi(VC1Context *v)
int bmvtype = BMV_TYPE_BACKWARD;
int idx_mbmode, interpmvp;
- mquant = v->pq; /* Loosy initialization */
+ mquant = v->pq; /* Lossy initialization */
s->mb_intra = 0;
idx_mbmode = get_vlc2(gb, v->mbmode_vlc->table, VC1_IF_MBMODE_VLC_BITS, 2);
@@ -4215,7 +4235,7 @@ static void vc1_decode_b_mb_intfi(VC1Context *v)
for (j = 0; j < 64; j++)
s->block[i][j] <<= 1;
off = (i & 4) ? 0 : ((i & 1) * 8 + (i & 2) * 4 * s->linesize);
- off += v->cur_field_type ? ((i & 4) ? s->current_picture_ptr->f.linesize[1] : s->current_picture_ptr->f.linesize[0]) : 0;
+ off += v->second_field ? ((i & 4) ? s->current_picture_ptr->f.linesize[1] : s->current_picture_ptr->f.linesize[0]) : 0;
s->dsp.put_signed_pixels_clamped(s->block[i], s->dest[dst_idx] + off, (i & 4) ? s->uvlinesize : s->linesize);
// TODO: yet to perform loop filter
}
@@ -4297,7 +4317,7 @@ static void vc1_decode_b_mb_intfi(VC1Context *v)
dst_idx += i >> 2;
val = ((cbp >> (5 - i)) & 1);
off = (i & 4) ? 0 : (i & 1) * 8 + (i & 2) * 4 * s->linesize;
- if (v->cur_field_type)
+ if (v->second_field)
off += (i & 4) ? s->current_picture_ptr->f.linesize[1] : s->current_picture_ptr->f.linesize[0];
if (val) {
vc1_decode_p_block(v, s->block[i], i, mquant, ttmb,
@@ -4648,7 +4668,7 @@ static void vc1_decode_p_blocks(VC1Context *v)
if (s->mb_y != s->start_mb_y) ff_draw_horiz_band(s, (s->mb_y - 1) * 16, 16);
s->first_slice_line = 0;
}
- if (apply_loop_filter) {
+ if (apply_loop_filter && v->fcm == PROGRESSIVE) {
s->mb_x = 0;
ff_init_block_index(s);
for (; s->mb_x < s->mb_width; s->mb_x++) {
@@ -4733,9 +4753,11 @@ static void vc1_decode_skip_blocks(VC1Context *v)
s->mb_x = 0;
ff_init_block_index(s);
ff_update_block_index(s);
- memcpy(s->dest[0], s->last_picture.f.data[0] + s->mb_y * 16 * s->linesize, s->linesize * 16);
- memcpy(s->dest[1], s->last_picture.f.data[1] + s->mb_y * 8 * s->uvlinesize, s->uvlinesize * 8);
- memcpy(s->dest[2], s->last_picture.f.data[2] + s->mb_y * 8 * s->uvlinesize, s->uvlinesize * 8);
+ if (s->last_picture.f.data[0]) {
+ memcpy(s->dest[0], s->last_picture.f.data[0] + s->mb_y * 16 * s->linesize, s->linesize * 16);
+ memcpy(s->dest[1], s->last_picture.f.data[1] + s->mb_y * 8 * s->uvlinesize, s->uvlinesize * 8);
+ memcpy(s->dest[2], s->last_picture.f.data[2] + s->mb_y * 8 * s->uvlinesize, s->uvlinesize * 8);
+ }
ff_draw_horiz_band(s, s->mb_y * 16, 16);
s->first_slice_line = 0;
}
@@ -5164,6 +5186,15 @@ static av_cold int vc1_decode_init(AVCodecContext *avctx)
if (ff_vc1_init_common(v) < 0)
return -1;
+ // ensure static VLC tables are initialized
+ if (ff_msmpeg4_decode_init(avctx) < 0)
+ return -1;
+ if (ff_vc1_decode_init_alloc_tables(v) < 0)
+ return -1;
+ // Hack to ensure the above functions will be called
+ // again once we know all necessary settings.
+ // That this is necessary might indicate a bug.
+ ff_vc1_decode_end(avctx);
ff_vc1dsp_init(&v->vc1dsp);
if (avctx->codec_id == AV_CODEC_ID_WMV3 || avctx->codec_id == AV_CODEC_ID_WMV3IMAGE) {
@@ -5316,14 +5347,19 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data,
MpegEncContext *s = &v->s;
AVFrame *pict = data;
uint8_t *buf2 = NULL;
- const uint8_t *buf_start = buf;
- int mb_height, n_slices1;
+ const uint8_t *buf_start = buf, *buf_start_second_field = NULL;
+ int mb_height, n_slices1=-1;
struct {
uint8_t *buf;
GetBitContext gb;
int mby_start;
} *slices = NULL, *tmp;
+ v->second_field = 0;
+
+ if(s->flags & CODEC_FLAG_LOW_DELAY)
+ s->low_delay = 1;
+
/* no supplementary picture */
if (buf_size == 0 || (buf_size == 4 && AV_RB32(buf) == VC1_CODE_ENDOFSEQ)) {
/* special case for last picture */
@@ -5334,7 +5370,7 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data,
*got_frame = 1;
}
- return 0;
+ return buf_size;
}
if (s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU) {
@@ -5367,6 +5403,9 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data,
break;
case VC1_CODE_FIELD: {
int buf_size3;
+ if (avctx->hwaccel ||
+ s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU)
+ buf_start_second_field = start;
tmp = av_realloc(slices, sizeof(*slices) * (n_slices+1));
if (!tmp)
goto err;
@@ -5418,6 +5457,9 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data,
av_log(avctx, AV_LOG_ERROR, "Error in WVC1 interlaced frame\n");
goto err;
} else { // found field marker, unescape second field
+ if (avctx->hwaccel ||
+ s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU)
+ buf_start_second_field = divider;
tmp = av_realloc(slices, sizeof(*slices) * (n_slices+1));
if (!tmp)
goto err;
@@ -5471,6 +5513,8 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data,
s->low_delay = !avctx->has_b_frames || v->res_sprite;
if (v->profile == PROFILE_ADVANCED) {
+ if(avctx->coded_width<=1 || avctx->coded_height<=1)
+ goto err;
s->h_edge_pos = avctx->coded_width;
s->v_edge_pos = avctx->coded_height;
}
@@ -5487,15 +5531,20 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data,
// do parse frame header
v->pic_header_flag = 0;
+ v->first_pic_header_flag = 1;
if (v->profile < PROFILE_ADVANCED) {
- if (ff_vc1_parse_frame_header(v, &s->gb) == -1) {
+ if (ff_vc1_parse_frame_header(v, &s->gb) < 0) {
goto err;
}
} else {
- if (ff_vc1_parse_frame_header_adv(v, &s->gb) == -1) {
+ if (ff_vc1_parse_frame_header_adv(v, &s->gb) < 0) {
goto err;
}
}
+ v->first_pic_header_flag = 0;
+
+ if (avctx->debug & FF_DEBUG_PICT_INFO)
+ av_log(v->s.avctx, AV_LOG_DEBUG, "pict_type: %c\n", av_get_picture_type_char(s->pict_type));
if ((avctx->codec_id == AV_CODEC_ID_WMV3IMAGE || avctx->codec_id == AV_CODEC_ID_VC1IMAGE)
&& s->pict_type != AV_PICTURE_TYPE_I) {
@@ -5503,6 +5552,11 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data,
goto err;
}
+ if ((s->mb_height >> v->field_mode) == 0) {
+ av_log(v->s.avctx, AV_LOG_ERROR, "image too short\n");
+ goto err;
+ }
+
// process pulldown flags
s->current_picture_ptr->f.repeat_pict = 0;
// Pulldown flags are only valid when 'broadcast' has been set.
@@ -5540,6 +5594,9 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data,
goto err;
}
+ v->s.current_picture_ptr->f.interlaced_frame = (v->fcm != PROGRESSIVE);
+ v->s.current_picture_ptr->f.top_field_first = v->tff;
+
s->me.qpel_put = s->dsp.put_qpel_pixels_tab;
s->me.qpel_avg = s->dsp.avg_qpel_pixels_tab;
@@ -5547,13 +5604,46 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data,
&&s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU)
ff_vdpau_vc1_decode_picture(s, buf_start, (buf + buf_size) - buf_start);
else if (avctx->hwaccel) {
- if (avctx->hwaccel->start_frame(avctx, buf, buf_size) < 0)
- goto err;
- if (avctx->hwaccel->decode_slice(avctx, buf_start, (buf + buf_size) - buf_start) < 0)
- goto err;
- if (avctx->hwaccel->end_frame(avctx) < 0)
- goto err;
+ if (v->field_mode && buf_start_second_field) {
+ // decode first field
+ s->picture_structure = PICT_BOTTOM_FIELD - v->tff;
+ if (avctx->hwaccel->start_frame(avctx, buf_start, buf_start_second_field - buf_start) < 0)
+ goto err;
+ if (avctx->hwaccel->decode_slice(avctx, buf_start, buf_start_second_field - buf_start) < 0)
+ goto err;
+ if (avctx->hwaccel->end_frame(avctx) < 0)
+ goto err;
+
+ // decode second field
+ s->gb = slices[n_slices1 + 1].gb;
+ s->picture_structure = PICT_TOP_FIELD + v->tff;
+ v->second_field = 1;
+ v->pic_header_flag = 0;
+ if (ff_vc1_parse_frame_header_adv(v, &s->gb) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "parsing header for second field failed");
+ goto err;
+ }
+ v->s.current_picture_ptr->f.pict_type = v->s.pict_type;
+
+ if (avctx->hwaccel->start_frame(avctx, buf_start_second_field, (buf + buf_size) - buf_start_second_field) < 0)
+ goto err;
+ if (avctx->hwaccel->decode_slice(avctx, buf_start_second_field, (buf + buf_size) - buf_start_second_field) < 0)
+ goto err;
+ if (avctx->hwaccel->end_frame(avctx) < 0)
+ goto err;
+ } else {
+ s->picture_structure = PICT_FRAME;
+ if (avctx->hwaccel->start_frame(avctx, buf_start, (buf + buf_size) - buf_start) < 0)
+ goto err;
+ if (avctx->hwaccel->decode_slice(avctx, buf_start, (buf + buf_size) - buf_start) < 0)
+ goto err;
+ if (avctx->hwaccel->end_frame(avctx) < 0)
+ goto err;
+ }
} else {
+ if (v->fcm == ILACE_FRAME && s->pict_type == AV_PICTURE_TYPE_B)
+ goto err; // This codepath is still incomplete thus it is disabled
+
ff_er_frame_start(s);
v->bits = buf_size * 8;
@@ -5584,7 +5674,7 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data,
continue;
}
v->second_field = 1;
- v->blocks_off = s->mb_width * s->mb_height << 1;
+ v->blocks_off = s->b8_stride * (s->mb_height&~1);
v->mb_off = s->mb_stride * s->mb_height >> 1;
} else {
v->second_field = 0;
@@ -5609,8 +5699,21 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data,
s->start_mb_y = (i == 0) ? 0 : FFMAX(0, slices[i-1].mby_start % mb_height);
if (!v->field_mode || v->second_field)
s->end_mb_y = (i == n_slices ) ? mb_height : FFMIN(mb_height, slices[i].mby_start % mb_height);
- else
+ else {
+ if (i >= n_slices) {
+ av_log(v->s.avctx, AV_LOG_ERROR, "first field slice count too large\n");
+ continue;
+ }
s->end_mb_y = (i <= n_slices1 + 1) ? mb_height : FFMIN(mb_height, slices[i].mby_start % mb_height);
+ }
+ if (s->end_mb_y <= s->start_mb_y) {
+ av_log(v->s.avctx, AV_LOG_ERROR, "end mb y %d %d invalid\n", s->end_mb_y, s->start_mb_y);
+ continue;
+ }
+ if (!v->p_frame_skipped && s->pict_type != AV_PICTURE_TYPE_I && !v->cbpcy_vlc) {
+ av_log(v->s.avctx, AV_LOG_ERROR, "missing cbpcy_vlc\n");
+ continue;
+ }
ff_vc1_decode_blocks(v);
if (i != n_slices)
s->gb = slices[i].gb;
@@ -5631,7 +5734,10 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data,
get_bits_count(&s->gb), s->gb.size_in_bits);
// if (get_bits_count(&s->gb) > buf_size * 8)
// return -1;
- ff_er_frame_end(s);
+ if(s->error_occurred && s->pict_type == AV_PICTURE_TYPE_B)
+ goto err;
+ if(!v->field_mode)
+ ff_er_frame_end(s);
}
ff_MPV_frame_end(s);
OpenPOWER on IntegriCloud