annotate ffmpeg/libavcodec/msrledec.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * Microsoft RLE decoder
yading@10 3 * Copyright (C) 2008 Konstantin Shishkov
yading@10 4 *
yading@10 5 * This file is part of FFmpeg.
yading@10 6 *
yading@10 7 * FFmpeg is free software; you can redistribute it and/or
yading@10 8 * modify it under the terms of the GNU Lesser General Public
yading@10 9 * License as published by the Free Software Foundation; either
yading@10 10 * version 2.1 of the License, or (at your option) any later version.
yading@10 11 *
yading@10 12 * FFmpeg is distributed in the hope that it will be useful,
yading@10 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 15 * Lesser General Public License for more details.
yading@10 16 *
yading@10 17 * You should have received a copy of the GNU Lesser General Public
yading@10 18 * License along with FFmpeg; if not, write to the Free Software
yading@10 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 20 */
yading@10 21
yading@10 22 /**
yading@10 23 * @file
yading@10 24 * MS RLE decoder based on decoder by Mike Melanson and my own for TSCC
yading@10 25 * For more information about the MS RLE format, visit:
yading@10 26 * http://www.multimedia.cx/msrle.txt
yading@10 27 */
yading@10 28
yading@10 29 #include "libavutil/intreadwrite.h"
yading@10 30 #include "avcodec.h"
yading@10 31 #include "msrledec.h"
yading@10 32
yading@10 33 static int msrle_decode_pal4(AVCodecContext *avctx, AVPicture *pic,
yading@10 34 GetByteContext *gb)
yading@10 35 {
yading@10 36 unsigned char rle_code;
yading@10 37 unsigned char extra_byte, odd_pixel;
yading@10 38 unsigned char stream_byte;
yading@10 39 unsigned int pixel_ptr = 0;
yading@10 40 int row_dec = pic->linesize[0];
yading@10 41 int row_ptr = (avctx->height - 1) * row_dec;
yading@10 42 int frame_size = row_dec * avctx->height;
yading@10 43 int i;
yading@10 44
yading@10 45 while (row_ptr >= 0) {
yading@10 46 if (bytestream2_get_bytes_left(gb) <= 0) {
yading@10 47 av_log(avctx, AV_LOG_ERROR,
yading@10 48 "MS RLE: bytestream overrun, %d rows left\n",
yading@10 49 row_ptr);
yading@10 50 return AVERROR_INVALIDDATA;
yading@10 51 }
yading@10 52 rle_code = stream_byte = bytestream2_get_byteu(gb);
yading@10 53 if (rle_code == 0) {
yading@10 54 /* fetch the next byte to see how to handle escape code */
yading@10 55 stream_byte = bytestream2_get_byte(gb);
yading@10 56 if (stream_byte == 0) {
yading@10 57 /* line is done, goto the next one */
yading@10 58 row_ptr -= row_dec;
yading@10 59 pixel_ptr = 0;
yading@10 60 } else if (stream_byte == 1) {
yading@10 61 /* decode is done */
yading@10 62 return 0;
yading@10 63 } else if (stream_byte == 2) {
yading@10 64 /* reposition frame decode coordinates */
yading@10 65 stream_byte = bytestream2_get_byte(gb);
yading@10 66 pixel_ptr += stream_byte;
yading@10 67 stream_byte = bytestream2_get_byte(gb);
yading@10 68 row_ptr -= stream_byte * row_dec;
yading@10 69 } else {
yading@10 70 // copy pixels from encoded stream
yading@10 71 odd_pixel = stream_byte & 1;
yading@10 72 rle_code = (stream_byte + 1) / 2;
yading@10 73 extra_byte = rle_code & 0x01;
yading@10 74 if (row_ptr + pixel_ptr + stream_byte > frame_size ||
yading@10 75 bytestream2_get_bytes_left(gb) < rle_code) {
yading@10 76 av_log(avctx, AV_LOG_ERROR,
yading@10 77 "MS RLE: frame/stream ptr just went out of bounds (copy)\n");
yading@10 78 return AVERROR_INVALIDDATA;
yading@10 79 }
yading@10 80
yading@10 81 for (i = 0; i < rle_code; i++) {
yading@10 82 if (pixel_ptr >= avctx->width)
yading@10 83 break;
yading@10 84 stream_byte = bytestream2_get_byteu(gb);
yading@10 85 pic->data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
yading@10 86 pixel_ptr++;
yading@10 87 if (i + 1 == rle_code && odd_pixel)
yading@10 88 break;
yading@10 89 if (pixel_ptr >= avctx->width)
yading@10 90 break;
yading@10 91 pic->data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
yading@10 92 pixel_ptr++;
yading@10 93 }
yading@10 94
yading@10 95 // if the RLE code is odd, skip a byte in the stream
yading@10 96 if (extra_byte)
yading@10 97 bytestream2_skip(gb, 1);
yading@10 98 }
yading@10 99 } else {
yading@10 100 // decode a run of data
yading@10 101 if (row_ptr + pixel_ptr + stream_byte > frame_size) {
yading@10 102 av_log(avctx, AV_LOG_ERROR,
yading@10 103 "MS RLE: frame ptr just went out of bounds (run)\n");
yading@10 104 return AVERROR_INVALIDDATA;
yading@10 105 }
yading@10 106 stream_byte = bytestream2_get_byte(gb);
yading@10 107 for (i = 0; i < rle_code; i++) {
yading@10 108 if (pixel_ptr >= avctx->width)
yading@10 109 break;
yading@10 110 if ((i & 1) == 0)
yading@10 111 pic->data[0][row_ptr + pixel_ptr] = stream_byte >> 4;
yading@10 112 else
yading@10 113 pic->data[0][row_ptr + pixel_ptr] = stream_byte & 0x0F;
yading@10 114 pixel_ptr++;
yading@10 115 }
yading@10 116 }
yading@10 117 }
yading@10 118
yading@10 119 /* one last sanity check on the way out */
yading@10 120 if (bytestream2_get_bytes_left(gb)) {
yading@10 121 av_log(avctx, AV_LOG_ERROR,
yading@10 122 "MS RLE: ended frame decode with %d bytes left over\n",
yading@10 123 bytestream2_get_bytes_left(gb));
yading@10 124 return AVERROR_INVALIDDATA;
yading@10 125 }
yading@10 126
yading@10 127 return 0;
yading@10 128 }
yading@10 129
yading@10 130
yading@10 131 static int msrle_decode_8_16_24_32(AVCodecContext *avctx, AVPicture *pic,
yading@10 132 int depth, GetByteContext *gb)
yading@10 133 {
yading@10 134 uint8_t *output, *output_end;
yading@10 135 int p1, p2, line=avctx->height - 1, pos=0, i;
yading@10 136 uint16_t pix16;
yading@10 137 uint32_t pix32;
yading@10 138 unsigned int width= FFABS(pic->linesize[0]) / (depth >> 3);
yading@10 139
yading@10 140 output = pic->data[0] + (avctx->height - 1) * pic->linesize[0];
yading@10 141 output_end = output + FFABS(pic->linesize[0]);
yading@10 142
yading@10 143 while (bytestream2_get_bytes_left(gb) > 0) {
yading@10 144 p1 = bytestream2_get_byteu(gb);
yading@10 145 if(p1 == 0) { //Escape code
yading@10 146 p2 = bytestream2_get_byte(gb);
yading@10 147 if(p2 == 0) { //End-of-line
yading@10 148 if (--line < 0) {
yading@10 149 if (bytestream2_get_be16(gb) == 1) { // end-of-picture
yading@10 150 return 0;
yading@10 151 } else {
yading@10 152 av_log(avctx, AV_LOG_ERROR,
yading@10 153 "Next line is beyond picture bounds (%d bytes left)\n",
yading@10 154 bytestream2_get_bytes_left(gb));
yading@10 155 return AVERROR_INVALIDDATA;
yading@10 156 }
yading@10 157 }
yading@10 158 output = pic->data[0] + line * pic->linesize[0];
yading@10 159 output_end = output + FFABS(pic->linesize[0]);
yading@10 160 pos = 0;
yading@10 161 continue;
yading@10 162 } else if(p2 == 1) { //End-of-picture
yading@10 163 return 0;
yading@10 164 } else if(p2 == 2) { //Skip
yading@10 165 p1 = bytestream2_get_byte(gb);
yading@10 166 p2 = bytestream2_get_byte(gb);
yading@10 167 line -= p2;
yading@10 168 pos += p1;
yading@10 169 if (line < 0 || pos >= width){
yading@10 170 av_log(avctx, AV_LOG_ERROR, "Skip beyond picture bounds\n");
yading@10 171 return -1;
yading@10 172 }
yading@10 173 output = pic->data[0] + line * pic->linesize[0] + pos * (depth >> 3);
yading@10 174 output_end = pic->data[0] + line * pic->linesize[0] + FFABS(pic->linesize[0]);
yading@10 175 continue;
yading@10 176 }
yading@10 177 // Copy data
yading@10 178 if (output + p2 * (depth >> 3) > output_end) {
yading@10 179 bytestream2_skip(gb, 2 * (depth >> 3));
yading@10 180 continue;
yading@10 181 } else if (bytestream2_get_bytes_left(gb) < p2 * (depth >> 3)) {
yading@10 182 av_log(avctx, AV_LOG_ERROR, "bytestream overrun\n");
yading@10 183 return AVERROR_INVALIDDATA;
yading@10 184 }
yading@10 185
yading@10 186 if ((depth == 8) || (depth == 24)) {
yading@10 187 for(i = 0; i < p2 * (depth >> 3); i++) {
yading@10 188 *output++ = bytestream2_get_byteu(gb);
yading@10 189 }
yading@10 190 // RLE8 copy is actually padded - and runs are not!
yading@10 191 if(depth == 8 && (p2 & 1)) {
yading@10 192 bytestream2_skip(gb, 1);
yading@10 193 }
yading@10 194 } else if (depth == 16) {
yading@10 195 for(i = 0; i < p2; i++) {
yading@10 196 *(uint16_t*)output = bytestream2_get_le16u(gb);
yading@10 197 output += 2;
yading@10 198 }
yading@10 199 } else if (depth == 32) {
yading@10 200 for(i = 0; i < p2; i++) {
yading@10 201 *(uint32_t*)output = bytestream2_get_le32u(gb);
yading@10 202 output += 4;
yading@10 203 }
yading@10 204 }
yading@10 205 pos += p2;
yading@10 206 } else { //run of pixels
yading@10 207 uint8_t pix[3]; //original pixel
yading@10 208 if (output + p1 * (depth >> 3) > output_end)
yading@10 209 continue;
yading@10 210
yading@10 211 switch(depth){
yading@10 212 case 8:
yading@10 213 pix[0] = bytestream2_get_byte(gb);
yading@10 214 for(i = 0; i < p1; i++)
yading@10 215 *output++ = pix[0];
yading@10 216 break;
yading@10 217 case 16:
yading@10 218 pix16 = bytestream2_get_le16(gb);
yading@10 219 for(i = 0; i < p1; i++) {
yading@10 220 *(uint16_t*)output = pix16;
yading@10 221 output += 2;
yading@10 222 }
yading@10 223 break;
yading@10 224 case 24:
yading@10 225 pix[0] = bytestream2_get_byte(gb);
yading@10 226 pix[1] = bytestream2_get_byte(gb);
yading@10 227 pix[2] = bytestream2_get_byte(gb);
yading@10 228 for(i = 0; i < p1; i++) {
yading@10 229 *output++ = pix[0];
yading@10 230 *output++ = pix[1];
yading@10 231 *output++ = pix[2];
yading@10 232 }
yading@10 233 break;
yading@10 234 case 32:
yading@10 235 pix32 = bytestream2_get_le32(gb);
yading@10 236 for(i = 0; i < p1; i++) {
yading@10 237 *(uint32_t*)output = pix32;
yading@10 238 output += 4;
yading@10 239 }
yading@10 240 break;
yading@10 241 }
yading@10 242 pos += p1;
yading@10 243 }
yading@10 244 }
yading@10 245
yading@10 246 av_log(avctx, AV_LOG_WARNING, "MS RLE warning: no end-of-picture code\n");
yading@10 247 return 0;
yading@10 248 }
yading@10 249
yading@10 250
yading@10 251 int ff_msrle_decode(AVCodecContext *avctx, AVPicture *pic,
yading@10 252 int depth, GetByteContext *gb)
yading@10 253 {
yading@10 254 switch(depth){
yading@10 255 case 4:
yading@10 256 return msrle_decode_pal4(avctx, pic, gb);
yading@10 257 case 8:
yading@10 258 case 16:
yading@10 259 case 24:
yading@10 260 case 32:
yading@10 261 return msrle_decode_8_16_24_32(avctx, pic, depth, gb);
yading@10 262 default:
yading@10 263 av_log(avctx, AV_LOG_ERROR, "Unknown depth %d\n", depth);
yading@10 264 return -1;
yading@10 265 }
yading@10 266 }