Mercurial > libavcodec.hg
annotate rl2.c @ 11032:01bd040f8607 libavcodec
Unroll main loop so the edge==0 case is seperate.
This allows many things to be simplified away.
h264 decoder is overall 1% faster with a mbaff sample and
0.1% slower with the cathedral sample, probably because the slow loop
filter code must be loaded into the code cache for each first MB of each
row but isnt used for the following MBs.
author | michael |
---|---|
date | Thu, 28 Jan 2010 01:24:25 +0000 |
parents | 5da84f0d0a55 |
children | 8a4984c5cacc |
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 | |
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 | |
53 * @param buf input buffer | |
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 /** | |
173 * Decode a single frame | |
174 * @param avctx decoder context | |
175 * @param data decoded frame | |
176 * @param data_size size of the decoded frame | |
177 * @param buf input buffer | |
178 * @param buf_size input buffer size | |
179 * @return 0 success, -1 on error | |
180 */ | |
181 static int rl2_decode_frame(AVCodecContext *avctx, | |
182 void *data, int *data_size, | |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8718
diff
changeset
|
183 AVPacket *avpkt) |
6523 | 184 { |
9355
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8718
diff
changeset
|
185 const uint8_t *buf = avpkt->data; |
54bc8a2727b0
Implement avcodec_decode_video2(), _audio3() and _subtitle2() which takes an
rbultje
parents:
8718
diff
changeset
|
186 int buf_size = avpkt->size; |
6523 | 187 Rl2Context *s = avctx->priv_data; |
188 | |
189 if(s->frame.data[0]) | |
190 avctx->release_buffer(avctx, &s->frame); | |
191 | |
192 /** get buffer */ | |
193 s->frame.reference= 0; | |
194 if(avctx->get_buffer(avctx, &s->frame)) { | |
195 av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
196 return -1; | |
197 } | |
198 | |
199 /** run length decode */ | |
200 rl2_rle_decode(s,buf,buf_size,s->frame.data[0],s->frame.linesize[0],s->video_base); | |
201 | |
202 /** make the palette available on the way out */ | |
203 memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE); | |
204 | |
205 *data_size = sizeof(AVFrame); | |
206 *(AVFrame*)data = s->frame; | |
207 | |
208 /** report that the buffer was completely consumed */ | |
209 return buf_size; | |
210 } | |
211 | |
212 | |
213 /** | |
214 * Uninit decoder | |
215 * @param avctx decoder context | |
216 * @return 0 success, -1 on error | |
217 */ | |
218 static av_cold int rl2_decode_end(AVCodecContext *avctx) | |
219 { | |
220 Rl2Context *s = avctx->priv_data; | |
221 | |
222 if(s->frame.data[0]) | |
223 avctx->release_buffer(avctx, &s->frame); | |
224 | |
225 av_free(s->back_frame); | |
226 | |
227 return 0; | |
228 } | |
229 | |
230 | |
231 AVCodec rl2_decoder = { | |
232 "rl2", | |
233 CODEC_TYPE_VIDEO, | |
234 CODEC_ID_RL2, | |
235 sizeof(Rl2Context), | |
236 rl2_decode_init, | |
237 NULL, | |
238 rl2_decode_end, | |
239 rl2_decode_frame, | |
240 CODEC_CAP_DR1, | |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6712
diff
changeset
|
241 .long_name = NULL_IF_CONFIG_SMALL("RL2 video"), |
6523 | 242 }; |
243 |