static int decode_plane(UtvideoContext *c, int plane_no, uint8_t *dst, int step, ptrdiff_t stride, int width, int height, const uint8_t *src, int use_pred) { int i, j, slice, pix; int sstart, send; VLC vlc; GetBitContext gb; int prev, fsym; const int cmask = c->interlaced ? ~(1 + 2 * (!plane_no && c->avctx->pix_fmt == AV_PIX_FMT_YUV420P)) : ~(!plane_no && c->avctx->pix_fmt == AV_PIX_FMT_YUV420P); if (build_huff(src, &vlc, &fsym)) { av_log(c->avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n"); return AVERROR_INVALIDDATA; } if (fsym >= 0) { // build_huff reported a symbol to fill slices with send = 0; for (slice = 0; slice < c->slices; slice++) { uint8_t *dest; sstart = send; send = (height * (slice + 1) / c->slices) & cmask; dest = dst + sstart * stride; prev = 0x80; for (j = sstart; j < send; j++) { for (i = 0; i < width * step; i += step) { pix = fsym; if (use_pred) { prev += pix; pix = prev; } dest[i] = pix; } dest += stride; } } return 0; } src += 256; send = 0; for (slice = 0; slice < c->slices; slice++) { uint8_t *dest; int slice_data_start, slice_data_end, slice_size; sstart = send; send = (height * (slice + 1) / c->slices) & cmask; dest = dst + sstart * stride; // slice offset and size validation was done earlier slice_data_start = slice ? AV_RL32(src + slice * 4 - 4) : 0; slice_data_end = AV_RL32(src + slice * 4); slice_size = slice_data_end - slice_data_start; if (!slice_size) { av_log(c->avctx, AV_LOG_ERROR, "Plane has more than one symbol " "yet a slice has a length of zero.\n"); goto fail; } memset(c->slice_bits + slice_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); c->bdsp.bswap_buf((uint32_t *) c->slice_bits, (uint32_t *)(src + slice_data_start + c->slices * 4), (slice_data_end - slice_data_start + 3) >> 2); init_get_bits(&gb, c->slice_bits, slice_size * 8); prev = 0x80; for (j = sstart; j < send; j++) { for (i = 0; i < width * step; i += step) { pix = get_vlc2(&gb, vlc.table, VLC_BITS, 3); if (pix < 0) { av_log(c->avctx, AV_LOG_ERROR, "Decoding error\n"); goto fail; } if (use_pred) { prev += pix; pix = prev; } dest[i] = pix; } if (get_bits_left(&gb) < 0) { av_log(c->avctx, AV_LOG_ERROR, "Slice decoding ran out of bits\n"); goto fail; } dest += stride; } if (get_bits_left(&gb) > 32) av_log(c->avctx, AV_LOG_WARNING, "%d bits left after decoding slice\n", get_bits_left(&gb)); } ff_free_vlc(&vlc); return 0; fail: ff_free_vlc(&vlc); return AVERROR_INVALIDDATA; }