00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00029 #include "libavutil/intreadwrite.h"
00030 #include "avcodec.h"
00031 #include "msrledec.h"
00032
00033 static int msrle_decode_pal4(AVCodecContext *avctx, AVPicture *pic,
00034 GetByteContext *gb)
00035 {
00036 unsigned char rle_code;
00037 unsigned char extra_byte, odd_pixel;
00038 unsigned char stream_byte;
00039 unsigned int pixel_ptr = 0;
00040 int row_dec = pic->linesize[0];
00041 int row_ptr = (avctx->height - 1) * row_dec;
00042 int frame_size = row_dec * avctx->height;
00043 int i;
00044
00045 while (row_ptr >= 0) {
00046 if (bytestream2_get_bytes_left(gb) <= 0) {
00047 av_log(avctx, AV_LOG_ERROR,
00048 "MS RLE: bytestream overrun, %d rows left\n",
00049 row_ptr);
00050 return AVERROR_INVALIDDATA;
00051 }
00052 rle_code = stream_byte = bytestream2_get_byteu(gb);
00053 if (rle_code == 0) {
00054
00055 stream_byte = bytestream2_get_byte(gb);
00056 if (stream_byte == 0) {
00057
00058 row_ptr -= row_dec;
00059 pixel_ptr = 0;
00060 } else if (stream_byte == 1) {
00061
00062 return 0;
00063 } else if (stream_byte == 2) {
00064
00065 stream_byte = bytestream2_get_byte(gb);
00066 pixel_ptr += stream_byte;
00067 stream_byte = bytestream2_get_byte(gb);
00068 row_ptr -= stream_byte * row_dec;
00069 } else {
00070
00071 odd_pixel = stream_byte & 1;
00072 rle_code = (stream_byte + 1) / 2;
00073 extra_byte = rle_code & 0x01;
00074 if (row_ptr + pixel_ptr + stream_byte > frame_size ||
00075 bytestream2_get_bytes_left(gb) < rle_code) {
00076 av_log(avctx, AV_LOG_ERROR,
00077 "MS RLE: frame/stream ptr just went out of bounds (copy)\n");
00078 return AVERROR_INVALIDDATA;
00079 }
00080
00081 for (i = 0; i < rle_code; i++) {
00082 if (pixel_ptr >= avctx->width)
00083 break;
00084 stream_byte = bytestream2_get_byteu(gb);
00085 pic->data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
00086 pixel_ptr++;
00087 if (i + 1 == rle_code && odd_pixel)
00088 break;
00089 if (pixel_ptr >= avctx->width)
00090 break;
00091 pic->data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
00092 pixel_ptr++;
00093 }
00094
00095
00096 if (extra_byte)
00097 bytestream2_skip(gb, 1);
00098 }
00099 } else {
00100
00101 if (row_ptr + pixel_ptr + stream_byte > frame_size) {
00102 av_log(avctx, AV_LOG_ERROR,
00103 "MS RLE: frame ptr just went out of bounds (run)\n");
00104 return AVERROR_INVALIDDATA;
00105 }
00106 stream_byte = bytestream2_get_byte(gb);
00107 for (i = 0; i < rle_code; i++) {
00108 if (pixel_ptr >= avctx->width)
00109 break;
00110 if ((i & 1) == 0)
00111 pic->data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
00112 else
00113 pic->data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
00114 pixel_ptr++;
00115 }
00116 }
00117 }
00118
00119
00120 if (bytestream2_get_bytes_left(gb)) {
00121 av_log(avctx, AV_LOG_ERROR,
00122 "MS RLE: ended frame decode with %d bytes left over\n",
00123 bytestream2_get_bytes_left(gb));
00124 return AVERROR_INVALIDDATA;
00125 }
00126
00127 return 0;
00128 }
00129
00130
00131 static int msrle_decode_8_16_24_32(AVCodecContext *avctx, AVPicture *pic,
00132 int depth, GetByteContext *gb)
00133 {
00134 uint8_t *output, *output_end;
00135 int p1, p2, line=avctx->height - 1, pos=0, i;
00136 uint16_t pix16;
00137 uint32_t pix32;
00138 unsigned int width= FFABS(pic->linesize[0]) / (depth >> 3);
00139
00140 output = pic->data[0] + (avctx->height - 1) * pic->linesize[0];
00141 output_end = pic->data[0] + avctx->height * pic->linesize[0];
00142 while (bytestream2_get_bytes_left(gb) > 0) {
00143 p1 = bytestream2_get_byteu(gb);
00144 if(p1 == 0) {
00145 p2 = bytestream2_get_byte(gb);
00146 if(p2 == 0) {
00147 output = pic->data[0] + (--line) * pic->linesize[0];
00148 if (line < 0) {
00149 if (bytestream2_get_be16(gb) == 1) {
00150 return 0;
00151 } else {
00152 av_log(avctx, AV_LOG_ERROR,
00153 "Next line is beyond picture bounds (%d bytes left)\n",
00154 bytestream2_get_bytes_left(gb));
00155 return AVERROR_INVALIDDATA;
00156 }
00157 }
00158 pos = 0;
00159 continue;
00160 } else if(p2 == 1) {
00161 return 0;
00162 } else if(p2 == 2) {
00163 p1 = bytestream2_get_byte(gb);
00164 p2 = bytestream2_get_byte(gb);
00165 line -= p2;
00166 pos += p1;
00167 if (line < 0 || pos >= width){
00168 av_log(avctx, AV_LOG_ERROR, "Skip beyond picture bounds\n");
00169 return -1;
00170 }
00171 output = pic->data[0] + line * pic->linesize[0] + pos * (depth >> 3);
00172 continue;
00173 }
00174
00175 if ((pic->linesize[0] > 0 && output + p2 * (depth >> 3) > output_end) ||
00176 (pic->linesize[0] < 0 && output + p2 * (depth >> 3) < output_end)) {
00177 bytestream2_skip(gb, 2 * (depth >> 3));
00178 continue;
00179 } else if (bytestream2_get_bytes_left(gb) < p2 * (depth >> 3)) {
00180 av_log(avctx, AV_LOG_ERROR, "bytestream overrun\n");
00181 return AVERROR_INVALIDDATA;
00182 }
00183
00184 if ((depth == 8) || (depth == 24)) {
00185 for(i = 0; i < p2 * (depth >> 3); i++) {
00186 *output++ = bytestream2_get_byteu(gb);
00187 }
00188
00189 if(depth == 8 && (p2 & 1)) {
00190 bytestream2_skip(gb, 1);
00191 }
00192 } else if (depth == 16) {
00193 for(i = 0; i < p2; i++) {
00194 *(uint16_t*)output = bytestream2_get_le16u(gb);
00195 output += 2;
00196 }
00197 } else if (depth == 32) {
00198 for(i = 0; i < p2; i++) {
00199 *(uint32_t*)output = bytestream2_get_le32u(gb);
00200 output += 4;
00201 }
00202 }
00203 pos += p2;
00204 } else {
00205 uint8_t pix[3];
00206 switch(depth){
00207 case 8: pix[0] = bytestream2_get_byte(gb);
00208 break;
00209 case 16: pix16 = bytestream2_get_le16(gb);
00210 break;
00211 case 24: pix[0] = bytestream2_get_byte(gb);
00212 pix[1] = bytestream2_get_byte(gb);
00213 pix[2] = bytestream2_get_byte(gb);
00214 break;
00215 case 32: pix32 = bytestream2_get_le32(gb);
00216 break;
00217 }
00218 if ((pic->linesize[0] > 0 && output + p1 * (depth >> 3) > output_end) ||
00219 (pic->linesize[0] < 0 && output + p1 * (depth >> 3) < output_end))
00220 continue;
00221 for(i = 0; i < p1; i++) {
00222 switch(depth){
00223 case 8: *output++ = pix[0];
00224 break;
00225 case 16: *(uint16_t*)output = pix16;
00226 output += 2;
00227 break;
00228 case 24: *output++ = pix[0];
00229 *output++ = pix[1];
00230 *output++ = pix[2];
00231 break;
00232 case 32: *(uint32_t*)output = pix32;
00233 output += 4;
00234 break;
00235 }
00236 }
00237 pos += p1;
00238 }
00239 }
00240
00241 av_log(avctx, AV_LOG_WARNING, "MS RLE warning: no end-of-picture code\n");
00242 return 0;
00243 }
00244
00245
00246 int ff_msrle_decode(AVCodecContext *avctx, AVPicture *pic,
00247 int depth, GetByteContext *gb)
00248 {
00249 switch(depth){
00250 case 4:
00251 return msrle_decode_pal4(avctx, pic, gb);
00252 case 8:
00253 case 16:
00254 case 24:
00255 case 32:
00256 return msrle_decode_8_16_24_32(avctx, pic, depth, gb);
00257 default:
00258 av_log(avctx, AV_LOG_ERROR, "Unknown depth %d\n", depth);
00259 return -1;
00260 }
00261 }