+static void magicyuv_median_pred10(uint16_t *dst, const uint16_t *src1,
+ const uint16_t *diff, intptr_t w,
+ int *left, int *left_top)
+{
+ int i;
+ uint16_t l, lt;
+
+ l = *left;
+ lt = *left_top;
+
+ for (i = 0; i < w; i++) {
+ l = mid_pred(l, src1[i], (l + src1[i] - lt)) + diff[i];
+ l &= 0x3FF;
+ lt = src1[i];
+ dst[i] = l;
+ }
+
+ *left = l;
+ *left_top = lt;
+}
+
+static int magy_decode_slice10(AVCodecContext *avctx, void *tdata,
+ int j, int threadnr)
+{
+ MagicYUVContext *s = avctx->priv_data;
+ int interlaced = s->interlaced;
+ AVFrame *p = s->p;
+ int i, k, x;
+ GetBitContext gb;
+ uint16_t *dst;
+
+ for (i = 0; i < s->planes; i++) {
+ int left, lefttop, top;
+ int height = AV_CEIL_RSHIFT(FFMIN(s->slice_height, avctx->coded_height - j * s->slice_height), s->vshift[i]);
+ int width = AV_CEIL_RSHIFT(avctx->coded_width, s->hshift[i]);
+ int sheight = AV_CEIL_RSHIFT(s->slice_height, s->vshift[i]);
+ ptrdiff_t fake_stride = (p->linesize[i] / 2) * (1 + interlaced);
+ ptrdiff_t stride = p->linesize[i] / 2;
+ int flags, pred;
+ int ret = init_get_bits8(&gb, s->buf + s->slices[i][j].start,
+ s->slices[i][j].size);
+
+ if (ret < 0)
+ return ret;
+
+ flags = get_bits(&gb, 8);
+ pred = get_bits(&gb, 8);
+
+ dst = (uint16_t *)p->data[i] + j * sheight * stride;
+ if (flags & 1) {
+ for (k = 0; k < height; k++) {
+ for (x = 0; x < width; x++)
+ dst[x] = get_bits(&gb, 10);
+
+ dst += stride;
+ }
+ } else {
+ for (k = 0; k < height; k++) {
+ for (x = 0; x < width; x++) {
+ int pix;
+ if (get_bits_left(&gb) <= 0)
+ return AVERROR_INVALIDDATA;
+
+ pix = get_vlc2(&gb, s->vlc[i].table, s->vlc[i].bits, 3);
+ if (pix < 0)
+ return AVERROR_INVALIDDATA;
+
+ dst[x] = 1023 - pix;
+ }
+ dst += stride;
+ }
+ }
+
+ switch (pred) {
+ case LEFT:
+ dst = (uint16_t *)p->data[i] + j * sheight * stride;
+ s->llviddsp.add_left_pred_int16(dst, dst, 1023, width, 0);
+ dst += stride;
+ if (interlaced) {
+ s->llviddsp.add_left_pred_int16(dst, dst, 1023, width, 0);
+ dst += stride;
+ }
+ for (k = 1 + interlaced; k < height; k++) {
+ s->llviddsp.add_left_pred_int16(dst, dst, 1023, width, dst[-fake_stride]);
+ dst += stride;
+ }
+ break;
+ case GRADIENT:
+ dst = (uint16_t *)p->data[i] + j * sheight * stride;
+ s->llviddsp.add_left_pred_int16(dst, dst, 1023, width, 0);
+ left = lefttop = 0;
+ dst += stride;
+ if (interlaced) {
+ s->llviddsp.add_left_pred_int16(dst, dst, 1023, width, 0);
+ left = lefttop = 0;
+ dst += stride;
+ }
+ for (k = 1 + interlaced; k < height; k++) {
+ top = dst[-fake_stride];
+ left = top + dst[0];
+ dst[0] = left & 0x3FF;
+ for (x = 1; x < width; x++) {
+ top = dst[x - fake_stride];
+ lefttop = dst[x - (fake_stride + 1)];
+ left += top - lefttop + dst[x];
+ dst[x] = left & 0x3FF;
+ }
+ dst += stride;
+ }
+ break;
+ case MEDIAN:
+ dst = (uint16_t *)p->data[i] + j * sheight * stride;
+ lefttop = left = dst[0];
+ s->llviddsp.add_left_pred_int16(dst, dst, 1023, width, 0);
+ dst += stride;
+ if (interlaced) {
+ lefttop = left = dst[0];
+ s->llviddsp.add_left_pred_int16(dst, dst, 1023, width, 0);
+ dst += stride;
+ }
+ for (k = 1 + interlaced; k < height; k++) {
+ magicyuv_median_pred10(dst, dst - fake_stride, dst, width, &left, &lefttop);
+ lefttop = left = dst[0];
+ dst += stride;
+ }
+ break;
+ default:
+ avpriv_request_sample(avctx, "Unknown prediction: %d", pred);
+ }
+ }
+
+ if (s->decorrelate) {
+ int height = FFMIN(s->slice_height, avctx->coded_height - j * s->slice_height);
+ int width = avctx->coded_width;
+ uint16_t *r = (uint16_t *)p->data[0] + j * s->slice_height * p->linesize[0] / 2;
+ uint16_t *g = (uint16_t *)p->data[1] + j * s->slice_height * p->linesize[1] / 2;
+ uint16_t *b = (uint16_t *)p->data[2] + j * s->slice_height * p->linesize[2] / 2;
+
+ for (i = 0; i < height; i++) {
+ for (k = 0; k < width; k++) {
+ b[k] = (b[k] + g[k]) & 0x3FF;
+ r[k] = (r[k] + g[k]) & 0x3FF;
+ }
+ b += p->linesize[0] / 2;
+ g += p->linesize[1] / 2;
+ r += p->linesize[2] / 2;
+ }
+ }
+
+ return 0;
+}
+