Mercurial > libavcodec.hg
annotate rl2.c @ 12483:0159a19bfff7 libavcodec
aacdec: Rework channel mapping compatibility hacks.
For a PCE based configuration map the channels solely based on tags.
For an indexed configuration map the channels solely based on position.
This works with all known exotic samples including al17, elem_id0, bad_concat,
and lfe_is_sce.
author | alexc |
---|---|
date | Fri, 10 Sep 2010 18:01:48 +0000 |
parents | 9cfc564bc3e6 |
children |
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 | |
11644
7dd2a45249a9
Remove explicit filename from Doxygen @file commands.
diego
parents:
11560
diff
changeset
|
24 * @file |
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 | |
8573
2acf0ae7b041
Fix build: Add intreadwrite.h and bswap.h #includes where necessary.
diego
parents:
7040
diff
changeset
|
34 #include "libavutil/intreadwrite.h" |
6523 | 35 #include "avcodec.h" |
36 | |
37 | |
38 #define EXTRADATA1_SIZE (6 + 256 * 3) ///< video base, clr count, palette | |
39 | |
40 typedef struct Rl2Context { | |
41 AVCodecContext *avctx; | |
42 AVFrame frame; | |
43 | |
44 unsigned short video_base; ///< initial drawing offset | |
45 unsigned int clr_count; ///< number of used colors (currently unused) | |
46 unsigned char* back_frame; ///< background frame | |
47 unsigned int palette[AVPALETTE_COUNT]; | |
48 } Rl2Context; | |
49 | |
50 /** | |
51 * Run Length Decode a single 320x200 frame | |
52 * @param s rl2 context | |
12056
25e9cb2b9477
Fix misspelled parameter names in Doxygen documentation.
diego
parents:
11644
diff
changeset
|
53 * @param in input buffer |
6523 | 54 * @param size input buffer size |
55 * @param out ouput buffer | |
56 * @param stride stride of the output buffer | |
57 * @param video_base offset of the rle data inside the frame | |
58 */ | |
59 static void rl2_rle_decode(Rl2Context *s,const unsigned char* in,int size, | |
60 unsigned char* out,int stride,int video_base){ | |
61 int base_x = video_base % s->avctx->width; | |
62 int base_y = video_base / s->avctx->width; | |
63 int stride_adj = stride - s->avctx->width; | |
64 int i; | |
65 const unsigned char* back_frame = s->back_frame; | |
66 const unsigned char* in_end = in + size; | |
67 const unsigned char* out_end = out + stride * s->avctx->height; | |
68 unsigned char* line_end = out + s->avctx->width; | |
69 | |
70 /** copy start of the background frame */ | |
71 for(i=0;i<=base_y;i++){ | |
72 if(s->back_frame) | |
73 memcpy(out,back_frame,s->avctx->width); | |
74 out += stride; | |
75 back_frame += s->avctx->width; | |
76 } | |
77 back_frame += base_x - s->avctx->width; | |
78 line_end = out - stride_adj; | |
79 out += base_x - stride; | |
80 | |
81 /** decode the variable part of the frame */ | |
82 while(in < in_end){ | |
83 unsigned char val = *in++; | |
84 int len = 1; | |
85 if(val >= 0x80){ | |
86 if(in >= in_end) | |
87 break; | |
88 len = *in++; | |
89 if(!len) | |
90 break; | |
91 } | |
92 | |
93 if(len >= out_end - out) | |
94 break; | |
95 | |
96 if(s->back_frame) | |
97 val |= 0x80; | |
98 else | |
99 val &= ~0x80; | |
100 | |
101 while(len--){ | |
102 *out++ = (val == 0x80)? *back_frame:val; | |
103 back_frame++; | |
104 if(out == line_end){ | |
105 out += stride_adj; | |
106 line_end += stride; | |
107 if(len >= out_end - out) | |
108 break; | |
109 } | |
110 } | |
111 } | |
112 | |
113 /** copy the rest from the background frame */ | |
114 if(s->back_frame){ | |
115 while(out < out_end){ | |
116 memcpy(out, back_frame, line_end - out); | |
117 back_frame += line_end - out; | |
118 out = line_end + stride_adj; | |
119 line_end += stride; | |
120 } | |
121 } | |
122 } | |
123 | |
124 | |
125 /** | |
126 * Initialize the decoder | |
127 * @param avctx decoder context | |
128 * @return 0 success, -1 on error | |
129 */ | |
130 static av_cold int rl2_decode_init(AVCodecContext *avctx) | |
131 { | |
132 Rl2Context *s = avctx->priv_data; | |
133 int back_size; | |
134 int i; | |
135 s->avctx = avctx; | |
136 avctx->pix_fmt = PIX_FMT_PAL8; | |
137 | |
138 /** parse extra data */ | |
139 if(!avctx->extradata || avctx->extradata_size < EXTRADATA1_SIZE){ | |
140 av_log(avctx, AV_LOG_ERROR, "invalid extradata size\n"); | |
141 return -1; | |
142 } | |
143 | |
144 /** get frame_offset */ | |
145 s->video_base = AV_RL16(&avctx->extradata[0]); | |
146 s->clr_count = AV_RL32(&avctx->extradata[2]); | |
147 | |
148 if(s->video_base >= avctx->width * avctx->height){ | |
149 av_log(avctx, AV_LOG_ERROR, "invalid video_base\n"); | |
150 return -1; | |
151 } | |
152 | |
153 /** initialize palette */ | |
154 for(i=0;i<AVPALETTE_COUNT;i++) | |
155 s->palette[i] = AV_RB24(&avctx->extradata[6 + i * 3]); | |
156 | |
157 /** decode background frame if present */ | |
158 back_size = avctx->extradata_size - EXTRADATA1_SIZE; | |
159 | |
160 if(back_size > 0){ | |
161 unsigned char* back_frame = av_mallocz(avctx->width*avctx->height); | |
162 if(!back_frame) | |
163 return -1; | |
164 rl2_rle_decode(s,avctx->extradata + EXTRADATA1_SIZE,back_size, | |
165 back_frame,avctx->width,0); | |
166 s->back_frame = back_frame; | |
167 } | |
168 return 0; | |
169 } | |
170 | |
171 | |
172 static int rl2_decode_frame(AVCodecContext *avctx, | |
173 void *data, int *data_size, | |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8718
diff
changeset
|
174 AVPacket *avpkt) |
6523 | 175 { |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8718
diff
changeset
|
176 const uint8_t *buf = avpkt->data; |
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8718
diff
changeset
|
177 int buf_size = avpkt->size; |
6523 | 178 Rl2Context *s = avctx->priv_data; |
179 | |
180 if(s->frame.data[0]) | |
181 avctx->release_buffer(avctx, &s->frame); | |
182 | |
183 /** get buffer */ | |
184 s->frame.reference= 0; | |
185 if(avctx->get_buffer(avctx, &s->frame)) { | |
186 av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
187 return -1; | |
188 } | |
189 | |
190 /** run length decode */ | |
191 rl2_rle_decode(s,buf,buf_size,s->frame.data[0],s->frame.linesize[0],s->video_base); | |
192 | |
193 /** make the palette available on the way out */ | |
194 memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE); | |
195 | |
196 *data_size = sizeof(AVFrame); | |
197 *(AVFrame*)data = s->frame; | |
198 | |
199 /** report that the buffer was completely consumed */ | |
200 return buf_size; | |
201 } | |
202 | |
203 | |
204 /** | |
205 * Uninit decoder | |
206 * @param avctx decoder context | |
207 * @return 0 success, -1 on error | |
208 */ | |
209 static av_cold int rl2_decode_end(AVCodecContext *avctx) | |
210 { | |
211 Rl2Context *s = avctx->priv_data; | |
212 | |
213 if(s->frame.data[0]) | |
214 avctx->release_buffer(avctx, &s->frame); | |
215 | |
216 av_free(s->back_frame); | |
217 | |
218 return 0; | |
219 } | |
220 | |
221 | |
222 AVCodec rl2_decoder = { | |
223 "rl2", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
9981
diff
changeset
|
224 AVMEDIA_TYPE_VIDEO, |
6523 | 225 CODEC_ID_RL2, |
226 sizeof(Rl2Context), | |
227 rl2_decode_init, | |
228 NULL, | |
229 rl2_decode_end, | |
230 rl2_decode_frame, | |
231 CODEC_CAP_DR1, | |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6712
diff
changeset
|
232 .long_name = NULL_IF_CONFIG_SMALL("RL2 video"), |
6523 | 233 }; |
234 |