static int xan_decode_chroma(AVCodecContext *avctx, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; XanContext *s = avctx->priv_data; uint8_t *U, *V; unsigned chroma_off; int val, uval, vval; int i, j; const uint8_t *src, *src_end; const uint8_t *table; int mode, offset, dec_size; chroma_off = AV_RL32(buf + 4); if (!chroma_off) return 0; if (chroma_off + 10 >= avpkt->size) { av_log(avctx, AV_LOG_ERROR, "Invalid chroma block position\n"); return -1; } src = avpkt->data + 4 + chroma_off; table = src + 2; mode = bytestream_get_le16(&src); offset = bytestream_get_le16(&src) * 2; if (src - avpkt->data >= avpkt->size - offset) { av_log(avctx, AV_LOG_ERROR, "Invalid chroma block offset\n"); return -1; } memset(s->scratch_buffer, 0, s->buffer_size); dec_size = xan_unpack(s->scratch_buffer, s->buffer_size, src + offset, avpkt->size - offset - (src - avpkt->data)); if (dec_size < 0) { av_log(avctx, AV_LOG_ERROR, "Chroma unpacking failed\n"); return -1; } U = s->pic.data[1]; V = s->pic.data[2]; src = s->scratch_buffer; src_end = src + dec_size; if (mode) { for (j = 0; j < avctx->height >> 1; j++) { for (i = 0; i < avctx->width >> 1; i++) { val = *src++; if (val) { val = AV_RL16(table + (val << 1)); uval = (val >> 3) & 0xF8; vval = (val >> 8) & 0xF8; U[i] = uval | (uval >> 5); V[i] = vval | (vval >> 5); } if (src == src_end) return 0; } U += s->pic.linesize[1]; V += s->pic.linesize[2]; } } else { uint8_t *U2 = U + s->pic.linesize[1]; uint8_t *V2 = V + s->pic.linesize[2]; for (j = 0; j < avctx->height >> 2; j++) { for (i = 0; i < avctx->width >> 1; i += 2) { val = *src++; if (val) { val = AV_RL16(table + (val << 1)); uval = (val >> 3) & 0xF8; vval = (val >> 8) & 0xF8; U[i] = U[i+1] = U2[i] = U2[i+1] = uval | (uval >> 5); V[i] = V[i+1] = V2[i] = V2[i+1] = vval | (vval >> 5); } } U += s->pic.linesize[1] * 2; V += s->pic.linesize[2] * 2; U2 += s->pic.linesize[1] * 2; V2 += s->pic.linesize[2] * 2; } } return 0; }
static int xan_decode_chroma(AVCodecContext *avctx, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; XanContext *s = avctx->priv_data; uint8_t *U, *V; unsigned chroma_off; int val, uval, vval; int i, j; const uint8_t *src, *src_end; const uint8_t *table; int mode, offset, dec_size; chroma_off = AV_RL32(buf + 4); if (!chroma_off) return 0; if (chroma_off + 10 >= avpkt->size) { av_log(avctx, AV_LOG_ERROR, "Invalid chroma block position\n"); return -1; } src = avpkt->data + 4 + chroma_off; table = src + 2; mode = bytestream_get_le16(&src); offset = bytestream_get_le16(&src) * 2; if (src - avpkt->data >= avpkt->size - offset) { av_log(avctx, AV_LOG_ERROR, "Invalid chroma block offset\n"); return -1; } memset(s->scratch_buffer, 0, s->buffer_size); dec_size = xan_unpack(s->scratch_buffer, s->buffer_size, src + offset, avpkt->size - offset - (src - avpkt->data)); if (dec_size < 0) { av_log(avctx, AV_LOG_ERROR, "Chroma unpacking failed\n"); return -1; } U = s->pic.data[1]; V = s->pic.data[2]; src = s->scratch_buffer; src_end = src + dec_size; if (mode) { for (j = 0; j < avctx->height >> 1; j++) { for (i = 0; i < avctx->width >> 1; i++) { val = *src++; if (val) { val = AV_RL16(table + (val << 1)); uval = (val >> 3) & 0xF8; vval = (val >> 8) & 0xF8; U[i] = uval | (uval >> 5); V[i] = vval | (vval >> 5); } if (src == src_end) return 0; } U += s->pic.linesize[1]; V += s->pic.linesize[2]; } } else { uint8_t *U2 = U + s->pic.linesize[1]; uint8_t *V2 = V + s->pic.linesize[2]; for (j = 0; j < avctx->height >> 2; j++) { for (i = 0; i < avctx->width >> 1; i += 2) { val = *src++; if (val) { val = AV_RL16(table + (val << 1)); uval = (val >> 3) & 0xF8; vval = (val >> 8) & 0xF8; U[i] = U[i+1] = U2[i] = U2[i+1] = uval | (uval >> 5); V[i] = V[i+1] = V2[i] = V2[i+1] = vval | (vval >> 5); } } U += s->pic.linesize[1] * 2; V += s->pic.linesize[2] * 2; U2 += s->pic.linesize[1] * 2; V2 += s->pic.linesize[2] * 2; } } return 0; }