X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fhuffyuvdec.c;h=e713b91e4dd0585e56e51e598df7106edaf8921d;hb=46dac8cf3d250184ab4247809bc03f60e14f4c0c;hp=66357bfb40353f6f762c4c6ce2a1c19a859b84ec;hpb=768b07e3bca7e81d2f9c60badb3973d3d88481dc;p=ffmpeg diff --git a/libavcodec/huffyuvdec.c b/libavcodec/huffyuvdec.c index 66357bfb403..e713b91e4dd 100644 --- a/libavcodec/huffyuvdec.c +++ b/libavcodec/huffyuvdec.c @@ -418,9 +418,6 @@ static av_cold int decode_init(AVCodecContext *avctx) case 0x0F0: avctx->pix_fmt = AV_PIX_FMT_GRAY16; break; - case 0x170: - avctx->pix_fmt = AV_PIX_FMT_GRAY8A; - break; case 0x470: avctx->pix_fmt = AV_PIX_FMT_GBRP; break; @@ -573,35 +570,6 @@ static av_cold int decode_init(AVCodecContext *avctx) return ret; } -#if HAVE_THREADS -static av_cold int decode_init_thread_copy(AVCodecContext *avctx) -{ - HYuvContext *s = avctx->priv_data; - int i, ret; - - s->avctx = avctx; - - if ((ret = ff_huffyuv_alloc_temp(s)) < 0) { - ff_huffyuv_common_end(s); - return ret; - } - - for (i = 0; i < 8; i++) - s->vlc[i].table = NULL; - - if (s->version >= 2) { - if ((ret = read_huffman_tables(s, avctx->extradata + 4, - avctx->extradata_size)) < 0) - return ret; - } else { - if ((ret = read_old_huffman_tables(s)) < 0) - return ret; - } - - return 0; -} -#endif - /** Subset of GET_VLC for use in hand-roller VLC code */ #define VLC_INTERN(dst, table, gb, name, bits, max_depth) \ code = table[index][0]; \ @@ -905,54 +873,23 @@ static void add_median_prediction(HYuvContext *s, uint8_t *dst, const uint8_t *s s->hdsp.add_hfyu_median_pred_int16((uint16_t *)dst, (const uint16_t *)src, (const uint16_t *)diff, s->n-1, w, left, left_top); } } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) + +static int decode_slice(AVCodecContext *avctx, AVFrame *p, int height, + int buf_size, int y_offset, int table_size) { - const uint8_t *buf = avpkt->data; - int buf_size = avpkt->size; HYuvContext *s = avctx->priv_data; + int fake_ystride, fake_ustride, fake_vstride; const int width = s->width; const int width2 = s->width >> 1; - const int height = s->height; - int fake_ystride, fake_ustride, fake_vstride; - ThreadFrame frame = { .f = data }; - AVFrame *const p = data; - int table_size = 0, ret; - - if (buf_size < (width * height + 7)/8) - return AVERROR_INVALIDDATA; - - av_fast_padded_malloc(&s->bitstream_buffer, - &s->bitstream_buffer_size, - buf_size); - if (!s->bitstream_buffer) - return AVERROR(ENOMEM); - - s->bdsp.bswap_buf((uint32_t *) s->bitstream_buffer, - (const uint32_t *) buf, buf_size / 4); - - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) - return ret; - - if (s->context) { - table_size = read_huffman_tables(s, s->bitstream_buffer, buf_size); - if (table_size < 0) - return table_size; - } - - if ((unsigned) (buf_size - table_size) >= INT_MAX / 8) - return AVERROR_INVALIDDATA; + int ret; - if ((ret = init_get_bits(&s->gb, s->bitstream_buffer + table_size, - (buf_size - table_size) * 8)) < 0) + if ((ret = init_get_bits8(&s->gb, s->bitstream_buffer + table_size, buf_size - table_size)) < 0) return ret; fake_ystride = s->interlaced ? p->linesize[0] * 2 : p->linesize[0]; fake_ustride = s->interlaced ? p->linesize[1] * 2 : p->linesize[1]; fake_vstride = s->interlaced ? p->linesize[2] * 2 : p->linesize[2]; - s->last_slice_end = 0; - if (s->version > 2) { int plane; for(plane = 0; plane < 1 + 2*s->chroma + s->alpha; plane++) { @@ -991,12 +928,16 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, left= left_prediction(s, p->data[plane], s->temp[0], w, 0); y = 1; + if (y >= h) + break; /* second line is left predicted for interlaced case */ if (s->interlaced) { decode_plane_bitstream(s, w, plane); left = left_prediction(s, p->data[plane] + p->linesize[plane], s->temp[0], w, left); y++; + if (y >= h) + break; } lefttop = p->data[plane][0]; @@ -1034,31 +975,31 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return AVERROR_PATCHWELCOME; } else { leftv = - p->data[2][0] = get_bits(&s->gb, 8); + p->data[2][0 + y_offset * p->linesize[2]] = get_bits(&s->gb, 8); lefty = - p->data[0][1] = get_bits(&s->gb, 8); + p->data[0][1 + y_offset * p->linesize[0]] = get_bits(&s->gb, 8); leftu = - p->data[1][0] = get_bits(&s->gb, 8); - p->data[0][0] = get_bits(&s->gb, 8); + p->data[1][0 + y_offset * p->linesize[1]] = get_bits(&s->gb, 8); + p->data[0][0 + y_offset * p->linesize[0]] = get_bits(&s->gb, 8); switch (s->predictor) { case LEFT: case PLANE: decode_422_bitstream(s, width - 2); - lefty = s->llviddsp.add_left_pred(p->data[0] + 2, s->temp[0], + lefty = s->llviddsp.add_left_pred(p->data[0] + p->linesize[0] * y_offset + 2, s->temp[0], width - 2, lefty); if (!(s->flags & AV_CODEC_FLAG_GRAY)) { - leftu = s->llviddsp.add_left_pred(p->data[1] + 1, s->temp[1], width2 - 1, leftu); - leftv = s->llviddsp.add_left_pred(p->data[2] + 1, s->temp[2], width2 - 1, leftv); + leftu = s->llviddsp.add_left_pred(p->data[1] + p->linesize[1] * y_offset + 1, s->temp[1], width2 - 1, leftu); + leftv = s->llviddsp.add_left_pred(p->data[2] + p->linesize[2] * y_offset + 1, s->temp[2], width2 - 1, leftv); } - for (cy = y = 1; y < s->height; y++, cy++) { + for (cy = y = 1; y < height; y++, cy++) { uint8_t *ydst, *udst, *vdst; if (s->bitstream_bpp == 12) { decode_gray_bitstream(s, width); - ydst = p->data[0] + p->linesize[0] * y; + ydst = p->data[0] + p->linesize[0] * (y + y_offset); lefty = s->llviddsp.add_left_pred(ydst, s->temp[0], width, lefty); @@ -1067,15 +1008,15 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, s->llviddsp.add_bytes(ydst, ydst - fake_ystride, width); } y++; - if (y >= s->height) + if (y >= height) break; } draw_slice(s, p, y); - ydst = p->data[0] + p->linesize[0] * y; - udst = p->data[1] + p->linesize[1] * cy; - vdst = p->data[2] + p->linesize[2] * cy; + ydst = p->data[0] + p->linesize[0] * (y + y_offset); + udst = p->data[1] + p->linesize[1] * (cy + y_offset); + vdst = p->data[2] + p->linesize[2] * (cy + y_offset); decode_422_bitstream(s, width); lefty = s->llviddsp.add_left_pred(ydst, s->temp[0], @@ -1108,6 +1049,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } cy = y = 1; + if (y >= height) + break; /* second line is left predicted for interlaced case */ if (s->interlaced) { @@ -1120,6 +1063,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } y++; cy++; + if (y >= height) + break; } /* next 4 pixels are left predicted too */ @@ -1185,7 +1130,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } else { int y; uint8_t left[4]; - const int last_line = (height - 1) * p->linesize[0]; + const int last_line = (y_offset + height - 1) * p->linesize[0]; if (s->bitstream_bpp == 32) { left[A] = p->data[0][last_line + A] = get_bits(&s->gb, 8); @@ -1208,17 +1153,17 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, s->hdsp.add_hfyu_left_pred_bgr32(p->data[0] + last_line + 4, s->temp[0], width - 1, left); - for (y = s->height - 2; y >= 0; y--) { // Yes it is stored upside down. + for (y = height - 2; y >= 0; y--) { // Yes it is stored upside down. decode_bgr_bitstream(s, width); - s->hdsp.add_hfyu_left_pred_bgr32(p->data[0] + p->linesize[0] * y, + s->hdsp.add_hfyu_left_pred_bgr32(p->data[0] + p->linesize[0] * (y + y_offset), s->temp[0], width, left); if (s->predictor == PLANE) { if (s->bitstream_bpp != 32) left[A] = 0; - if (y < s->height - 1 - s->interlaced) { - s->llviddsp.add_bytes(p->data[0] + p->linesize[0] * y, - p->data[0] + p->linesize[0] * y + + if (y < height - 1 - s->interlaced) { + s->llviddsp.add_bytes(p->data[0] + p->linesize[0] * (y + y_offset), + p->data[0] + p->linesize[0] * (y + y_offset) + fake_ystride, 4 * width); } } @@ -1236,7 +1181,89 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return AVERROR_PATCHWELCOME; } } - emms_c(); + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + HYuvContext *s = avctx->priv_data; + const int width = s->width; + const int height = s->height; + ThreadFrame frame = { .f = data }; + AVFrame *const p = data; + int slice, table_size = 0, ret, nb_slices; + unsigned slices_info_offset; + int slice_height; + + if (buf_size < (width * height + 7)/8) + return AVERROR_INVALIDDATA; + + av_fast_padded_malloc(&s->bitstream_buffer, + &s->bitstream_buffer_size, + buf_size); + if (!s->bitstream_buffer) + return AVERROR(ENOMEM); + + s->bdsp.bswap_buf((uint32_t *) s->bitstream_buffer, + (const uint32_t *) buf, buf_size / 4); + + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + return ret; + + if (s->context) { + table_size = read_huffman_tables(s, s->bitstream_buffer, buf_size); + if (table_size < 0) + return table_size; + } + + if ((unsigned) (buf_size - table_size) >= INT_MAX / 8) + return AVERROR_INVALIDDATA; + + s->last_slice_end = 0; + + if (avctx->codec_id == AV_CODEC_ID_HYMT && + (buf_size > 32 && AV_RL32(avpkt->data + buf_size - 16) == 0)) { + slices_info_offset = AV_RL32(avpkt->data + buf_size - 4); + slice_height = AV_RL32(avpkt->data + buf_size - 8); + nb_slices = AV_RL32(avpkt->data + buf_size - 12); + if (nb_slices * 8LL + slices_info_offset > buf_size - 16 || + s->chroma_v_shift || + slice_height <= 0 || nb_slices * (uint64_t)slice_height > height) + return AVERROR_INVALIDDATA; + } else { + slice_height = height; + nb_slices = 1; + } + + for (slice = 0; slice < nb_slices; slice++) { + int y_offset, slice_offset, slice_size; + + if (nb_slices > 1) { + slice_offset = AV_RL32(avpkt->data + slices_info_offset + slice * 8); + slice_size = AV_RL32(avpkt->data + slices_info_offset + slice * 8 + 4); + + if (slice_offset < 0 || slice_size <= 0 || (slice_offset&3) || + slice_offset + (int64_t)slice_size > buf_size) + return AVERROR_INVALIDDATA; + + y_offset = height - (slice + 1) * slice_height; + s->bdsp.bswap_buf((uint32_t *)s->bitstream_buffer, + (const uint32_t *)(buf + slice_offset), slice_size / 4); + } else { + y_offset = 0; + slice_offset = 0; + slice_size = buf_size; + } + + ret = decode_slice(avctx, p, slice_height, slice_size, y_offset, table_size); + emms_c(); + if (ret < 0) + return ret; + } *got_frame = 1; @@ -1254,7 +1281,6 @@ AVCodec ff_huffyuv_decoder = { .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_FRAME_THREADS, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy), }; #if CONFIG_FFVHUFF_DECODER @@ -1269,6 +1295,20 @@ AVCodec ff_ffvhuff_decoder = { .decode = decode_frame, .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_FRAME_THREADS, - .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy), }; #endif /* CONFIG_FFVHUFF_DECODER */ + +#if CONFIG_HYMT_DECODER +AVCodec ff_hymt_decoder = { + .name = "hymt", + .long_name = NULL_IF_CONFIG_SMALL("HuffYUV MT"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_HYMT, + .priv_data_size = sizeof(HYuvContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND | + AV_CODEC_CAP_FRAME_THREADS, +}; +#endif /* CONFIG_HYMT_DECODER */