Mercurial > libavcodec.hg
annotate rl2.c @ 9077:ad7fd7a40717 libavcodec
Do not read uninitialized buffer, no matter if it will be multiplied by
zero later. This should fix some valgrind warnings and hopefully FATE
ra144 test on ARM.
author | vitor |
---|---|
date | Sun, 01 Mar 2009 11:14:21 +0000 |
parents | e9d9d946f213 |
children | 54bc8a2727b0 |
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, | |
184 const uint8_t *buf, int buf_size) | |
185 { | |
186 Rl2Context *s = avctx->priv_data; | |
187 | |
188 if(s->frame.data[0]) | |
189 avctx->release_buffer(avctx, &s->frame); | |
190 | |
191 /** get buffer */ | |
192 s->frame.reference= 0; | |
193 if(avctx->get_buffer(avctx, &s->frame)) { | |
194 av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
195 return -1; | |
196 } | |
197 | |
198 /** run length decode */ | |
199 rl2_rle_decode(s,buf,buf_size,s->frame.data[0],s->frame.linesize[0],s->video_base); | |
200 | |
201 /** make the palette available on the way out */ | |
202 memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE); | |
203 | |
204 *data_size = sizeof(AVFrame); | |
205 *(AVFrame*)data = s->frame; | |
206 | |
207 /** report that the buffer was completely consumed */ | |
208 return buf_size; | |
209 } | |
210 | |
211 | |
212 /** | |
213 * Uninit decoder | |
214 * @param avctx decoder context | |
215 * @return 0 success, -1 on error | |
216 */ | |
217 static av_cold int rl2_decode_end(AVCodecContext *avctx) | |
218 { | |
219 Rl2Context *s = avctx->priv_data; | |
220 | |
221 if(s->frame.data[0]) | |
222 avctx->release_buffer(avctx, &s->frame); | |
223 | |
224 av_free(s->back_frame); | |
225 | |
226 return 0; | |
227 } | |
228 | |
229 | |
230 AVCodec rl2_decoder = { | |
231 "rl2", | |
232 CODEC_TYPE_VIDEO, | |
233 CODEC_ID_RL2, | |
234 sizeof(Rl2Context), | |
235 rl2_decode_init, | |
236 NULL, | |
237 rl2_decode_end, | |
238 rl2_decode_frame, | |
239 CODEC_CAP_DR1, | |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6712
diff
changeset
|
240 .long_name = NULL_IF_CONFIG_SMALL("RL2 video"), |
6523 | 241 }; |
242 |