Mercurial > libavcodec.hg
annotate idcinvideo.c @ 2497:69adfbbdcdeb libavcodec
- samples from mplayer ftp in the "adv" profile seem to have profile=2,
which isn't the advanced one; and indeed, using adv. profile parser fails.
Using normal parser works, and that's what is done
- attempt at taking care of stride for NORM2 bitplane decoding
- duplication of much code from msmpeg4.c; this code isn't yet used, but
goes down as far as the block layer (mainly Transform Type stuff, the
remains are wild editing without checking). Unusable yet, and lacks the AC
decoding (but a step further in bitstream parsing)
patch by anonymous
author | michael |
---|---|
date | Fri, 04 Feb 2005 02:20:38 +0000 |
parents | 932d306bf1dc |
children | b0ec6f51b5bd |
rev | line source |
---|---|
1498 | 1 /* |
2 * Id Quake II CIN Video Decoder | |
3 * Copyright (C) 2003 the ffmpeg project | |
4 * | |
5 * This library is free software; you can redistribute it and/or | |
6 * modify it under the terms of the GNU Lesser General Public | |
7 * License as published by the Free Software Foundation; either | |
8 * version 2 of the License, or (at your option) any later version. | |
9 * | |
10 * This library is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 * Lesser General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU Lesser General Public | |
16 * License along with this library; if not, write to the Free Software | |
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 * | |
19 */ | |
20 | |
21 /** | |
22 * @file idcinvideo.c | |
23 * Id Quake II Cin Video Decoder by Dr. Tim Ferguson | |
24 * For more information about the Id CIN format, visit: | |
25 * http://www.csse.monash.edu.au/~timf/ | |
26 * | |
1499 | 27 * This video decoder outputs PAL8 colorspace data. Interacting with this |
28 * decoder is a little involved. During initialization, the demuxer must | |
29 * transmit the 65536-byte Huffman table(s) to the decoder via extradata. | |
30 * Then, whenever a palette change is encountered while demuxing the file, | |
31 * the demuxer must use the same extradata space to transmit an | |
32 * AVPaletteControl structure. | |
1498 | 33 * |
34 * Id CIN video is purely Huffman-coded, intraframe-only codec. It achieves | |
35 * a little more compression by exploiting the fact that adjacent pixels | |
36 * tend to be similar. | |
37 * | |
38 * Note that this decoder could use ffmpeg's optimized VLC facilities | |
39 * rather than naive, tree-based Huffman decoding. However, there are 256 | |
40 * Huffman tables. Plus, the VLC bit coding order is right -> left instead | |
41 * or left -> right, so all of the bits would have to be reversed. Further, | |
42 * the original Quake II implementation likely used a similar naive | |
43 * decoding algorithm and it worked fine on much lower spec machines. | |
44 */ | |
45 | |
46 #include <stdio.h> | |
47 #include <stdlib.h> | |
48 #include <string.h> | |
49 #include <unistd.h> | |
50 | |
51 #include "common.h" | |
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 { | |
150 IdcinContext *s = (IdcinContext *)avctx->priv_data; | |
151 int i, j, histogram_index = 0; | |
152 unsigned char *histograms; | |
153 | |
154 s->avctx = avctx; | |
155 avctx->pix_fmt = PIX_FMT_PAL8; | |
156 avctx->has_b_frames = 0; | |
157 dsputil_init(&s->dsp, avctx); | |
158 | |
159 /* make sure the Huffman tables make it */ | |
160 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
|
161 av_log(s->avctx, AV_LOG_ERROR, " Id CIN video: expected extradata size of %d\n", HUFFMAN_TABLE_SIZE); |
1498 | 162 return -1; |
163 } | |
164 | |
165 /* build the 256 Huffman decode trees */ | |
166 histograms = (unsigned char *)s->avctx->extradata; | |
167 for (i = 0; i < 256; i++) { | |
168 for(j = 0; j < HUF_TOKENS; j++) | |
169 s->huff_nodes[i][j].count = histograms[histogram_index++]; | |
170 huff_build_tree(s, i); | |
171 } | |
172 | |
173 s->frame.data[0] = NULL; | |
174 | |
175 return 0; | |
176 } | |
177 | |
178 static void idcin_decode_vlcs(IdcinContext *s) | |
179 { | |
180 hnode_t *hnodes; | |
181 long x, y; | |
182 int prev; | |
183 unsigned char v = 0; | |
184 int bit_pos, node_num, dat_pos; | |
185 | |
186 prev = bit_pos = dat_pos = 0; | |
187 for (y = 0; y < (s->frame.linesize[0] * s->avctx->height); | |
188 y += s->frame.linesize[0]) { | |
189 for (x = y; x < y + s->avctx->width; x++) { | |
190 node_num = s->num_huff_nodes[prev]; | |
191 hnodes = s->huff_nodes[prev]; | |
192 | |
193 while(node_num >= HUF_TOKENS) { | |
194 if(!bit_pos) { | |
195 if(dat_pos > s->size) { | |
1598
932d306bf1dc
av_log() patch by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michael
parents:
1585
diff
changeset
|
196 av_log(s->avctx, AV_LOG_ERROR, "Huffman decode error.\n"); |
1498 | 197 return; |
198 } | |
199 bit_pos = 8; | |
200 v = s->buf[dat_pos++]; | |
201 } | |
202 | |
203 node_num = hnodes[node_num].children[v & 0x01]; | |
204 v = v >> 1; | |
205 bit_pos--; | |
206 } | |
207 | |
208 s->frame.data[0][x] = node_num; | |
209 prev = node_num; | |
210 } | |
211 } | |
212 } | |
213 | |
214 static int idcin_decode_frame(AVCodecContext *avctx, | |
215 void *data, int *data_size, | |
216 uint8_t *buf, int buf_size) | |
217 { | |
218 IdcinContext *s = (IdcinContext *)avctx->priv_data; | |
1585
6b224ca24033
revised palette API, courtesy of Roberto Togni (rtogni at freemail.it)
melanson
parents:
1499
diff
changeset
|
219 AVPaletteControl *palette_control = avctx->palctrl; |
1498 | 220 |
221 s->buf = buf; | |
222 s->size = buf_size; | |
223 | |
224 if (s->frame.data[0]) | |
225 avctx->release_buffer(avctx, &s->frame); | |
226 | |
227 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
|
228 av_log(avctx, AV_LOG_ERROR, " Id CIN Video: get_buffer() failed\n"); |
1498 | 229 return -1; |
230 } | |
231 | |
232 idcin_decode_vlcs(s); | |
233 | |
234 /* 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
|
235 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
|
236 /* If palette changed inform application*/ |
6b224ca24033
revised palette API, courtesy of Roberto Togni (rtogni at freemail.it)
melanson
parents:
1499
diff
changeset
|
237 if (palette_control->palette_changed) { |
6b224ca24033
revised palette API, courtesy of Roberto Togni (rtogni at freemail.it)
melanson
parents:
1499
diff
changeset
|
238 palette_control->palette_changed = 0; |
6b224ca24033
revised palette API, courtesy of Roberto Togni (rtogni at freemail.it)
melanson
parents:
1499
diff
changeset
|
239 s->frame.palette_has_changed = 1; |
6b224ca24033
revised palette API, courtesy of Roberto Togni (rtogni at freemail.it)
melanson
parents:
1499
diff
changeset
|
240 } |
1498 | 241 |
242 *data_size = sizeof(AVFrame); | |
243 *(AVFrame*)data = s->frame; | |
244 | |
245 /* report that the buffer was completely consumed */ | |
246 return buf_size; | |
247 } | |
248 | |
249 static int idcin_decode_end(AVCodecContext *avctx) | |
250 { | |
251 IdcinContext *s = (IdcinContext *)avctx->priv_data; | |
252 | |
253 if (s->frame.data[0]) | |
254 avctx->release_buffer(avctx, &s->frame); | |
255 | |
256 return 0; | |
257 } | |
258 | |
259 AVCodec idcin_decoder = { | |
260 "idcinvideo", | |
261 CODEC_TYPE_VIDEO, | |
262 CODEC_ID_IDCIN, | |
263 sizeof(IdcinContext), | |
264 idcin_decode_init, | |
265 NULL, | |
266 idcin_decode_end, | |
267 idcin_decode_frame, | |
268 CODEC_CAP_DR1, | |
269 }; | |
270 |