- GetByteContext gb;
- GetBitContext gb2;
- int nslices, slice, slice_height;
- int cur_y, next_y;
- uint32_t off, slice_size;
- uint8_t *Y, *U, *V;
- int ret;
-
- bytestream2_init(&gb, src, src_size);
- nslices = bytestream2_get_le16(&gb);
- off = FFALIGN(nslices * 4 + 2, 16);
- if (src_size < off) {
- av_log(avctx, AV_LOG_ERROR, "no slice data\n");
- return AVERROR_INVALIDDATA;
- }
-
- if (!nslices) {
- avpriv_request_sample(avctx, "%d slices for %dx%d", nslices,
- avctx->width, avctx->height);
- return AVERROR_PATCHWELCOME;
- }
-
- if ((avctx->width & 1) || (avctx->height & 1)) {
- avpriv_request_sample(avctx, "Frame dimensions %dx%d",
- avctx->width, avctx->height);
- }
-
- avctx->pix_fmt = AV_PIX_FMT_YUV420P;
- if ((ret = ff_get_buffer(avctx, pic, 0)) < 0)
- return ret;
-
- Y = pic->data[0];
- U = pic->data[1];
- V = pic->data[2];
-
- cur_y = 0;
- for (slice = 0; slice < nslices; slice++) {
- slice_size = bytestream2_get_le32(&gb);
- next_y = ((slice + 1) * avctx->height) / nslices;
- slice_height = (next_y & ~1) - (cur_y & ~1);
- if (slice_size > src_size - off) {
- av_log(avctx, AV_LOG_ERROR,
- "invalid slice size %"PRIu32" (only %"PRIu32" bytes left)\n",
- slice_size, src_size - off);
- return AVERROR_INVALIDDATA;
- }
- if (slice_size <= 16) {
- av_log(avctx, AV_LOG_ERROR, "invalid slice size %"PRIu32"\n", slice_size);
- return AVERROR_INVALIDDATA;
- }
-
- if (AV_RL32(src + off) != slice_size - 16) {
- av_log(avctx, AV_LOG_ERROR,
- "Slice sizes mismatch: got %"PRIu32" instead of %"PRIu32"\n",
- AV_RL32(src + off), slice_size - 16);
- }
- if ((ret = init_get_bits8(&gb2, src + off + 16, slice_size - 16)) < 0)
- return ret;
- dx2_decode_slice_420(&gb2, avctx->width, slice_height, Y, U, V,
- pic->linesize[0], pic->linesize[1],
- pic->linesize[2]);
-
- Y += pic->linesize[0] * slice_height;
- U += pic->linesize[1] * (slice_height >> 1);
- V += pic->linesize[2] * (slice_height >> 1);
- off += slice_size;
- cur_y = next_y;
- }
-
- return 0;