VirtualBox

source: vbox/trunk/src/libs/ffmpeg-20060710/libavcodec/vmdav.c@ 10516

最後變更 在這個檔案從10516是 5776,由 vboxsync 提交於 17 年 前

ffmpeg: exported to OSE

檔案大小: 16.8 KB
 
1/*
2 * Sierra VMD Audio & Video Decoders
3 * Copyright (C) 2004 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 */
20
21/**
22 * @file vmdvideo.c
23 * Sierra VMD audio & video decoders
24 * by Vladimir "VAG" Gneushev (vagsoft at mail.ru)
25 * for more information on the Sierra VMD format, visit:
26 * http://www.pcisys.net/~melanson/codecs/
27 *
28 * The video decoder outputs PAL8 colorspace data. The decoder expects
29 * a 0x330-byte VMD file header to be transmitted via extradata during
30 * codec initialization. Each encoded frame that is sent to this decoder
31 * is expected to be prepended with the appropriate 16-byte frame
32 * information record from the VMD file.
33 *
34 * The audio decoder, like the video decoder, expects each encoded data
35 * chunk to be prepended with the appropriate 16-byte frame information
36 * record from the VMD file. It does not require the 0x330-byte VMD file
37 * header, but it does need the audio setup parameters passed in through
38 * normal libavcodec API means.
39 */
40
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44#include <unistd.h>
45
46#include "common.h"
47#include "avcodec.h"
48#include "dsputil.h"
49
50#define VMD_HEADER_SIZE 0x330
51#define PALETTE_COUNT 256
52
53/*
54 * Video Decoder
55 */
56
57typedef struct VmdVideoContext {
58
59 AVCodecContext *avctx;
60 DSPContext dsp;
61 AVFrame frame;
62 AVFrame prev_frame;
63
64 unsigned char *buf;
65 int size;
66
67 unsigned char palette[PALETTE_COUNT * 4];
68 unsigned char *unpack_buffer;
69 int unpack_buffer_size;
70
71} VmdVideoContext;
72
73#define QUEUE_SIZE 0x1000
74#define QUEUE_MASK 0x0FFF
75
76static void lz_unpack(unsigned char *src, unsigned char *dest, int dest_len)
77{
78 unsigned char *s;
79 unsigned char *d;
80 unsigned char *d_end;
81 unsigned char queue[QUEUE_SIZE];
82 unsigned int qpos;
83 unsigned int dataleft;
84 unsigned int chainofs;
85 unsigned int chainlen;
86 unsigned int speclen;
87 unsigned char tag;
88 unsigned int i, j;
89
90 s = src;
91 d = dest;
92 d_end = d + dest_len;
93 dataleft = LE_32(s);
94 s += 4;
95 memset(queue, QUEUE_SIZE, 0x20);
96 if (LE_32(s) == 0x56781234) {
97 s += 4;
98 qpos = 0x111;
99 speclen = 0xF + 3;
100 } else {
101 qpos = 0xFEE;
102 speclen = 100; /* no speclen */
103 }
104
105 while (dataleft > 0) {
106 tag = *s++;
107 if ((tag == 0xFF) && (dataleft > 8)) {
108 if (d + 8 > d_end)
109 return;
110 for (i = 0; i < 8; i++) {
111 queue[qpos++] = *d++ = *s++;
112 qpos &= QUEUE_MASK;
113 }
114 dataleft -= 8;
115 } else {
116 for (i = 0; i < 8; i++) {
117 if (dataleft == 0)
118 break;
119 if (tag & 0x01) {
120 if (d + 1 > d_end)
121 return;
122 queue[qpos++] = *d++ = *s++;
123 qpos &= QUEUE_MASK;
124 dataleft--;
125 } else {
126 chainofs = *s++;
127 chainofs |= ((*s & 0xF0) << 4);
128 chainlen = (*s++ & 0x0F) + 3;
129 if (chainlen == speclen)
130 chainlen = *s++ + 0xF + 3;
131 if (d + chainlen > d_end)
132 return;
133 for (j = 0; j < chainlen; j++) {
134 *d = queue[chainofs++ & QUEUE_MASK];
135 queue[qpos++] = *d++;
136 qpos &= QUEUE_MASK;
137 }
138 dataleft -= chainlen;
139 }
140 tag >>= 1;
141 }
142 }
143 }
144}
145
146static int rle_unpack(unsigned char *src, unsigned char *dest,
147 int src_len, int dest_len)
148{
149 unsigned char *ps;
150 unsigned char *pd;
151 int i, l;
152 unsigned char *dest_end = dest + dest_len;
153
154 ps = src;
155 pd = dest;
156 if (src_len & 1)
157 *pd++ = *ps++;
158
159 src_len >>= 1;
160 i = 0;
161 do {
162 l = *ps++;
163 if (l & 0x80) {
164 l = (l & 0x7F) * 2;
165 if (pd + l > dest_end)
166 return (ps - src);
167 memcpy(pd, ps, l);
168 ps += l;
169 pd += l;
170 } else {
171 if (pd + i > dest_end)
172 return (ps - src);
173 for (i = 0; i < l; i++) {
174 *pd++ = ps[0];
175 *pd++ = ps[1];
176 }
177 ps += 2;
178 }
179 i += l;
180 } while (i < src_len);
181
182 return (ps - src);
183}
184
185static void vmd_decode(VmdVideoContext *s)
186{
187 int i;
188 unsigned int *palette32;
189 unsigned char r, g, b;
190
191 /* point to the start of the encoded data */
192 unsigned char *p = s->buf + 16;
193
194 unsigned char *pb;
195 unsigned char meth;
196 unsigned char *dp; /* pointer to current frame */
197 unsigned char *pp; /* pointer to previous frame */
198 unsigned char len;
199 int ofs;
200
201 int frame_x, frame_y;
202 int frame_width, frame_height;
203 int dp_size;
204
205 frame_x = LE_16(&s->buf[6]);
206 frame_y = LE_16(&s->buf[8]);
207 frame_width = LE_16(&s->buf[10]) - frame_x + 1;
208 frame_height = LE_16(&s->buf[12]) - frame_y + 1;
209
210 /* if only a certain region will be updated, copy the entire previous
211 * frame before the decode */
212 if (frame_x || frame_y || (frame_width != s->avctx->width) ||
213 (frame_height != s->avctx->height)) {
214
215 memcpy(s->frame.data[0], s->prev_frame.data[0],
216 s->avctx->height * s->frame.linesize[0]);
217 }
218
219 /* check if there is a new palette */
220 if (s->buf[15] & 0x02) {
221 p += 2;
222 palette32 = (unsigned int *)s->palette;
223 for (i = 0; i < PALETTE_COUNT; i++) {
224 r = *p++ * 4;
225 g = *p++ * 4;
226 b = *p++ * 4;
227 palette32[i] = (r << 16) | (g << 8) | (b);
228 }
229 s->size -= (256 * 3 + 2);
230 }
231 if (s->size >= 0) {
232 /* originally UnpackFrame in VAG's code */
233 pb = p;
234 meth = *pb++;
235 if (meth & 0x80) {
236 lz_unpack(pb, s->unpack_buffer, s->unpack_buffer_size);
237 meth &= 0x7F;
238 pb = s->unpack_buffer;
239 }
240
241 dp = &s->frame.data[0][frame_y * s->frame.linesize[0] + frame_x];
242 dp_size = s->frame.linesize[0] * s->avctx->height;
243 pp = &s->prev_frame.data[0][frame_y * s->prev_frame.linesize[0] + frame_x];
244 switch (meth) {
245 case 1:
246 for (i = 0; i < frame_height; i++) {
247 ofs = 0;
248 do {
249 len = *pb++;
250 if (len & 0x80) {
251 len = (len & 0x7F) + 1;
252 if (ofs + len > frame_width)
253 return;
254 memcpy(&dp[ofs], pb, len);
255 pb += len;
256 ofs += len;
257 } else {
258 /* interframe pixel copy */
259 if (ofs + len + 1 > frame_width)
260 return;
261 memcpy(&dp[ofs], &pp[ofs], len + 1);
262 ofs += len + 1;
263 }
264 } while (ofs < frame_width);
265 if (ofs > frame_width) {
266 av_log(s->avctx, AV_LOG_ERROR, "VMD video: offset > width (%d > %d)\n",
267 ofs, frame_width);
268 break;
269 }
270 dp += s->frame.linesize[0];
271 pp += s->prev_frame.linesize[0];
272 }
273 break;
274
275 case 2:
276 for (i = 0; i < frame_height; i++) {
277 memcpy(dp, pb, frame_width);
278 pb += frame_width;
279 dp += s->frame.linesize[0];
280 pp += s->prev_frame.linesize[0];
281 }
282 break;
283
284 case 3:
285 for (i = 0; i < frame_height; i++) {
286 ofs = 0;
287 do {
288 len = *pb++;
289 if (len & 0x80) {
290 len = (len & 0x7F) + 1;
291 if (*pb++ == 0xFF)
292 len = rle_unpack(pb, &dp[ofs], len, frame_width - ofs);
293 else
294 memcpy(&dp[ofs], pb, len);
295 pb += len;
296 ofs += len;
297 } else {
298 /* interframe pixel copy */
299 if (ofs + len + 1 > frame_width)
300 return;
301 memcpy(&dp[ofs], &pp[ofs], len + 1);
302 ofs += len + 1;
303 }
304 } while (ofs < frame_width);
305 if (ofs > frame_width) {
306 av_log(s->avctx, AV_LOG_ERROR, "VMD video: offset > width (%d > %d)\n",
307 ofs, frame_width);
308 }
309 dp += s->frame.linesize[0];
310 pp += s->prev_frame.linesize[0];
311 }
312 break;
313 }
314 }
315}
316
317static int vmdvideo_decode_init(AVCodecContext *avctx)
318{
319 VmdVideoContext *s = (VmdVideoContext *)avctx->priv_data;
320 int i;
321 unsigned int *palette32;
322 int palette_index = 0;
323 unsigned char r, g, b;
324 unsigned char *vmd_header;
325 unsigned char *raw_palette;
326
327 s->avctx = avctx;
328 avctx->pix_fmt = PIX_FMT_PAL8;
329 avctx->has_b_frames = 0;
330 dsputil_init(&s->dsp, avctx);
331
332 /* make sure the VMD header made it */
333 if (s->avctx->extradata_size != VMD_HEADER_SIZE) {
334 av_log(s->avctx, AV_LOG_ERROR, "VMD video: expected extradata size of %d\n",
335 VMD_HEADER_SIZE);
336 return -1;
337 }
338 vmd_header = (unsigned char *)avctx->extradata;
339
340 s->unpack_buffer_size = LE_32(&vmd_header[800]);
341 s->unpack_buffer = av_malloc(s->unpack_buffer_size);
342 if (!s->unpack_buffer)
343 return -1;
344
345 /* load up the initial palette */
346 raw_palette = &vmd_header[28];
347 palette32 = (unsigned int *)s->palette;
348 for (i = 0; i < PALETTE_COUNT; i++) {
349 r = raw_palette[palette_index++] * 4;
350 g = raw_palette[palette_index++] * 4;
351 b = raw_palette[palette_index++] * 4;
352 palette32[i] = (r << 16) | (g << 8) | (b);
353 }
354
355 s->frame.data[0] = s->prev_frame.data[0] = NULL;
356
357 return 0;
358}
359
360static int vmdvideo_decode_frame(AVCodecContext *avctx,
361 void *data, int *data_size,
362 uint8_t *buf, int buf_size)
363{
364 VmdVideoContext *s = (VmdVideoContext *)avctx->priv_data;
365
366 s->buf = buf;
367 s->size = buf_size;
368
369 if (buf_size < 16)
370 return buf_size;
371
372 s->frame.reference = 1;
373 if (avctx->get_buffer(avctx, &s->frame)) {
374 av_log(s->avctx, AV_LOG_ERROR, "VMD Video: get_buffer() failed\n");
375 return -1;
376 }
377
378 vmd_decode(s);
379
380 /* make the palette available on the way out */
381 memcpy(s->frame.data[1], s->palette, PALETTE_COUNT * 4);
382
383 if (s->prev_frame.data[0])
384 avctx->release_buffer(avctx, &s->prev_frame);
385
386 /* shuffle frames */
387 s->prev_frame = s->frame;
388
389 *data_size = sizeof(AVFrame);
390 *(AVFrame*)data = s->frame;
391
392 /* report that the buffer was completely consumed */
393 return buf_size;
394}
395
396static int vmdvideo_decode_end(AVCodecContext *avctx)
397{
398 VmdVideoContext *s = (VmdVideoContext *)avctx->priv_data;
399
400 if (s->prev_frame.data[0])
401 avctx->release_buffer(avctx, &s->prev_frame);
402 av_free(s->unpack_buffer);
403
404 return 0;
405}
406
407
408/*
409 * Audio Decoder
410 */
411
412typedef struct VmdAudioContext {
413 AVCodecContext *avctx;
414 int channels;
415 int bits;
416 int block_align;
417 int predictors[2];
418} VmdAudioContext;
419
420static uint16_t vmdaudio_table[128] = {
421 0x000, 0x008, 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, 0x080,
422 0x090, 0x0A0, 0x0B0, 0x0C0, 0x0D0, 0x0E0, 0x0F0, 0x100, 0x110, 0x120,
423 0x130, 0x140, 0x150, 0x160, 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0,
424 0x1D0, 0x1E0, 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
425 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270, 0x278, 0x280,
426 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0, 0x2B8, 0x2C0, 0x2C8, 0x2D0,
427 0x2D8, 0x2E0, 0x2E8, 0x2F0, 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320,
428 0x328, 0x330, 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
429 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0, 0x3B8, 0x3C0,
430 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0, 0x3F8, 0x400, 0x440, 0x480,
431 0x4C0, 0x500, 0x540, 0x580, 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700,
432 0x740, 0x780, 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
433 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
434};
435
436static int vmdaudio_decode_init(AVCodecContext *avctx)
437{
438 VmdAudioContext *s = (VmdAudioContext *)avctx->priv_data;
439
440 s->avctx = avctx;
441 s->channels = avctx->channels;
442 s->bits = avctx->bits_per_sample;
443 s->block_align = avctx->block_align;
444
445 av_log(s->avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, block align = %d, sample rate = %d\n",
446 s->channels, s->bits, s->block_align, avctx->sample_rate);
447
448 return 0;
449}
450
451static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data,
452 uint8_t *buf, int stereo)
453{
454 int i;
455 int chan = 0;
456 int16_t *out = (int16_t*)data;
457
458 for(i = 0; i < s->block_align; i++) {
459 if(buf[i] & 0x80)
460 s->predictors[chan] -= vmdaudio_table[buf[i] & 0x7F];
461 else
462 s->predictors[chan] += vmdaudio_table[buf[i]];
463 s->predictors[chan] = clip(s->predictors[chan], -32768, 32767);
464 out[i] = s->predictors[chan];
465 chan ^= stereo;
466 }
467}
468
469static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data,
470 uint8_t *buf, int silence)
471{
472 int bytes_decoded = 0;
473 int i;
474
475// if (silence)
476// av_log(s->avctx, AV_LOG_INFO, "silent block!\n");
477 if (s->channels == 2) {
478
479 /* stereo handling */
480 if (silence) {
481 memset(data, 0, s->block_align * 2);
482 } else {
483 if (s->bits == 16)
484 vmdaudio_decode_audio(s, data, buf, 1);
485 else
486 /* copy the data but convert it to signed */
487 for (i = 0; i < s->block_align; i++)
488 data[i * 2 + 1] = buf[i] + 0x80;
489 }
490 } else {
491 bytes_decoded = s->block_align * 2;
492
493 /* mono handling */
494 if (silence) {
495 memset(data, 0, s->block_align * 2);
496 } else {
497 if (s->bits == 16) {
498 vmdaudio_decode_audio(s, data, buf, 0);
499 } else {
500 /* copy the data but convert it to signed */
501 for (i = 0; i < s->block_align; i++)
502 data[i * 2 + 1] = buf[i] + 0x80;
503 }
504 }
505 }
506
507 return s->block_align * 2;
508}
509
510static int vmdaudio_decode_frame(AVCodecContext *avctx,
511 void *data, int *data_size,
512 uint8_t *buf, int buf_size)
513{
514 VmdAudioContext *s = (VmdAudioContext *)avctx->priv_data;
515 unsigned int sound_flags;
516 unsigned char *output_samples = (unsigned char *)data;
517
518 /* point to the start of the encoded data */
519 unsigned char *p = buf + 16;
520 unsigned char *p_end = buf + buf_size;
521
522 if (buf_size < 16)
523 return buf_size;
524
525 if (buf[6] == 1) {
526 /* the chunk contains audio */
527 *data_size = vmdaudio_loadsound(s, output_samples, p, 0);
528 } else if (buf[6] == 2) {
529 /* the chunk contains audio and silence mixed together */
530 sound_flags = LE_32(p);
531 p += 4;
532
533 /* do something with extrabufs here? */
534
535 while (p < p_end) {
536 if (sound_flags & 0x01)
537 /* silence */
538 *data_size += vmdaudio_loadsound(s, output_samples, p, 1);
539 else {
540 /* audio */
541 *data_size += vmdaudio_loadsound(s, output_samples, p, 0);
542 p += s->block_align;
543 }
544 output_samples += (s->block_align * s->bits / 8);
545 sound_flags >>= 1;
546 }
547 } else if (buf[6] == 3) {
548 /* silent chunk */
549 *data_size = vmdaudio_loadsound(s, output_samples, p, 1);
550 }
551
552 return buf_size;
553}
554
555
556/*
557 * Public Data Structures
558 */
559
560AVCodec vmdvideo_decoder = {
561 "vmdvideo",
562 CODEC_TYPE_VIDEO,
563 CODEC_ID_VMDVIDEO,
564 sizeof(VmdVideoContext),
565 vmdvideo_decode_init,
566 NULL,
567 vmdvideo_decode_end,
568 vmdvideo_decode_frame,
569 CODEC_CAP_DR1,
570};
571
572AVCodec vmdaudio_decoder = {
573 "vmdaudio",
574 CODEC_TYPE_AUDIO,
575 CODEC_ID_VMDAUDIO,
576 sizeof(VmdAudioContext),
577 vmdaudio_decode_init,
578 NULL,
579 NULL,
580 vmdaudio_decode_frame,
581};
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette