+ int x, y, i;
+ uint8_t lru[3][8];
+
+ for (i = 0; i < 3; i++)
+ memcpy(lru[i], def_lru, 8 * sizeof(*def_lru));
+
+ for (y = 0; y < height; y+=2) {
+ for (x = 0; x < width; x += 2) {
+ Y[x + 0 + 0 * ystride] = decode_sym(gb, lru[0]);
+ Y[x + 1 + 0 * ystride] = decode_sym(gb, lru[0]);
+ Y[x + 0 + 1 * ystride] = decode_sym(gb, lru[0]);
+ Y[x + 1 + 1 * ystride] = decode_sym(gb, lru[0]);
+ U[x >> 1] = decode_sym(gb, lru[1]) ^ 0x80;
+ V[x >> 1] = decode_sym(gb, lru[2]) ^ 0x80;
+ }
+
+ Y += ystride << 1;
+ U += ustride;
+ V += vstride;
+ }
+
+ return 0;
+}
+
+static int dxtory_decode_v2(AVCodecContext *avctx, AVFrame *pic,
+ const uint8_t *src, int src_size)
+{
+ GetByteContext gb;
+ GetBitContext gb2;
+ int nslices, slice, slice_height;
+ 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 || avctx->height % nslices) {
+ avpriv_request_sample(avctx, "%d slices for %dx%d", nslices,
+ avctx->width, avctx->height);
+ return AVERROR(ENOSYS);
+ }
+
+ slice_height = avctx->height / nslices;
+ if ((avctx->width & 1) || (slice_height & 1)) {
+ avpriv_request_sample(avctx, "slice dimensions %dx%d",
+ avctx->width, slice_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];
+
+ for (slice = 0; slice < nslices; slice++) {
+ slice_size = bytestream2_get_le32(&gb);
+ if (slice_size > src_size - off) {
+ av_log(avctx, AV_LOG_ERROR,
+ "invalid slice size %d (only %d bytes left)\n",
+ slice_size, src_size - off);
+ return AVERROR_INVALIDDATA;
+ }
+ if (slice_size <= 16) {
+ av_log(avctx, AV_LOG_ERROR, "invalid slice size %d\n", slice_size);
+ return AVERROR_INVALIDDATA;
+ }
+
+ if (AV_RL32(src + off) != slice_size - 16) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Slice sizes mismatch: got %d instead of %d\n",
+ AV_RL32(src + off), slice_size - 16);
+ }
+ init_get_bits(&gb2, src + off + 16, (slice_size - 16) * 8);
+ dx2_decode_slice(&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;
+ }