Mercurial > libavcodec.hg
annotate idcinvideo.c @ 5311:7742d5411c9d libavcodec
AC-3 decoder, soc revision 48, Aug 16 11:27:49 2006 UTC by cloud9
I realized that the bug was not in the imdct routine but in the
get_transform_coeffs.
Fixed it.
Code now uses the ffmpeg's imdct routines.
All the mplayer's ac3 samples are decoded
successfully.
Also improved downmixing.
Now all the downmixing coeffcients for channels
are normalized such that the sum of coefficients
used to construct the output for single channel
never exceeds 1.0.
author | jbr |
---|---|
date | Sat, 14 Jul 2007 15:58:42 +0000 |
parents | 2b72f9bc4f06 |
children | dfdff1ca78a7 |
rev | line source |
---|---|
1498 | 1 /* |
2 * Id Quake II CIN Video Decoder | |
3 * Copyright (C) 2003 the ffmpeg project | |
4 * | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
5 * This file is part of FFmpeg. |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
6 * |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
1498 | 8 * modify it under the terms of the GNU Lesser General Public |
9 * License as published by the Free Software Foundation; either | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
1498 | 11 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
1498 | 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 | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
3036
0b546eab515d
Update licensing information: The FSF changed postal address.
diego
parents:
2508
diff
changeset
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
1498 | 20 */ |
21 | |
22 /** | |
23 * @file idcinvideo.c | |
24 * Id Quake II Cin Video Decoder by Dr. Tim Ferguson | |
25 * For more information about the Id CIN format, visit: | |
26 * http://www.csse.monash.edu.au/~timf/ | |
27 * | |
1499 | 28 * This video decoder outputs PAL8 colorspace data. Interacting with this |
29 * decoder is a little involved. During initialization, the demuxer must | |
30 * transmit the 65536-byte Huffman table(s) to the decoder via extradata. | |
31 * Then, whenever a palette change is encountered while demuxing the file, | |
32 * the demuxer must use the same extradata space to transmit an | |
33 * AVPaletteControl structure. | |
1498 | 34 * |
35 * Id CIN video is purely Huffman-coded, intraframe-only codec. It achieves | |
36 * a little more compression by exploiting the fact that adjacent pixels | |
37 * tend to be similar. | |
38 * | |
39 * Note that this decoder could use ffmpeg's optimized VLC facilities | |
40 * rather than naive, tree-based Huffman decoding. However, there are 256 | |
41 * Huffman tables. Plus, the VLC bit coding order is right -> left instead | |
42 * or left -> right, so all of the bits would have to be reversed. Further, | |
43 * the original Quake II implementation likely used a similar naive | |
44 * decoding algorithm and it worked fine on much lower spec machines. | |
45 */ | |
46 | |
47 #include <stdio.h> | |
48 #include <stdlib.h> | |
49 #include <string.h> | |
50 #include <unistd.h> | |
51 | |
52 #include "avcodec.h" | |
53 #include "dsputil.h" | |
54 | |
55 #define HUFFMAN_TABLE_SIZE 64 * 1024 | |
56 #define HUF_TOKENS 256 | |
57 #define PALETTE_COUNT 256 | |
58 | |
59 typedef struct | |
60 { | |
61 int count; | |
62 unsigned char used; | |
63 int children[2]; | |
64 } hnode_t; | |
65 | |
66 typedef struct IdcinContext { | |
67 | |
68 AVCodecContext *avctx; | |
69 DSPContext dsp; | |
70 AVFrame frame; | |
71 | |
72 unsigned char *buf; | |
73 int size; | |
74 | |
75 hnode_t huff_nodes[256][HUF_TOKENS*2]; | |
76 int num_huff_nodes[256]; | |
77 | |
78 } IdcinContext; | |
79 | |
80 /* | |
81 * Find the lowest probability node in a Huffman table, and mark it as | |
82 * being assigned to a higher probability. | |
83 * Returns the node index of the lowest unused node, or -1 if all nodes | |
84 * are used. | |
85 */ | |
86 static int huff_smallest_node(hnode_t *hnodes, int num_hnodes) { | |
87 int i; | |
88 int best, best_node; | |
89 | |
90 best = 99999999; | |
91 best_node = -1; | |
92 for(i = 0; i < num_hnodes; i++) { | |
93 if(hnodes[i].used) | |
94 continue; | |
95 if(!hnodes[i].count) | |
96 continue; | |
97 if(hnodes[i].count < best) { | |
98 best = hnodes[i].count; | |
99 best_node = i; | |
100 } | |
101 } | |
102 | |
103 if(best_node == -1) | |
104 return -1; | |
105 hnodes[best_node].used = 1; | |
106 return best_node; | |
107 } | |
108 | |
109 /* | |
110 * Build the Huffman tree using the generated/loaded probabilities histogram. | |
111 * | |
112 * On completion: | |
113 * huff_nodes[prev][i < HUF_TOKENS] - are the nodes at the base of the tree. | |
114 * huff_nodes[prev][i >= HUF_TOKENS] - are used to construct the tree. | |
115 * num_huff_nodes[prev] - contains the index to the root node of the tree. | |
116 * That is: huff_nodes[prev][num_huff_nodes[prev]] is the root node. | |
117 */ | |
118 static void huff_build_tree(IdcinContext *s, int prev) { | |
119 hnode_t *node, *hnodes; | |
120 int num_hnodes, i; | |
121 | |
122 num_hnodes = HUF_TOKENS; | |
123 hnodes = s->huff_nodes[prev]; | |
124 for(i = 0; i < HUF_TOKENS * 2; i++) | |
125 hnodes[i].used = 0; | |
126 | |
127 while (1) { | |
128 node = &hnodes[num_hnodes]; /* next free node */ | |
129 | |
130 /* pick two lowest counts */ | |
131 node->children[0] = huff_smallest_node(hnodes, num_hnodes); | |
132 if(node->children[0] == -1) | |
133 break; /* reached the root node */ | |
134 | |
135 node->children[1] = huff_smallest_node(hnodes, num_hnodes); | |
136 if(node->children[1] == -1) | |
137 break; /* reached the root node */ | |
138 | |
139 /* combine nodes probability for new node */ | |
140 node->count = hnodes[node->children[0]].count + | |
141 hnodes[node->children[1]].count; | |
142 num_hnodes++; | |
143 } | |
144 | |
145 s->num_huff_nodes[prev] = num_hnodes - 1; | |
146 } | |
147 | |
148 static int idcin_decode_init(AVCodecContext *avctx) | |
149 { | |
4827 | 150 IdcinContext *s = avctx->priv_data; |
1498 | 151 int i, j, histogram_index = 0; |
152 unsigned char *histograms; | |
153 | |
154 s->avctx = avctx; | |
155 avctx->pix_fmt = PIX_FMT_PAL8; | |
156 dsputil_init(&s->dsp, avctx); | |
157 | |
158 /* make sure the Huffman tables make it */ | |
159 if (s->avctx->extradata_size != HUFFMAN_TABLE_SIZE) { | |
1598
932d306bf1dc
av_log() patch by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michael
parents:
1585
diff
changeset
|
160 av_log(s->avctx, AV_LOG_ERROR, " Id CIN video: expected extradata size of %d\n", HUFFMAN_TABLE_SIZE); |
1498 | 161 return -1; |
162 } | |
163 | |
164 /* build the 256 Huffman decode trees */ | |
165 histograms = (unsigned char *)s->avctx->extradata; | |
166 for (i = 0; i < 256; i++) { | |
167 for(j = 0; j < HUF_TOKENS; j++) | |
168 s->huff_nodes[i][j].count = histograms[histogram_index++]; | |
169 huff_build_tree(s, i); | |
170 } | |
171 | |
172 s->frame.data[0] = NULL; | |
173 | |
174 return 0; | |
175 } | |
176 | |
177 static void idcin_decode_vlcs(IdcinContext *s) | |
178 { | |
179 hnode_t *hnodes; | |
180 long x, y; | |
181 int prev; | |
182 unsigned char v = 0; | |
183 int bit_pos, node_num, dat_pos; | |
184 | |
185 prev = bit_pos = dat_pos = 0; | |
186 for (y = 0; y < (s->frame.linesize[0] * s->avctx->height); | |
187 y += s->frame.linesize[0]) { | |
188 for (x = y; x < y + s->avctx->width; x++) { | |
189 node_num = s->num_huff_nodes[prev]; | |
190 hnodes = s->huff_nodes[prev]; | |
191 | |
192 while(node_num >= HUF_TOKENS) { | |
193 if(!bit_pos) { | |
2508 | 194 if(dat_pos >= s->size) { |
1598
932d306bf1dc
av_log() patch by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michael
parents:
1585
diff
changeset
|
195 av_log(s->avctx, AV_LOG_ERROR, "Huffman decode error.\n"); |
1498 | 196 return; |
197 } | |
198 bit_pos = 8; | |
199 v = s->buf[dat_pos++]; | |
200 } | |
201 | |
202 node_num = hnodes[node_num].children[v & 0x01]; | |
203 v = v >> 1; | |
204 bit_pos--; | |
205 } | |
206 | |
207 s->frame.data[0][x] = node_num; | |
208 prev = node_num; | |
209 } | |
210 } | |
211 } | |
212 | |
213 static int idcin_decode_frame(AVCodecContext *avctx, | |
214 void *data, int *data_size, | |
215 uint8_t *buf, int buf_size) | |
216 { | |
4827 | 217 IdcinContext *s = avctx->priv_data; |
1585
6b224ca24033
revised palette API, courtesy of Roberto Togni (rtogni at freemail.it)
melanson
parents:
1499
diff
changeset
|
218 AVPaletteControl *palette_control = avctx->palctrl; |
1498 | 219 |
220 s->buf = buf; | |
221 s->size = buf_size; | |
222 | |
223 if (s->frame.data[0]) | |
224 avctx->release_buffer(avctx, &s->frame); | |
225 | |
226 if (avctx->get_buffer(avctx, &s->frame)) { | |
1598
932d306bf1dc
av_log() patch by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michael
parents:
1585
diff
changeset
|
227 av_log(avctx, AV_LOG_ERROR, " Id CIN Video: get_buffer() failed\n"); |
1498 | 228 return -1; |
229 } | |
230 | |
231 idcin_decode_vlcs(s); | |
232 | |
233 /* make the palette available on the way out */ | |
1585
6b224ca24033
revised palette API, courtesy of Roberto Togni (rtogni at freemail.it)
melanson
parents:
1499
diff
changeset
|
234 memcpy(s->frame.data[1], palette_control->palette, PALETTE_COUNT * 4); |
6b224ca24033
revised palette API, courtesy of Roberto Togni (rtogni at freemail.it)
melanson
parents:
1499
diff
changeset
|
235 /* If palette changed inform application*/ |
6b224ca24033
revised palette API, courtesy of Roberto Togni (rtogni at freemail.it)
melanson
parents:
1499
diff
changeset
|
236 if (palette_control->palette_changed) { |
6b224ca24033
revised palette API, courtesy of Roberto Togni (rtogni at freemail.it)
melanson
parents:
1499
diff
changeset
|
237 palette_control->palette_changed = 0; |
6b224ca24033
revised palette API, courtesy of Roberto Togni (rtogni at freemail.it)
melanson
parents:
1499
diff
changeset
|
238 s->frame.palette_has_changed = 1; |
6b224ca24033
revised palette API, courtesy of Roberto Togni (rtogni at freemail.it)
melanson
parents:
1499
diff
changeset
|
239 } |
1498 | 240 |
241 *data_size = sizeof(AVFrame); | |
242 *(AVFrame*)data = s->frame; | |
243 | |
244 /* report that the buffer was completely consumed */ | |
245 return buf_size; | |
246 } | |
247 | |
248 static int idcin_decode_end(AVCodecContext *avctx) | |
249 { | |
4827 | 250 IdcinContext *s = avctx->priv_data; |
1498 | 251 |
252 if (s->frame.data[0]) | |
253 avctx->release_buffer(avctx, &s->frame); | |
254 | |
255 return 0; | |
256 } | |
257 | |
258 AVCodec idcin_decoder = { | |
259 "idcinvideo", | |
260 CODEC_TYPE_VIDEO, | |
261 CODEC_ID_IDCIN, | |
262 sizeof(IdcinContext), | |
263 idcin_decode_init, | |
264 NULL, | |
265 idcin_decode_end, | |
266 idcin_decode_frame, | |
267 CODEC_CAP_DR1, | |
268 }; | |
269 |