static int msrle_decode_8_16_24_32(AVCodecContext *avctx, AVPicture *pic, int depth, const uint8_t *data, int srcsize) { uint8_t *output, *output_end; const uint8_t* src = data; int p1, p2, line=avctx->height, pos=0, i; uint16_t pix16; uint32_t pix32; output = pic->data[0] + (avctx->height - 1) * pic->linesize[0]; output_end = pic->data[0] + (avctx->height) * pic->linesize[0]; while(src < data + srcsize) { p1 = *src++; if(p1 == 0) { //Escape code p2 = *src++; if(p2 == 0) { //End-of-line output = pic->data[0] + (--line) * pic->linesize[0]; if (line < 0){ av_log(avctx, AV_LOG_ERROR, "Next line is beyond picture bounds\n"); return -1; } pos = 0; continue; } else if(p2 == 1) { //End-of-picture return 0; } else if(p2 == 2) { //Skip p1 = *src++; p2 = *src++; line -= p2; if (line < 0){ av_log(avctx, AV_LOG_ERROR, "Skip beyond picture bounds\n"); return -1; } pos += p1; output = pic->data[0] + line * pic->linesize[0] + pos * (depth >> 3); continue; } // Copy data if (output + p2 * (depth >> 3) > output_end) { src += p2 * (depth >> 3); continue; } if ((depth == 8) || (depth == 24)) { for(i = 0; i < p2 * (depth >> 3); i++) { *output++ = *src++; } // RLE8 copy is actually padded - and runs are not! if(depth == 8 && (p2 & 1)) { src++; } } else if (depth == 16) { for(i = 0; i < p2; i++) { pix16 = AV_RL16(src); src += 2; *(uint16_t*)output = pix16; output += 2; } } else if (depth == 32) { for(i = 0; i < p2; i++) { pix32 = AV_RL32(src); src += 4; *(uint32_t*)output = pix32; output += 4; } } pos += p2; } else { //Run of pixels uint8_t pix[3]; //original pixel switch(depth){ case 8: pix[0] = *src++; break; case 16: pix16 = AV_RL16(src); src += 2; break; case 24: pix[0] = *src++; pix[1] = *src++; pix[2] = *src++; break; case 32: pix32 = AV_RL32(src); src += 4; break; } if (output + p1 * (depth >> 3) > output_end) continue; for(i = 0; i < p1; i++) { switch(depth){ case 8: *output++ = pix[0]; break; case 16: *(uint16_t*)output = pix16; output += 2; break; case 24: *output++ = pix[0]; *output++ = pix[1]; *output++ = pix[2]; break; case 32: *(uint32_t*)output = pix32; output += 4; break; } } pos += p1; } } av_log(avctx, AV_LOG_WARNING, "MS RLE warning: no End-of-picture code\n"); return 0; }