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