yading@10
|
1 /*
|
yading@10
|
2 * Quicktime Graphics (SMC) Video Decoder
|
yading@10
|
3 * Copyright (C) 2003 the ffmpeg project
|
yading@10
|
4 *
|
yading@10
|
5 * This file is part of FFmpeg.
|
yading@10
|
6 *
|
yading@10
|
7 * FFmpeg is free software; you can redistribute it and/or
|
yading@10
|
8 * modify it under the terms of the GNU Lesser General Public
|
yading@10
|
9 * License as published by the Free Software Foundation; either
|
yading@10
|
10 * version 2.1 of the License, or (at your option) any later version.
|
yading@10
|
11 *
|
yading@10
|
12 * FFmpeg is distributed in the hope that it will be useful,
|
yading@10
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
yading@10
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
yading@10
|
15 * Lesser General Public License for more details.
|
yading@10
|
16 *
|
yading@10
|
17 * You should have received a copy of the GNU Lesser General Public
|
yading@10
|
18 * License along with FFmpeg; if not, write to the Free Software
|
yading@10
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
yading@10
|
20 */
|
yading@10
|
21
|
yading@10
|
22 /**
|
yading@10
|
23 * @file
|
yading@10
|
24 * QT SMC Video Decoder by Mike Melanson (melanson@pcisys.net)
|
yading@10
|
25 * For more information about the SMC format, visit:
|
yading@10
|
26 * http://www.pcisys.net/~melanson/codecs/
|
yading@10
|
27 *
|
yading@10
|
28 * The SMC decoder outputs PAL8 colorspace data.
|
yading@10
|
29 */
|
yading@10
|
30
|
yading@10
|
31 #include <stdio.h>
|
yading@10
|
32 #include <stdlib.h>
|
yading@10
|
33 #include <string.h>
|
yading@10
|
34
|
yading@10
|
35 #include "libavutil/intreadwrite.h"
|
yading@10
|
36 #include "avcodec.h"
|
yading@10
|
37 #include "bytestream.h"
|
yading@10
|
38 #include "internal.h"
|
yading@10
|
39
|
yading@10
|
40 #define CPAIR 2
|
yading@10
|
41 #define CQUAD 4
|
yading@10
|
42 #define COCTET 8
|
yading@10
|
43
|
yading@10
|
44 #define COLORS_PER_TABLE 256
|
yading@10
|
45
|
yading@10
|
46 typedef struct SmcContext {
|
yading@10
|
47
|
yading@10
|
48 AVCodecContext *avctx;
|
yading@10
|
49 AVFrame frame;
|
yading@10
|
50
|
yading@10
|
51 GetByteContext gb;
|
yading@10
|
52
|
yading@10
|
53 /* SMC color tables */
|
yading@10
|
54 unsigned char color_pairs[COLORS_PER_TABLE * CPAIR];
|
yading@10
|
55 unsigned char color_quads[COLORS_PER_TABLE * CQUAD];
|
yading@10
|
56 unsigned char color_octets[COLORS_PER_TABLE * COCTET];
|
yading@10
|
57
|
yading@10
|
58 uint32_t pal[256];
|
yading@10
|
59 } SmcContext;
|
yading@10
|
60
|
yading@10
|
61 #define GET_BLOCK_COUNT() \
|
yading@10
|
62 (opcode & 0x10) ? (1 + bytestream2_get_byte(&s->gb)) : 1 + (opcode & 0x0F);
|
yading@10
|
63
|
yading@10
|
64 #define ADVANCE_BLOCK() \
|
yading@10
|
65 { \
|
yading@10
|
66 pixel_ptr += 4; \
|
yading@10
|
67 if (pixel_ptr >= width) \
|
yading@10
|
68 { \
|
yading@10
|
69 pixel_ptr = 0; \
|
yading@10
|
70 row_ptr += stride * 4; \
|
yading@10
|
71 } \
|
yading@10
|
72 total_blocks--; \
|
yading@10
|
73 if (total_blocks < 0) \
|
yading@10
|
74 { \
|
yading@10
|
75 av_log(s->avctx, AV_LOG_INFO, "warning: block counter just went negative (this should not happen)\n"); \
|
yading@10
|
76 return; \
|
yading@10
|
77 } \
|
yading@10
|
78 }
|
yading@10
|
79
|
yading@10
|
80 static void smc_decode_stream(SmcContext *s)
|
yading@10
|
81 {
|
yading@10
|
82 int width = s->avctx->width;
|
yading@10
|
83 int height = s->avctx->height;
|
yading@10
|
84 int stride = s->frame.linesize[0];
|
yading@10
|
85 int i;
|
yading@10
|
86 int chunk_size;
|
yading@10
|
87 int buf_size = bytestream2_size(&s->gb);
|
yading@10
|
88 unsigned char opcode;
|
yading@10
|
89 int n_blocks;
|
yading@10
|
90 unsigned int color_flags;
|
yading@10
|
91 unsigned int color_flags_a;
|
yading@10
|
92 unsigned int color_flags_b;
|
yading@10
|
93 unsigned int flag_mask;
|
yading@10
|
94
|
yading@10
|
95 unsigned char *pixels = s->frame.data[0];
|
yading@10
|
96
|
yading@10
|
97 int image_size = height * s->frame.linesize[0];
|
yading@10
|
98 int row_ptr = 0;
|
yading@10
|
99 int pixel_ptr = 0;
|
yading@10
|
100 int pixel_x, pixel_y;
|
yading@10
|
101 int row_inc = stride - 4;
|
yading@10
|
102 int block_ptr;
|
yading@10
|
103 int prev_block_ptr;
|
yading@10
|
104 int prev_block_ptr1, prev_block_ptr2;
|
yading@10
|
105 int prev_block_flag;
|
yading@10
|
106 int total_blocks;
|
yading@10
|
107 int color_table_index; /* indexes to color pair, quad, or octet tables */
|
yading@10
|
108 int pixel;
|
yading@10
|
109
|
yading@10
|
110 int color_pair_index = 0;
|
yading@10
|
111 int color_quad_index = 0;
|
yading@10
|
112 int color_octet_index = 0;
|
yading@10
|
113
|
yading@10
|
114 /* make the palette available */
|
yading@10
|
115 memcpy(s->frame.data[1], s->pal, AVPALETTE_SIZE);
|
yading@10
|
116
|
yading@10
|
117 bytestream2_skip(&s->gb, 1);
|
yading@10
|
118 chunk_size = bytestream2_get_be24(&s->gb);
|
yading@10
|
119 if (chunk_size != buf_size)
|
yading@10
|
120 av_log(s->avctx, AV_LOG_INFO, "warning: MOV chunk size != encoded chunk size (%d != %d); using MOV chunk size\n",
|
yading@10
|
121 chunk_size, buf_size);
|
yading@10
|
122
|
yading@10
|
123 chunk_size = buf_size;
|
yading@10
|
124 total_blocks = ((s->avctx->width + 3) / 4) * ((s->avctx->height + 3) / 4);
|
yading@10
|
125
|
yading@10
|
126 /* traverse through the blocks */
|
yading@10
|
127 while (total_blocks) {
|
yading@10
|
128 /* sanity checks */
|
yading@10
|
129 /* make sure the row pointer hasn't gone wild */
|
yading@10
|
130 if (row_ptr >= image_size) {
|
yading@10
|
131 av_log(s->avctx, AV_LOG_INFO, "SMC decoder just went out of bounds (row ptr = %d, height = %d)\n",
|
yading@10
|
132 row_ptr, image_size);
|
yading@10
|
133 return;
|
yading@10
|
134 }
|
yading@10
|
135
|
yading@10
|
136 opcode = bytestream2_get_byte(&s->gb);
|
yading@10
|
137 switch (opcode & 0xF0) {
|
yading@10
|
138 /* skip n blocks */
|
yading@10
|
139 case 0x00:
|
yading@10
|
140 case 0x10:
|
yading@10
|
141 n_blocks = GET_BLOCK_COUNT();
|
yading@10
|
142 while (n_blocks--) {
|
yading@10
|
143 ADVANCE_BLOCK();
|
yading@10
|
144 }
|
yading@10
|
145 break;
|
yading@10
|
146
|
yading@10
|
147 /* repeat last block n times */
|
yading@10
|
148 case 0x20:
|
yading@10
|
149 case 0x30:
|
yading@10
|
150 n_blocks = GET_BLOCK_COUNT();
|
yading@10
|
151
|
yading@10
|
152 /* sanity check */
|
yading@10
|
153 if ((row_ptr == 0) && (pixel_ptr == 0)) {
|
yading@10
|
154 av_log(s->avctx, AV_LOG_INFO, "encountered repeat block opcode (%02X) but no blocks rendered yet\n",
|
yading@10
|
155 opcode & 0xF0);
|
yading@10
|
156 return;
|
yading@10
|
157 }
|
yading@10
|
158
|
yading@10
|
159 /* figure out where the previous block started */
|
yading@10
|
160 if (pixel_ptr == 0)
|
yading@10
|
161 prev_block_ptr1 =
|
yading@10
|
162 (row_ptr - s->avctx->width * 4) + s->avctx->width - 4;
|
yading@10
|
163 else
|
yading@10
|
164 prev_block_ptr1 = row_ptr + pixel_ptr - 4;
|
yading@10
|
165
|
yading@10
|
166 while (n_blocks--) {
|
yading@10
|
167 block_ptr = row_ptr + pixel_ptr;
|
yading@10
|
168 prev_block_ptr = prev_block_ptr1;
|
yading@10
|
169 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
|
yading@10
|
170 for (pixel_x = 0; pixel_x < 4; pixel_x++) {
|
yading@10
|
171 pixels[block_ptr++] = pixels[prev_block_ptr++];
|
yading@10
|
172 }
|
yading@10
|
173 block_ptr += row_inc;
|
yading@10
|
174 prev_block_ptr += row_inc;
|
yading@10
|
175 }
|
yading@10
|
176 ADVANCE_BLOCK();
|
yading@10
|
177 }
|
yading@10
|
178 break;
|
yading@10
|
179
|
yading@10
|
180 /* repeat previous pair of blocks n times */
|
yading@10
|
181 case 0x40:
|
yading@10
|
182 case 0x50:
|
yading@10
|
183 n_blocks = GET_BLOCK_COUNT();
|
yading@10
|
184 n_blocks *= 2;
|
yading@10
|
185
|
yading@10
|
186 /* sanity check */
|
yading@10
|
187 if ((row_ptr == 0) && (pixel_ptr < 2 * 4)) {
|
yading@10
|
188 av_log(s->avctx, AV_LOG_INFO, "encountered repeat block opcode (%02X) but not enough blocks rendered yet\n",
|
yading@10
|
189 opcode & 0xF0);
|
yading@10
|
190 return;
|
yading@10
|
191 }
|
yading@10
|
192
|
yading@10
|
193 /* figure out where the previous 2 blocks started */
|
yading@10
|
194 if (pixel_ptr == 0)
|
yading@10
|
195 prev_block_ptr1 = (row_ptr - s->avctx->width * 4) +
|
yading@10
|
196 s->avctx->width - 4 * 2;
|
yading@10
|
197 else if (pixel_ptr == 4)
|
yading@10
|
198 prev_block_ptr1 = (row_ptr - s->avctx->width * 4) + row_inc;
|
yading@10
|
199 else
|
yading@10
|
200 prev_block_ptr1 = row_ptr + pixel_ptr - 4 * 2;
|
yading@10
|
201
|
yading@10
|
202 if (pixel_ptr == 0)
|
yading@10
|
203 prev_block_ptr2 = (row_ptr - s->avctx->width * 4) + row_inc;
|
yading@10
|
204 else
|
yading@10
|
205 prev_block_ptr2 = row_ptr + pixel_ptr - 4;
|
yading@10
|
206
|
yading@10
|
207 prev_block_flag = 0;
|
yading@10
|
208 while (n_blocks--) {
|
yading@10
|
209 block_ptr = row_ptr + pixel_ptr;
|
yading@10
|
210 if (prev_block_flag)
|
yading@10
|
211 prev_block_ptr = prev_block_ptr2;
|
yading@10
|
212 else
|
yading@10
|
213 prev_block_ptr = prev_block_ptr1;
|
yading@10
|
214 prev_block_flag = !prev_block_flag;
|
yading@10
|
215
|
yading@10
|
216 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
|
yading@10
|
217 for (pixel_x = 0; pixel_x < 4; pixel_x++) {
|
yading@10
|
218 pixels[block_ptr++] = pixels[prev_block_ptr++];
|
yading@10
|
219 }
|
yading@10
|
220 block_ptr += row_inc;
|
yading@10
|
221 prev_block_ptr += row_inc;
|
yading@10
|
222 }
|
yading@10
|
223 ADVANCE_BLOCK();
|
yading@10
|
224 }
|
yading@10
|
225 break;
|
yading@10
|
226
|
yading@10
|
227 /* 1-color block encoding */
|
yading@10
|
228 case 0x60:
|
yading@10
|
229 case 0x70:
|
yading@10
|
230 n_blocks = GET_BLOCK_COUNT();
|
yading@10
|
231 pixel = bytestream2_get_byte(&s->gb);
|
yading@10
|
232
|
yading@10
|
233 while (n_blocks--) {
|
yading@10
|
234 block_ptr = row_ptr + pixel_ptr;
|
yading@10
|
235 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
|
yading@10
|
236 for (pixel_x = 0; pixel_x < 4; pixel_x++) {
|
yading@10
|
237 pixels[block_ptr++] = pixel;
|
yading@10
|
238 }
|
yading@10
|
239 block_ptr += row_inc;
|
yading@10
|
240 }
|
yading@10
|
241 ADVANCE_BLOCK();
|
yading@10
|
242 }
|
yading@10
|
243 break;
|
yading@10
|
244
|
yading@10
|
245 /* 2-color block encoding */
|
yading@10
|
246 case 0x80:
|
yading@10
|
247 case 0x90:
|
yading@10
|
248 n_blocks = (opcode & 0x0F) + 1;
|
yading@10
|
249
|
yading@10
|
250 /* figure out which color pair to use to paint the 2-color block */
|
yading@10
|
251 if ((opcode & 0xF0) == 0x80) {
|
yading@10
|
252 /* fetch the next 2 colors from bytestream and store in next
|
yading@10
|
253 * available entry in the color pair table */
|
yading@10
|
254 for (i = 0; i < CPAIR; i++) {
|
yading@10
|
255 pixel = bytestream2_get_byte(&s->gb);
|
yading@10
|
256 color_table_index = CPAIR * color_pair_index + i;
|
yading@10
|
257 s->color_pairs[color_table_index] = pixel;
|
yading@10
|
258 }
|
yading@10
|
259 /* this is the base index to use for this block */
|
yading@10
|
260 color_table_index = CPAIR * color_pair_index;
|
yading@10
|
261 color_pair_index++;
|
yading@10
|
262 /* wraparound */
|
yading@10
|
263 if (color_pair_index == COLORS_PER_TABLE)
|
yading@10
|
264 color_pair_index = 0;
|
yading@10
|
265 } else
|
yading@10
|
266 color_table_index = CPAIR * bytestream2_get_byte(&s->gb);
|
yading@10
|
267
|
yading@10
|
268 while (n_blocks--) {
|
yading@10
|
269 color_flags = bytestream2_get_be16(&s->gb);
|
yading@10
|
270 flag_mask = 0x8000;
|
yading@10
|
271 block_ptr = row_ptr + pixel_ptr;
|
yading@10
|
272 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
|
yading@10
|
273 for (pixel_x = 0; pixel_x < 4; pixel_x++) {
|
yading@10
|
274 if (color_flags & flag_mask)
|
yading@10
|
275 pixel = color_table_index + 1;
|
yading@10
|
276 else
|
yading@10
|
277 pixel = color_table_index;
|
yading@10
|
278 flag_mask >>= 1;
|
yading@10
|
279 pixels[block_ptr++] = s->color_pairs[pixel];
|
yading@10
|
280 }
|
yading@10
|
281 block_ptr += row_inc;
|
yading@10
|
282 }
|
yading@10
|
283 ADVANCE_BLOCK();
|
yading@10
|
284 }
|
yading@10
|
285 break;
|
yading@10
|
286
|
yading@10
|
287 /* 4-color block encoding */
|
yading@10
|
288 case 0xA0:
|
yading@10
|
289 case 0xB0:
|
yading@10
|
290 n_blocks = (opcode & 0x0F) + 1;
|
yading@10
|
291
|
yading@10
|
292 /* figure out which color quad to use to paint the 4-color block */
|
yading@10
|
293 if ((opcode & 0xF0) == 0xA0) {
|
yading@10
|
294 /* fetch the next 4 colors from bytestream and store in next
|
yading@10
|
295 * available entry in the color quad table */
|
yading@10
|
296 for (i = 0; i < CQUAD; i++) {
|
yading@10
|
297 pixel = bytestream2_get_byte(&s->gb);
|
yading@10
|
298 color_table_index = CQUAD * color_quad_index + i;
|
yading@10
|
299 s->color_quads[color_table_index] = pixel;
|
yading@10
|
300 }
|
yading@10
|
301 /* this is the base index to use for this block */
|
yading@10
|
302 color_table_index = CQUAD * color_quad_index;
|
yading@10
|
303 color_quad_index++;
|
yading@10
|
304 /* wraparound */
|
yading@10
|
305 if (color_quad_index == COLORS_PER_TABLE)
|
yading@10
|
306 color_quad_index = 0;
|
yading@10
|
307 } else
|
yading@10
|
308 color_table_index = CQUAD * bytestream2_get_byte(&s->gb);
|
yading@10
|
309
|
yading@10
|
310 while (n_blocks--) {
|
yading@10
|
311 color_flags = bytestream2_get_be32(&s->gb);
|
yading@10
|
312 /* flag mask actually acts as a bit shift count here */
|
yading@10
|
313 flag_mask = 30;
|
yading@10
|
314 block_ptr = row_ptr + pixel_ptr;
|
yading@10
|
315 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
|
yading@10
|
316 for (pixel_x = 0; pixel_x < 4; pixel_x++) {
|
yading@10
|
317 pixel = color_table_index +
|
yading@10
|
318 ((color_flags >> flag_mask) & 0x03);
|
yading@10
|
319 flag_mask -= 2;
|
yading@10
|
320 pixels[block_ptr++] = s->color_quads[pixel];
|
yading@10
|
321 }
|
yading@10
|
322 block_ptr += row_inc;
|
yading@10
|
323 }
|
yading@10
|
324 ADVANCE_BLOCK();
|
yading@10
|
325 }
|
yading@10
|
326 break;
|
yading@10
|
327
|
yading@10
|
328 /* 8-color block encoding */
|
yading@10
|
329 case 0xC0:
|
yading@10
|
330 case 0xD0:
|
yading@10
|
331 n_blocks = (opcode & 0x0F) + 1;
|
yading@10
|
332
|
yading@10
|
333 /* figure out which color octet to use to paint the 8-color block */
|
yading@10
|
334 if ((opcode & 0xF0) == 0xC0) {
|
yading@10
|
335 /* fetch the next 8 colors from bytestream and store in next
|
yading@10
|
336 * available entry in the color octet table */
|
yading@10
|
337 for (i = 0; i < COCTET; i++) {
|
yading@10
|
338 pixel = bytestream2_get_byte(&s->gb);
|
yading@10
|
339 color_table_index = COCTET * color_octet_index + i;
|
yading@10
|
340 s->color_octets[color_table_index] = pixel;
|
yading@10
|
341 }
|
yading@10
|
342 /* this is the base index to use for this block */
|
yading@10
|
343 color_table_index = COCTET * color_octet_index;
|
yading@10
|
344 color_octet_index++;
|
yading@10
|
345 /* wraparound */
|
yading@10
|
346 if (color_octet_index == COLORS_PER_TABLE)
|
yading@10
|
347 color_octet_index = 0;
|
yading@10
|
348 } else
|
yading@10
|
349 color_table_index = COCTET * bytestream2_get_byte(&s->gb);
|
yading@10
|
350
|
yading@10
|
351 while (n_blocks--) {
|
yading@10
|
352 /*
|
yading@10
|
353 For this input of 6 hex bytes:
|
yading@10
|
354 01 23 45 67 89 AB
|
yading@10
|
355 Mangle it to this output:
|
yading@10
|
356 flags_a = xx012456, flags_b = xx89A37B
|
yading@10
|
357 */
|
yading@10
|
358 /* build the color flags */
|
yading@10
|
359 int val1 = bytestream2_get_be16(&s->gb);
|
yading@10
|
360 int val2 = bytestream2_get_be16(&s->gb);
|
yading@10
|
361 int val3 = bytestream2_get_be16(&s->gb);
|
yading@10
|
362 color_flags_a = ((val1 & 0xFFF0) << 8) | (val2 >> 4);
|
yading@10
|
363 color_flags_b = ((val3 & 0xFFF0) << 8) |
|
yading@10
|
364 ((val1 & 0x0F) << 8) | ((val2 & 0x0F) << 4) | (val3 & 0x0F);
|
yading@10
|
365
|
yading@10
|
366 color_flags = color_flags_a;
|
yading@10
|
367 /* flag mask actually acts as a bit shift count here */
|
yading@10
|
368 flag_mask = 21;
|
yading@10
|
369 block_ptr = row_ptr + pixel_ptr;
|
yading@10
|
370 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
|
yading@10
|
371 /* reload flags at third row (iteration pixel_y == 2) */
|
yading@10
|
372 if (pixel_y == 2) {
|
yading@10
|
373 color_flags = color_flags_b;
|
yading@10
|
374 flag_mask = 21;
|
yading@10
|
375 }
|
yading@10
|
376 for (pixel_x = 0; pixel_x < 4; pixel_x++) {
|
yading@10
|
377 pixel = color_table_index +
|
yading@10
|
378 ((color_flags >> flag_mask) & 0x07);
|
yading@10
|
379 flag_mask -= 3;
|
yading@10
|
380 pixels[block_ptr++] = s->color_octets[pixel];
|
yading@10
|
381 }
|
yading@10
|
382 block_ptr += row_inc;
|
yading@10
|
383 }
|
yading@10
|
384 ADVANCE_BLOCK();
|
yading@10
|
385 }
|
yading@10
|
386 break;
|
yading@10
|
387
|
yading@10
|
388 /* 16-color block encoding (every pixel is a different color) */
|
yading@10
|
389 case 0xE0:
|
yading@10
|
390 n_blocks = (opcode & 0x0F) + 1;
|
yading@10
|
391
|
yading@10
|
392 while (n_blocks--) {
|
yading@10
|
393 block_ptr = row_ptr + pixel_ptr;
|
yading@10
|
394 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
|
yading@10
|
395 for (pixel_x = 0; pixel_x < 4; pixel_x++) {
|
yading@10
|
396 pixels[block_ptr++] = bytestream2_get_byte(&s->gb);
|
yading@10
|
397 }
|
yading@10
|
398 block_ptr += row_inc;
|
yading@10
|
399 }
|
yading@10
|
400 ADVANCE_BLOCK();
|
yading@10
|
401 }
|
yading@10
|
402 break;
|
yading@10
|
403
|
yading@10
|
404 case 0xF0:
|
yading@10
|
405 avpriv_request_sample(s->avctx, "0xF0 opcode");
|
yading@10
|
406 break;
|
yading@10
|
407 }
|
yading@10
|
408 }
|
yading@10
|
409
|
yading@10
|
410 return;
|
yading@10
|
411 }
|
yading@10
|
412
|
yading@10
|
413 static av_cold int smc_decode_init(AVCodecContext *avctx)
|
yading@10
|
414 {
|
yading@10
|
415 SmcContext *s = avctx->priv_data;
|
yading@10
|
416
|
yading@10
|
417 s->avctx = avctx;
|
yading@10
|
418 avctx->pix_fmt = AV_PIX_FMT_PAL8;
|
yading@10
|
419
|
yading@10
|
420 avcodec_get_frame_defaults(&s->frame);
|
yading@10
|
421
|
yading@10
|
422 return 0;
|
yading@10
|
423 }
|
yading@10
|
424
|
yading@10
|
425 static int smc_decode_frame(AVCodecContext *avctx,
|
yading@10
|
426 void *data, int *got_frame,
|
yading@10
|
427 AVPacket *avpkt)
|
yading@10
|
428 {
|
yading@10
|
429 const uint8_t *buf = avpkt->data;
|
yading@10
|
430 int buf_size = avpkt->size;
|
yading@10
|
431 SmcContext *s = avctx->priv_data;
|
yading@10
|
432 const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, NULL);
|
yading@10
|
433 int ret;
|
yading@10
|
434
|
yading@10
|
435 bytestream2_init(&s->gb, buf, buf_size);
|
yading@10
|
436
|
yading@10
|
437 if ((ret = ff_reget_buffer(avctx, &s->frame)) < 0)
|
yading@10
|
438 return ret;
|
yading@10
|
439
|
yading@10
|
440 if (pal) {
|
yading@10
|
441 s->frame.palette_has_changed = 1;
|
yading@10
|
442 memcpy(s->pal, pal, AVPALETTE_SIZE);
|
yading@10
|
443 }
|
yading@10
|
444
|
yading@10
|
445 smc_decode_stream(s);
|
yading@10
|
446
|
yading@10
|
447 *got_frame = 1;
|
yading@10
|
448 if ((ret = av_frame_ref(data, &s->frame)) < 0)
|
yading@10
|
449 return ret;
|
yading@10
|
450
|
yading@10
|
451 /* always report that the buffer was completely consumed */
|
yading@10
|
452 return buf_size;
|
yading@10
|
453 }
|
yading@10
|
454
|
yading@10
|
455 static av_cold int smc_decode_end(AVCodecContext *avctx)
|
yading@10
|
456 {
|
yading@10
|
457 SmcContext *s = avctx->priv_data;
|
yading@10
|
458
|
yading@10
|
459 av_frame_unref(&s->frame);
|
yading@10
|
460
|
yading@10
|
461 return 0;
|
yading@10
|
462 }
|
yading@10
|
463
|
yading@10
|
464 AVCodec ff_smc_decoder = {
|
yading@10
|
465 .name = "smc",
|
yading@10
|
466 .type = AVMEDIA_TYPE_VIDEO,
|
yading@10
|
467 .id = AV_CODEC_ID_SMC,
|
yading@10
|
468 .priv_data_size = sizeof(SmcContext),
|
yading@10
|
469 .init = smc_decode_init,
|
yading@10
|
470 .close = smc_decode_end,
|
yading@10
|
471 .decode = smc_decode_frame,
|
yading@10
|
472 .capabilities = CODEC_CAP_DR1,
|
yading@10
|
473 .long_name = NULL_IF_CONFIG_SMALL("QuickTime Graphics (SMC)"),
|
yading@10
|
474 };
|