Mercurial > libavcodec.hg
annotate rl2.c @ 9896:bbefbca72722 libavcodec
Drop code that attempts to decode frames that are prefixed by junk.
Too often it ends up decoding random data into noise without detecting
it (for example after seeking of some MP3 data with oddly often occurring
startcode emulation).
Fixes issue1154.
| author | michael |
|---|---|
| date | Tue, 30 Jun 2009 03:57:27 +0000 |
| parents | 54bc8a2727b0 |
| children | 5da84f0d0a55 |
| rev | line source |
|---|---|
| 6523 | 1 /* |
| 2 * RL2 Video Decoder | |
| 3 * Copyright (C) 2008 Sascha Sommer (saschasommer@freenet.de) | |
| 4 * | |
| 5 * This file is part of FFmpeg. | |
| 6 * | |
| 7 * FFmpeg is free software; you can redistribute it and/or | |
| 8 * modify it under the terms of the GNU Lesser General Public | |
| 9 * License as published by the Free Software Foundation; either | |
| 10 * version 2.1 of the License, or (at your option) any later version. | |
| 11 * | |
| 12 * FFmpeg is distributed in the hope that it will be useful, | |
| 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 15 * Lesser General Public License for more details. | |
| 16 * | |
| 17 * You should have received a copy of the GNU Lesser General Public | |
| 18 * License along with FFmpeg; if not, write to the Free Software | |
| 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| 20 */ | |
| 21 | |
| 22 /** | |
| 23 * RL2 Video Decoder | |
|
8718
e9d9d946f213
Use full internal pathname in doxygen @file directives.
diego
parents:
8573
diff
changeset
|
24 * @file libavcodec/rl2.c |
| 6523 | 25 * @author Sascha Sommer (saschasommer@freenet.de) |
| 26 * For more information about the RL2 format, visit: | |
| 27 * http://wiki.multimedia.cx/index.php?title=RL2 | |
| 28 */ | |
| 29 | |
| 30 #include <stdio.h> | |
| 31 #include <stdlib.h> | |
| 32 #include <string.h> | |
| 33 #include <unistd.h> | |
| 34 | |
|
8573
2acf0ae7b041
Fix build: Add intreadwrite.h and bswap.h #includes where necessary.
diego
parents:
7040
diff
changeset
|
35 #include "libavutil/intreadwrite.h" |
| 6523 | 36 #include "avcodec.h" |
| 37 | |
| 38 | |
| 39 #define EXTRADATA1_SIZE (6 + 256 * 3) ///< video base, clr count, palette | |
| 40 | |
| 41 typedef struct Rl2Context { | |
| 42 AVCodecContext *avctx; | |
| 43 AVFrame frame; | |
| 44 | |
| 45 unsigned short video_base; ///< initial drawing offset | |
| 46 unsigned int clr_count; ///< number of used colors (currently unused) | |
| 47 unsigned char* back_frame; ///< background frame | |
| 48 unsigned int palette[AVPALETTE_COUNT]; | |
| 49 } Rl2Context; | |
| 50 | |
| 51 /** | |
| 52 * Run Length Decode a single 320x200 frame | |
| 53 * @param s rl2 context | |
| 54 * @param buf input buffer | |
| 55 * @param size input buffer size | |
| 56 * @param out ouput buffer | |
| 57 * @param stride stride of the output buffer | |
| 58 * @param video_base offset of the rle data inside the frame | |
| 59 */ | |
| 60 static void rl2_rle_decode(Rl2Context *s,const unsigned char* in,int size, | |
| 61 unsigned char* out,int stride,int video_base){ | |
| 62 int base_x = video_base % s->avctx->width; | |
| 63 int base_y = video_base / s->avctx->width; | |
| 64 int stride_adj = stride - s->avctx->width; | |
| 65 int i; | |
| 66 const unsigned char* back_frame = s->back_frame; | |
| 67 const unsigned char* in_end = in + size; | |
| 68 const unsigned char* out_end = out + stride * s->avctx->height; | |
| 69 unsigned char* line_end = out + s->avctx->width; | |
| 70 | |
| 71 /** copy start of the background frame */ | |
| 72 for(i=0;i<=base_y;i++){ | |
| 73 if(s->back_frame) | |
| 74 memcpy(out,back_frame,s->avctx->width); | |
| 75 out += stride; | |
| 76 back_frame += s->avctx->width; | |
| 77 } | |
| 78 back_frame += base_x - s->avctx->width; | |
| 79 line_end = out - stride_adj; | |
| 80 out += base_x - stride; | |
| 81 | |
| 82 /** decode the variable part of the frame */ | |
| 83 while(in < in_end){ | |
| 84 unsigned char val = *in++; | |
| 85 int len = 1; | |
| 86 if(val >= 0x80){ | |
| 87 if(in >= in_end) | |
| 88 break; | |
| 89 len = *in++; | |
| 90 if(!len) | |
| 91 break; | |
| 92 } | |
| 93 | |
| 94 if(len >= out_end - out) | |
| 95 break; | |
| 96 | |
| 97 if(s->back_frame) | |
| 98 val |= 0x80; | |
| 99 else | |
| 100 val &= ~0x80; | |
| 101 | |
| 102 while(len--){ | |
| 103 *out++ = (val == 0x80)? *back_frame:val; | |
| 104 back_frame++; | |
| 105 if(out == line_end){ | |
| 106 out += stride_adj; | |
| 107 line_end += stride; | |
| 108 if(len >= out_end - out) | |
| 109 break; | |
| 110 } | |
| 111 } | |
| 112 } | |
| 113 | |
| 114 /** copy the rest from the background frame */ | |
| 115 if(s->back_frame){ | |
| 116 while(out < out_end){ | |
| 117 memcpy(out, back_frame, line_end - out); | |
| 118 back_frame += line_end - out; | |
| 119 out = line_end + stride_adj; | |
| 120 line_end += stride; | |
| 121 } | |
| 122 } | |
| 123 } | |
| 124 | |
| 125 | |
| 126 /** | |
| 127 * Initialize the decoder | |
| 128 * @param avctx decoder context | |
| 129 * @return 0 success, -1 on error | |
| 130 */ | |
| 131 static av_cold int rl2_decode_init(AVCodecContext *avctx) | |
| 132 { | |
| 133 Rl2Context *s = avctx->priv_data; | |
| 134 int back_size; | |
| 135 int i; | |
| 136 s->avctx = avctx; | |
| 137 avctx->pix_fmt = PIX_FMT_PAL8; | |
| 138 | |
| 139 /** parse extra data */ | |
| 140 if(!avctx->extradata || avctx->extradata_size < EXTRADATA1_SIZE){ | |
| 141 av_log(avctx, AV_LOG_ERROR, "invalid extradata size\n"); | |
| 142 return -1; | |
| 143 } | |
| 144 | |
| 145 /** get frame_offset */ | |
| 146 s->video_base = AV_RL16(&avctx->extradata[0]); | |
| 147 s->clr_count = AV_RL32(&avctx->extradata[2]); | |
| 148 | |
| 149 if(s->video_base >= avctx->width * avctx->height){ | |
| 150 av_log(avctx, AV_LOG_ERROR, "invalid video_base\n"); | |
| 151 return -1; | |
| 152 } | |
| 153 | |
| 154 /** initialize palette */ | |
| 155 for(i=0;i<AVPALETTE_COUNT;i++) | |
| 156 s->palette[i] = AV_RB24(&avctx->extradata[6 + i * 3]); | |
| 157 | |
| 158 /** decode background frame if present */ | |
| 159 back_size = avctx->extradata_size - EXTRADATA1_SIZE; | |
| 160 | |
| 161 if(back_size > 0){ | |
| 162 unsigned char* back_frame = av_mallocz(avctx->width*avctx->height); | |
| 163 if(!back_frame) | |
| 164 return -1; | |
| 165 rl2_rle_decode(s,avctx->extradata + EXTRADATA1_SIZE,back_size, | |
| 166 back_frame,avctx->width,0); | |
| 167 s->back_frame = back_frame; | |
| 168 } | |
| 169 return 0; | |
| 170 } | |
| 171 | |
| 172 | |
| 173 /** | |
| 174 * Decode a single frame | |
| 175 * @param avctx decoder context | |
| 176 * @param data decoded frame | |
| 177 * @param data_size size of the decoded frame | |
| 178 * @param buf input buffer | |
| 179 * @param buf_size input buffer size | |
| 180 * @return 0 success, -1 on error | |
| 181 */ | |
| 182 static int rl2_decode_frame(AVCodecContext *avctx, | |
| 183 void *data, int *data_size, | |
|
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8718
diff
changeset
|
184 AVPacket *avpkt) |
| 6523 | 185 { |
|
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8718
diff
changeset
|
186 const uint8_t *buf = avpkt->data; |
|
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8718
diff
changeset
|
187 int buf_size = avpkt->size; |
| 6523 | 188 Rl2Context *s = avctx->priv_data; |
| 189 | |
| 190 if(s->frame.data[0]) | |
| 191 avctx->release_buffer(avctx, &s->frame); | |
| 192 | |
| 193 /** get buffer */ | |
| 194 s->frame.reference= 0; | |
| 195 if(avctx->get_buffer(avctx, &s->frame)) { | |
| 196 av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
| 197 return -1; | |
| 198 } | |
| 199 | |
| 200 /** run length decode */ | |
| 201 rl2_rle_decode(s,buf,buf_size,s->frame.data[0],s->frame.linesize[0],s->video_base); | |
| 202 | |
| 203 /** make the palette available on the way out */ | |
| 204 memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE); | |
| 205 | |
| 206 *data_size = sizeof(AVFrame); | |
| 207 *(AVFrame*)data = s->frame; | |
| 208 | |
| 209 /** report that the buffer was completely consumed */ | |
| 210 return buf_size; | |
| 211 } | |
| 212 | |
| 213 | |
| 214 /** | |
| 215 * Uninit decoder | |
| 216 * @param avctx decoder context | |
| 217 * @return 0 success, -1 on error | |
| 218 */ | |
| 219 static av_cold int rl2_decode_end(AVCodecContext *avctx) | |
| 220 { | |
| 221 Rl2Context *s = avctx->priv_data; | |
| 222 | |
| 223 if(s->frame.data[0]) | |
| 224 avctx->release_buffer(avctx, &s->frame); | |
| 225 | |
| 226 av_free(s->back_frame); | |
| 227 | |
| 228 return 0; | |
| 229 } | |
| 230 | |
| 231 | |
| 232 AVCodec rl2_decoder = { | |
| 233 "rl2", | |
| 234 CODEC_TYPE_VIDEO, | |
| 235 CODEC_ID_RL2, | |
| 236 sizeof(Rl2Context), | |
| 237 rl2_decode_init, | |
| 238 NULL, | |
| 239 rl2_decode_end, | |
| 240 rl2_decode_frame, | |
| 241 CODEC_CAP_DR1, | |
|
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6712
diff
changeset
|
242 .long_name = NULL_IF_CONFIG_SMALL("RL2 video"), |
| 6523 | 243 }; |
| 244 |
