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