X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fprosumer.c;h=9950519604c53a8f8f618a8527708095d3f8534e;hb=42eb78059d149abcd994f46c8b8a0dd98e86b594;hp=9e8a94d4dbecd5742f8a4c64d980f85f70228d4f;hpb=fa1d3caef0cbe24d2e74e3410495344c5aee9776;p=ffmpeg diff --git a/libavcodec/prosumer.c b/libavcodec/prosumer.c index 9e8a94d4dbe..9950519604c 100644 --- a/libavcodec/prosumer.c +++ b/libavcodec/prosumer.c @@ -38,8 +38,8 @@ typedef struct ProSumerContext { unsigned stride; unsigned size; - uint32_t lut[0x10000]; - uint8_t *table_b; + uint32_t lut[0x2000]; + uint8_t *initial_line; uint8_t *decbuffer; } ProSumerContext; @@ -57,25 +57,25 @@ static int decompress(GetByteContext *gb, int size, PutByteContext *pb, const ui b = lut[2 * idx]; while (1) { - if (((b & 0xFF00u) != 0x8000u) || (b & 0xFFu)) { + if (bytestream2_get_bytes_left_p(pb) <= 0 || bytestream2_get_eof(pb)) + return 0; + if ((b & 0xFF00u) != 0x8000u || (b & 0xFFu)) { if ((b & 0xFF00u) != 0x8000u) { bytestream2_put_le16(pb, b); - } else if (b & 0xFFu) { + } else { idx = 0; for (int i = 0; i < (b & 0xFFu); i++) bytestream2_put_le32(pb, 0); } c = b >> 16; if (c & 0xFF00u) { - c = (((c >> 8) & 0xFFu) | (c & 0xFF00)) & 0xF00F; fill = lut[2 * idx + 1]; - if ((c & 0xFF00u) == 0x1000) { + if ((c & 0xF000u) == 0x1000) { bytestream2_put_le16(pb, fill); - c &= 0xFFFF00FFu; } else { bytestream2_put_le32(pb, fill); - c &= 0xFFFF00FFu; } + c = (c >> 8) & 0x0Fu; } while (c) { a <<= 4; @@ -84,21 +84,20 @@ static int decompress(GetByteContext *gb, int size, PutByteContext *pb, const ui if (bytestream2_get_bytes_left(gb) <= 0) { if (!a) return 0; - cnt = 4; } else { - pos = bytestream2_tell(gb) ^ 2; - bytestream2_seek(gb, pos, SEEK_SET); + pos = bytestream2_tell(gb); + bytestream2_seek(gb, pos ^ 2, SEEK_SET); AV_WN16(&a, bytestream2_peek_le16(gb)); - pos = pos ^ 2; - bytestream2_seek(gb, pos, SEEK_SET); - bytestream2_skip(gb, 2); - cnt = 4; + bytestream2_seek(gb, pos + 2, SEEK_SET); } + cnt = 4; } c--; } idx = a >> 20; b = lut[2 * idx]; + if (!b) + return AVERROR_INVALIDDATA; continue; } idx = 2; @@ -117,12 +116,10 @@ static int decompress(GetByteContext *gb, int size, PutByteContext *pb, const ui } return 0; } - pos = bytestream2_tell(gb) ^ 2; - bytestream2_seek(gb, pos, SEEK_SET); + pos = bytestream2_tell(gb); + bytestream2_seek(gb, pos ^ 2, SEEK_SET); AV_WN16(&a, bytestream2_peek_le16(gb)); - pos = pos ^ 2; - bytestream2_seek(gb, pos, SEEK_SET); - bytestream2_skip(gb, 2); + bytestream2_seek(gb, pos + 2, SEEK_SET); cnt = 4; idx--; } @@ -132,15 +129,13 @@ static int decompress(GetByteContext *gb, int size, PutByteContext *pb, const ui return 0; } -static void do_shift(uint32_t *dst, int offset, uint32_t *src, int stride, int height) +static void vertical_predict(uint32_t *dst, int offset, const uint32_t *src, int stride, int height) { - uint32_t x = (0x7F7F7F7F >> 1) & 0x7F7F7F7F; - dst += offset >> 2; for (int i = 0; i < height; i++) { for (int j = 0; j < stride >> 2; j++) { - dst[j] = (((src[j] >> 3) + (x & dst[j])) << 3) & 0xFCFCFCFC; + dst[j] = (((src[j] >> 3) + (0x3F3F3F3F & dst[j])) << 3) & 0xFCFCFCFC; } dst += stride >> 2; @@ -158,13 +153,19 @@ static int decode_frame(AVCodecContext *avctx, void *data, if (avpkt->size <= 32) return AVERROR_INVALIDDATA; - memset(s->decbuffer, 0, s->size); bytestream2_init(&s->gb, avpkt->data, avpkt->size); bytestream2_init_writer(&s->pb, s->decbuffer, s->size); + ret = decompress(&s->gb, AV_RL32(avpkt->data + 28) >> 1, &s->pb, s->lut); + if (ret < 0) + return ret; + if (bytestream2_get_bytes_left_p(&s->pb) > s->size * (int64_t)avctx->discard_damaged_percentage / 100) + return AVERROR_INVALIDDATA; + + av_assert0(s->size >= bytestream2_get_bytes_left_p(&s->pb)); + memset(s->decbuffer + bytestream2_tell_p(&s->pb), 0, bytestream2_get_bytes_left_p(&s->pb)); - decompress(&s->gb, AV_RL32(avpkt->data + 28) >> 1, &s->pb, s->lut); - do_shift((uint32_t *)s->decbuffer, 0, (uint32_t *)s->table_b, s->stride, 1); - do_shift((uint32_t *)s->decbuffer, s->stride, (uint32_t *)s->decbuffer, s->stride, avctx->height - 1); + vertical_predict((uint32_t *)s->decbuffer, 0, (uint32_t *)s->initial_line, s->stride, 1); + vertical_predict((uint32_t *)s->decbuffer, s->stride, (uint32_t *)s->decbuffer, s->stride, avctx->height - 1); ret = ff_get_buffer(avctx, frame, 0); if (ret < 0) @@ -174,7 +175,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, uint8_t *y = &frame->data[0][i * frame->linesize[0]]; uint8_t *u = &frame->data[1][i * frame->linesize[1]]; uint8_t *v = &frame->data[2][i * frame->linesize[2]]; - uint8_t *src = s->decbuffer + (avctx->height - 1 - i) * s->stride; + const uint8_t *src = s->decbuffer + (avctx->height - 1 - i) * s->stride; for (int j = 0; j < avctx->width; j += 8) { *(u++) = *src++; @@ -276,15 +277,14 @@ static const uint16_t table[] = { 0x8022, 0xDAC, 0x8023, 0xDAD, 0x8024, 0xDAE, 0x8025, 0xDAF, 0x8026, 0xDB0, 0x8027, 0xDB1, 0x8028, 0xDB2, 0x8029, 0xDB3, 0x802A, 0xDB4, 0x802B, 0xDB5, 0x802C, 0xDB6, 0x802D, 0xDB7, 0x802E, 0xDB8, 0x802F, 0xDB9, 0x80FF, 0xDBA, - 0x0001 }; -static void fill_elements(uint32_t idx, uint32_t shift, int size, uint32_t *e0, uint32_t *e1) +static void fill_elements(uint32_t idx, uint32_t shift, uint32_t *e0, uint32_t *e1) { uint32_t b, h = idx << (32 - shift); for (int j = 0; j < 2; j++) { - for (int i = 0; i < size; i++) { + for (int i = 0; i < 43; i++) { b = 4 * TB(i); if (shift >= b && ((h & (0xFFF00000u << (12 - b))) >> 20) == table[2 * i + 1]) { if (table[2 * i] >> 8 == 0x80u) { @@ -322,7 +322,7 @@ static void fill_lut(uint32_t *lut) uint32_t f = 0xFFFFFFFFu; c &= 0xFFFFFFu; if ((c & 0xFF00u) != 0x8000u) - fill_elements(j, d, 365, &c, &f); + fill_elements(j, d, &c, &f); lut[2 * a + 2 * j] = c; lut[2 * a + 2 * j + 1] = f; } @@ -344,11 +344,11 @@ static av_cold int decode_init(AVCodecContext *avctx) avctx->pix_fmt = AV_PIX_FMT_YUV411P; - s->table_b = av_malloc(s->stride); + s->initial_line = av_malloc(s->stride); s->decbuffer = av_malloc(s->size); - if (!s->table_b || !s->decbuffer) + if (!s->initial_line || !s->decbuffer) return AVERROR(ENOMEM); - memset(s->table_b, 0x80u, s->stride); + memset(s->initial_line, 0x80u, s->stride); fill_lut(s->lut); @@ -359,7 +359,7 @@ static av_cold int decode_close(AVCodecContext *avctx) { ProSumerContext *s = avctx->priv_data; - av_freep(&s->table_b); + av_freep(&s->initial_line); av_freep(&s->decbuffer); return 0;