X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;ds=sidebyside;f=libavcodec%2Flcldec.c;h=d2482138abedb8b6937defb5590faae06633385a;hb=36ef5369ee9b336febc2c270f8718cec4476cb85;hp=5225ff0552572bc3dcc263e07a8e9f819a8dd039;hpb=e4f141ad60afbd721e494975677fbfd8e0ebcb22;p=ffmpeg diff --git a/libavcodec/lcldec.c b/libavcodec/lcldec.c index 5225ff05525..d2482138abe 100644 --- a/libavcodec/lcldec.c +++ b/libavcodec/lcldec.c @@ -2,25 +2,25 @@ * LCL (LossLess Codec Library) Codec * Copyright (c) 2002-2004 Roberto Togni * - * This file is part of FFmpeg. + * This file is part of Libav. * - * FFmpeg is free software; you can redistribute it and/or + * Libav is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * FFmpeg is distributed in the hope that it will be useful, + * Libav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software + * License along with Libav; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** - * @file libavcodec/lcldec.c + * @file * LCL (LossLess Codec Library) Video Codec * Decoder for MSZH and ZLIB codecs * Experimental encoder for ZLIB RGB24 @@ -73,51 +73,57 @@ typedef struct LclDecContext { /** - * \param srcptr compressed source buffer, must be padded with at least 4 extra bytes - * \param destptr must be padded sufficiently for av_memcpy_backptr + * @param srcptr compressed source buffer, must be padded with at least 5 extra bytes + * @param destptr must be padded sufficiently for av_memcpy_backptr */ static unsigned int mszh_decomp(const unsigned char * srcptr, int srclen, unsigned char * destptr, unsigned int destsize) { unsigned char *destptr_bak = destptr; unsigned char *destptr_end = destptr + destsize; const unsigned char *srcptr_end = srcptr + srclen; - unsigned char mask = 0; - unsigned char maskbit = 0; - unsigned int ofs, cnt; + unsigned mask = *srcptr++; + unsigned maskbit = 0x80; while (srcptr < srcptr_end && destptr < destptr_end) { - if (maskbit == 0) { - mask = *srcptr++; - maskbit = 8; - continue; - } - if ((mask & (1 << (--maskbit))) == 0) { - if (destptr_end - destptr < 4) - break; + if (!(mask & maskbit)) { memcpy(destptr, srcptr, 4); destptr += 4; srcptr += 4; } else { - ofs = bytestream_get_le16(&srcptr); - cnt = (ofs >> 11) + 1; + unsigned ofs = bytestream_get_le16(&srcptr); + unsigned cnt = (ofs >> 11) + 1; ofs &= 0x7ff; + ofs = FFMIN(ofs, destptr - destptr_bak); cnt *= 4; cnt = FFMIN(cnt, destptr_end - destptr); av_memcpy_backptr(destptr, ofs, cnt); destptr += cnt; } + maskbit >>= 1; + if (!maskbit) { + mask = *srcptr++; + while (!mask) { + if (destptr_end - destptr < 32 || srcptr_end - srcptr < 32) break; + memcpy(destptr, srcptr, 32); + destptr += 32; + srcptr += 32; + mask = *srcptr++; + } + maskbit = 0x80; + } } return destptr - destptr_bak; } +#if CONFIG_ZLIB_DECODER /** - * \brief decompress a zlib-compressed data block into decomp_buf - * \param src compressed input buffer - * \param src_len data length in input buffer - * \param offset offset in decomp_buf - * \param expected expected decompressed length + * @brief decompress a zlib-compressed data block into decomp_buf + * @param src compressed input buffer + * @param src_len data length in input buffer + * @param offset offset in decomp_buf + * @param expected expected decompressed length */ static int zlib_decomp(AVCodecContext *avctx, const uint8_t *src, int src_len, int offset, int expected) { @@ -143,6 +149,7 @@ static int zlib_decomp(AVCodecContext *avctx, const uint8_t *src, int src_len, i } return c->zstream.total_out; } +#endif /* @@ -182,7 +189,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPac /* Decompress frame */ switch (avctx->codec_id) { - case CODEC_ID_MSZH: + case AV_CODEC_ID_MSZH: switch (c->compression) { case COMP_MSZH: if (c->flags & FLAG_MULTITHREAD) { @@ -216,22 +223,48 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPac len = mszh_dlen; } break; - case COMP_MSZH_NOCOMP: + case COMP_MSZH_NOCOMP: { + int bppx2; + switch (c->imgtype) { + case IMGTYPE_YUV111: + case IMGTYPE_RGB24: + bppx2 = 6; + break; + case IMGTYPE_YUV422: + case IMGTYPE_YUV211: + bppx2 = 4; + break; + case IMGTYPE_YUV411: + case IMGTYPE_YUV420: + bppx2 = 3; + break; + default: + bppx2 = 0; // will error out below + break; + } + if (len < ((width * height * bppx2) >> 1)) + return AVERROR_INVALIDDATA; break; + } default: av_log(avctx, AV_LOG_ERROR, "BUG! Unknown MSZH compression in frame decoder.\n"); return -1; } break; #if CONFIG_ZLIB_DECODER - case CODEC_ID_ZLIB: + case AV_CODEC_ID_ZLIB: /* Using the original dll with normal compression (-1) and RGB format * gives a file with ZLIB fourcc, but frame is really uncompressed. * To be sure that's true check also frame size */ if (c->compression == COMP_ZLIB_NORMAL && c->imgtype == IMGTYPE_RGB24 && - len == width * height * 3) - break; - if (c->flags & FLAG_MULTITHREAD) { + len == width * height * 3) { + if (c->flags & FLAG_PNGFILTER) { + memcpy(c->decomp_buf, encoded, len); + encoded = c->decomp_buf; + } else { + break; + } + } else if (c->flags & FLAG_MULTITHREAD) { int ret; mthread_inlen = AV_RL32(encoded); mthread_inlen = FFMIN(mthread_inlen, len - 8); @@ -257,7 +290,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPac /* Apply PNG filter */ - if (avctx->codec_id == CODEC_ID_ZLIB && (c->flags & FLAG_PNGFILTER)) { + if (avctx->codec_id == AV_CODEC_ID_ZLIB && (c->flags & FLAG_PNGFILTER)) { switch (c->imgtype) { case IMGTYPE_YUV111: case IMGTYPE_RGB24: @@ -446,25 +479,14 @@ static av_cold int decode_init(AVCodecContext *avctx) unsigned int max_basesize = FFALIGN(avctx->width, 4) * FFALIGN(avctx->height, 4) + AV_LZO_OUTPUT_PADDING; unsigned int max_decomp_size; - c->pic.data[0] = NULL; - -#if CONFIG_ZLIB_DECODER - // Needed if zlib unused or init aborted before inflateInit - memset(&c->zstream, 0, sizeof(z_stream)); -#endif - if (avctx->extradata_size < 8) { av_log(avctx, AV_LOG_ERROR, "Extradata size too small.\n"); - return 1; - } - - if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) { - return 1; + return AVERROR_INVALIDDATA; } /* Check codec type */ - if ((avctx->codec_id == CODEC_ID_MSZH && avctx->extradata[7] != CODEC_MSZH) || - (avctx->codec_id == CODEC_ID_ZLIB && avctx->extradata[7] != CODEC_ZLIB)) { + if ((avctx->codec_id == AV_CODEC_ID_MSZH && avctx->extradata[7] != CODEC_MSZH) || + (avctx->codec_id == AV_CODEC_ID_ZLIB && avctx->extradata[7] != CODEC_ZLIB)) { av_log(avctx, AV_LOG_ERROR, "Codec id and codec type mismatch. This should not happen.\n"); } @@ -508,13 +530,13 @@ static av_cold int decode_init(AVCodecContext *avctx) break; default: av_log(avctx, AV_LOG_ERROR, "Unsupported image format %d.\n", c->imgtype); - return 1; + return AVERROR_INVALIDDATA; } /* Detect compression method */ - c->compression = avctx->extradata[5]; + c->compression = (int8_t)avctx->extradata[5]; switch (avctx->codec_id) { - case CODEC_ID_MSZH: + case AV_CODEC_ID_MSZH: switch (c->compression) { case COMP_MSZH: av_log(avctx, AV_LOG_DEBUG, "Compression enabled.\n"); @@ -525,11 +547,11 @@ static av_cold int decode_init(AVCodecContext *avctx) break; default: av_log(avctx, AV_LOG_ERROR, "Unsupported compression format for MSZH (%d).\n", c->compression); - return 1; + return AVERROR_INVALIDDATA; } break; #if CONFIG_ZLIB_DECODER - case CODEC_ID_ZLIB: + case AV_CODEC_ID_ZLIB: switch (c->compression) { case COMP_ZLIB_HISPEED: av_log(avctx, AV_LOG_DEBUG, "High speed compression.\n"); @@ -543,7 +565,7 @@ static av_cold int decode_init(AVCodecContext *avctx) default: if (c->compression < Z_NO_COMPRESSION || c->compression > Z_BEST_COMPRESSION) { av_log(avctx, AV_LOG_ERROR, "Unsupported compression level for ZLIB: (%d).\n", c->compression); - return 1; + return AVERROR_INVALIDDATA; } av_log(avctx, AV_LOG_DEBUG, "Compression level for ZLIB: (%d).\n", c->compression); } @@ -551,14 +573,14 @@ static av_cold int decode_init(AVCodecContext *avctx) #endif default: av_log(avctx, AV_LOG_ERROR, "BUG! Unknown codec in compression switch.\n"); - return 1; + return AVERROR_INVALIDDATA; } /* Allocate decompression buffer */ if (c->decomp_size) { if ((c->decomp_buf = av_malloc(max_decomp_size)) == NULL) { av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n"); - return 1; + return AVERROR(ENOMEM); } } @@ -568,14 +590,14 @@ static av_cold int decode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_DEBUG, "Multithread encoder flag set.\n"); if (c->flags & FLAG_NULLFRAME) av_log(avctx, AV_LOG_DEBUG, "Nullframe insertion flag set.\n"); - if (avctx->codec_id == CODEC_ID_ZLIB && (c->flags & FLAG_PNGFILTER)) + if (avctx->codec_id == AV_CODEC_ID_ZLIB && (c->flags & FLAG_PNGFILTER)) av_log(avctx, AV_LOG_DEBUG, "PNG filter flag set.\n"); if (c->flags & FLAGMASK_UNUSED) av_log(avctx, AV_LOG_ERROR, "Unknown flag set (%d).\n", c->flags); /* If needed init zlib */ #if CONFIG_ZLIB_DECODER - if (avctx->codec_id == CODEC_ID_ZLIB) { + if (avctx->codec_id == AV_CODEC_ID_ZLIB) { int zret; c->zstream.zalloc = Z_NULL; c->zstream.zfree = Z_NULL; @@ -583,7 +605,8 @@ static av_cold int decode_init(AVCodecContext *avctx) zret = inflateInit(&c->zstream); if (zret != Z_OK) { av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret); - return 1; + av_freep(&c->decomp_buf); + return AVERROR_UNKNOWN; } } #endif @@ -600,41 +623,41 @@ static av_cold int decode_end(AVCodecContext *avctx) { LclDecContext * const c = avctx->priv_data; + av_freep(&c->decomp_buf); if (c->pic.data[0]) avctx->release_buffer(avctx, &c->pic); #if CONFIG_ZLIB_DECODER - inflateEnd(&c->zstream); + if (avctx->codec_id == AV_CODEC_ID_ZLIB) + inflateEnd(&c->zstream); #endif return 0; } #if CONFIG_MSZH_DECODER -AVCodec mszh_decoder = { - "mszh", - CODEC_TYPE_VIDEO, - CODEC_ID_MSZH, - sizeof(LclDecContext), - decode_init, - NULL, - decode_end, - decode_frame, - CODEC_CAP_DR1, - .long_name = NULL_IF_CONFIG_SMALL("LCL (LossLess Codec Library) MSZH"), +AVCodec ff_mszh_decoder = { + .name = "mszh", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_MSZH, + .priv_data_size = sizeof(LclDecContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("LCL (LossLess Codec Library) MSZH"), }; #endif #if CONFIG_ZLIB_DECODER -AVCodec zlib_decoder = { - "zlib", - CODEC_TYPE_VIDEO, - CODEC_ID_ZLIB, - sizeof(LclDecContext), - decode_init, - NULL, - decode_end, - decode_frame, - CODEC_CAP_DR1, - .long_name = NULL_IF_CONFIG_SMALL("LCL (LossLess Codec Library) ZLIB"), +AVCodec ff_zlib_decoder = { + .name = "zlib", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_ZLIB, + .priv_data_size = sizeof(LclDecContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("LCL (LossLess Codec Library) ZLIB"), }; #endif