static int targa_decode_rle(AVCodecContext *avctx, TargaContext *s, const uint8_t *src, int src_size, uint8_t *dst, int w, int h, int stride, int bpp) { int i, x, y; int depth = (bpp + 1) >> 3; int type, count; int diff; const uint8_t *src_end = src + src_size; diff = stride - w * depth; x = y = 0; while(y < h){ CHECK_BUFFER_SIZE(src, src_end, 1, "image type"); type = *src++; count = (type & 0x7F) + 1; type &= 0x80; if((x + count > w) && (x + count + 1 > (h - y) * w)){ av_log(avctx, AV_LOG_ERROR, "Packet went out of bounds: position (%i,%i) size %i\n", x, y, count); return -1; } if(type){ CHECK_BUFFER_SIZE(src, src_end, depth, "image data"); }else{ CHECK_BUFFER_SIZE(src, src_end, count * depth, "image data"); } for(i = 0; i < count; i++){ switch(depth){ case 1: *dst = *src; break; case 2: AV_WN16A(dst, AV_RN16A(src)); break; case 3: dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; break; case 4: AV_WN32A(dst, AV_RN32A(src)); break; } dst += depth; if(!type) src += depth; x++; if(x == w){ x = 0; y++; dst += diff; } } if(type) src += depth; } return src_size; }