diff options
Diffstat (limited to 'src/libffmpeg/libavcodec/lcl.c')
-rw-r--r-- | src/libffmpeg/libavcodec/lcl.c | 82 |
1 files changed, 56 insertions, 26 deletions
diff --git a/src/libffmpeg/libavcodec/lcl.c b/src/libffmpeg/libavcodec/lcl.c index 9a8591a89..a15a10769 100644 --- a/src/libffmpeg/libavcodec/lcl.c +++ b/src/libffmpeg/libavcodec/lcl.c @@ -41,6 +41,7 @@ #include <stdlib.h> #include "common.h" +#include "bitstream.h" #include "avcodec.h" #ifdef CONFIG_ZLIB @@ -144,14 +145,15 @@ static inline unsigned char get_r (unsigned char yq, signed char rq) -static int mszh_decomp(unsigned char * srcptr, int srclen, unsigned char * destptr) +static unsigned int mszh_decomp(unsigned char * srcptr, int srclen, unsigned char * destptr, unsigned int destsize) { unsigned char *destptr_bak = destptr; + unsigned char *destptr_end = destptr + destsize; unsigned char mask = 0; unsigned char maskbit = 0; unsigned int ofs, cnt; - while (srclen > 0) { + while ((srclen > 0) && (destptr < destptr_end)) { if (maskbit == 0) { mask = *(srcptr++); maskbit = 8; @@ -159,6 +161,8 @@ static int mszh_decomp(unsigned char * srcptr, int srclen, unsigned char * destp continue; } if ((mask & (1 << (--maskbit))) == 0) { + if (destptr + 4 > destptr_end) + break; *(int*)destptr = *(int*)srcptr; srclen -= 4; destptr += 4; @@ -171,6 +175,9 @@ static int mszh_decomp(unsigned char * srcptr, int srclen, unsigned char * destp ofs &= 0x7ff; srclen -= 2; cnt *= 4; + if (destptr + cnt > destptr_end) { + cnt = destptr_end - destptr; + } for (; cnt > 0; cnt--) { *(destptr) = *(destptr - ofs); destptr++; @@ -193,7 +200,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8 { LclContext * const c = (LclContext *)avctx->priv_data; unsigned char *encoded = (unsigned char *)buf; - int pixel_ptr; + unsigned int pixel_ptr; int row, col; unsigned char *outptr; unsigned int width = avctx->width; // Real image width @@ -205,11 +212,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8 #ifdef CONFIG_ZLIB int zret; // Zlib return code #endif - int len = buf_size; - - /* no supplementary picture */ - if (buf_size == 0) - return 0; + unsigned int len = buf_size; if(c->pic.data[0]) avctx->release_buffer(avctx, &c->pic); @@ -231,24 +234,29 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8 if (c->flags & FLAG_MULTITHREAD) { mthread_inlen = *((unsigned int*)encoded); mthread_outlen = *((unsigned int*)(encoded+4)); - mszh_dlen = mszh_decomp(encoded + 8, mthread_inlen, c->decomp_buf); + if (mthread_outlen > c->decomp_size) // this should not happen + mthread_outlen = c->decomp_size; + mszh_dlen = mszh_decomp(encoded + 8, mthread_inlen, c->decomp_buf, c->decomp_size); if (mthread_outlen != mszh_dlen) { av_log(avctx, AV_LOG_ERROR, "Mthread1 decoded size differs (%d != %d)\n", mthread_outlen, mszh_dlen); + return -1; } mszh_dlen = mszh_decomp(encoded + 8 + mthread_inlen, len - mthread_inlen, - c->decomp_buf + mthread_outlen); - if ((c->decomp_size - mthread_outlen) != mszh_dlen) { + c->decomp_buf + mthread_outlen, c->decomp_size - mthread_outlen); + if (mthread_outlen != mszh_dlen) { av_log(avctx, AV_LOG_ERROR, "Mthread2 decoded size differs (%d != %d)\n", - c->decomp_size - mthread_outlen, mszh_dlen); + mthread_outlen, mszh_dlen); + return -1; } encoded = c->decomp_buf; len = c->decomp_size; } else { - mszh_dlen = mszh_decomp(encoded, len, c->decomp_buf); + mszh_dlen = mszh_decomp(encoded, len, c->decomp_buf, c->decomp_size); if (c->decomp_size != mszh_dlen) { av_log(avctx, AV_LOG_ERROR, "Decoded size differs (%d != %d)\n", c->decomp_size, mszh_dlen); + return -1; } encoded = c->decomp_buf; len = mszh_dlen; @@ -277,10 +285,12 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8 if (c->flags & FLAG_MULTITHREAD) { mthread_inlen = *((unsigned int*)encoded); mthread_outlen = *((unsigned int*)(encoded+4)); + if (mthread_outlen > c->decomp_size) + mthread_outlen = c->decomp_size; c->zstream.next_in = encoded + 8; c->zstream.avail_in = mthread_inlen; c->zstream.next_out = c->decomp_buf; - c->zstream.avail_out = mthread_outlen; + c->zstream.avail_out = c->decomp_size; zret = inflate(&(c->zstream), Z_FINISH); if ((zret != Z_OK) && (zret != Z_STREAM_END)) { av_log(avctx, AV_LOG_ERROR, "Mthread1 inflate error: %d\n", zret); @@ -289,6 +299,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8 if (mthread_outlen != (unsigned int)(c->zstream.total_out)) { av_log(avctx, AV_LOG_ERROR, "Mthread1 decoded size differs (%u != %lu)\n", mthread_outlen, c->zstream.total_out); + return -1; } zret = inflateReset(&(c->zstream)); if (zret != Z_OK) { @@ -298,15 +309,16 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8 c->zstream.next_in = encoded + 8 + mthread_inlen; c->zstream.avail_in = len - mthread_inlen; c->zstream.next_out = c->decomp_buf + mthread_outlen; - c->zstream.avail_out = mthread_outlen; + c->zstream.avail_out = c->decomp_size - mthread_outlen; zret = inflate(&(c->zstream), Z_FINISH); if ((zret != Z_OK) && (zret != Z_STREAM_END)) { av_log(avctx, AV_LOG_ERROR, "Mthread2 inflate error: %d\n", zret); return -1; } - if ((c->decomp_size - mthread_outlen) != (unsigned int)(c->zstream.total_out)) { + if (mthread_outlen != (unsigned int)(c->zstream.total_out)) { av_log(avctx, AV_LOG_ERROR, "Mthread2 decoded size differs (%d != %lu)\n", - c->decomp_size - mthread_outlen, c->zstream.total_out); + mthread_outlen, c->zstream.total_out); + return -1; } } else { c->zstream.next_in = encoded; @@ -321,6 +333,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8 if (c->decomp_size != (unsigned int)(c->zstream.total_out)) { av_log(avctx, AV_LOG_ERROR, "Decoded size differs (%d != %lu)\n", c->decomp_size, c->zstream.total_out); + return -1; } } encoded = c->decomp_buf; @@ -567,13 +580,20 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, av_log(avctx, AV_LOG_ERROR, "Deflate reset error: %d\n", zret); return -1; } - c->zstream.next_in = p->data[0]; - c->zstream.avail_in = c->decomp_size; c->zstream.next_out = c->comp_buf; c->zstream.avail_out = c->max_comp_size; + for(i = avctx->height - 1; i >= 0; i--) { + c->zstream.next_in = p->data[0]+p->linesize[0]*i; + c->zstream.avail_in = avctx->width*3; + zret = deflate(&(c->zstream), Z_NO_FLUSH); + if (zret != Z_OK) { + av_log(avctx, AV_LOG_ERROR, "Deflate error: %d\n", zret); + return -1; + } + } zret = deflate(&(c->zstream), Z_FINISH); - if ((zret != Z_OK) && (zret != Z_STREAM_END)) { + if (zret != Z_STREAM_END) { av_log(avctx, AV_LOG_ERROR, "Deflate error: %d\n", zret); return -1; } @@ -596,7 +616,9 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, static int decode_init(AVCodecContext *avctx) { LclContext * const c = (LclContext *)avctx->priv_data; - int basesize = avctx->width * avctx->height; + unsigned int basesize = avctx->width * avctx->height; + unsigned int max_basesize = ((avctx->width + 3) & ~3) * ((avctx->height + 3) & ~3); + unsigned int max_decomp_size; int zret; // Zlib return code c->avctx = avctx; @@ -614,6 +636,10 @@ static int decode_init(AVCodecContext *avctx) return 1; } + if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) { + return 1; + } + /* Check codec type */ if (((avctx->codec_id == CODEC_ID_MSZH) && (*((char *)avctx->extradata + 7) != CODEC_MSZH)) || ((avctx->codec_id == CODEC_ID_ZLIB) && (*((char *)avctx->extradata + 7) != CODEC_ZLIB))) { @@ -624,26 +650,32 @@ static int decode_init(AVCodecContext *avctx) switch (c->imgtype = *((char *)avctx->extradata + 4)) { case IMGTYPE_YUV111: c->decomp_size = basesize * 3; + max_decomp_size = max_basesize * 3; av_log(avctx, AV_LOG_INFO, "Image type is YUV 1:1:1.\n"); break; case IMGTYPE_YUV422: c->decomp_size = basesize * 2; + max_decomp_size = max_basesize * 2; av_log(avctx, AV_LOG_INFO, "Image type is YUV 4:2:2.\n"); break; case IMGTYPE_RGB24: c->decomp_size = basesize * 3; + max_decomp_size = max_basesize * 3; av_log(avctx, AV_LOG_INFO, "Image type is RGB 24.\n"); break; case IMGTYPE_YUV411: c->decomp_size = basesize / 2 * 3; + max_decomp_size = max_basesize / 2 * 3; av_log(avctx, AV_LOG_INFO, "Image type is YUV 4:1:1.\n"); break; case IMGTYPE_YUV211: c->decomp_size = basesize * 2; + max_decomp_size = max_basesize * 2; av_log(avctx, AV_LOG_INFO, "Image type is YUV 2:1:1.\n"); break; case IMGTYPE_YUV420: c->decomp_size = basesize / 2 * 3; + max_decomp_size = max_basesize / 2 * 3; av_log(avctx, AV_LOG_INFO, "Image type is YUV 4:2:0.\n"); break; default: @@ -698,9 +730,8 @@ static int decode_init(AVCodecContext *avctx) } /* Allocate decompression buffer */ - /* 4*8 max overflow space for mszh decomp algorithm */ if (c->decomp_size) { - if ((c->decomp_buf = av_malloc(c->decomp_size+4*8)) == NULL) { + if ((c->decomp_buf = av_malloc(max_decomp_size)) == NULL) { av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n"); return 1; } @@ -785,7 +816,7 @@ static int encode_init(AVCodecContext *avctx) ((uint8_t*)avctx->extradata)[4]= c->imgtype; ((uint8_t*)avctx->extradata)[5]= c->compression; ((uint8_t*)avctx->extradata)[6]= c->flags; - ((uint8_t*)avctx->extradata)[7]= 0; + ((uint8_t*)avctx->extradata)[7]= CODEC_ZLIB; c->avctx->extradata_size= 8; c->zstream.zalloc = Z_NULL; @@ -843,7 +874,7 @@ static int encode_end(AVCodecContext *avctx) LclContext *c = avctx->priv_data; av_freep(&avctx->extradata); - av_freep(c->comp_buf); + av_freep(&c->comp_buf); #ifdef CONFIG_ZLIB deflateEnd(&(c->zstream)); #endif @@ -886,7 +917,6 @@ AVCodec zlib_encoder = { encode_init, encode_frame, encode_end, -// .options = lcl_options, }; #endif //CONFIG_ENCODERS |