1/*
2 * AVS video decoder.
3 * Copyright (c) 2006  Aurelien Jacobs <aurel@gnuage.org>
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg 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 * FFmpeg 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 FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include "avcodec.h"
23#include "get_bits.h"
24
25
26typedef struct {
27    AVFrame picture;
28} AvsContext;
29
30typedef enum {
31    AVS_VIDEO     = 0x01,
32    AVS_AUDIO     = 0x02,
33    AVS_PALETTE   = 0x03,
34    AVS_GAME_DATA = 0x04,
35} AvsBlockType;
36
37typedef enum {
38    AVS_I_FRAME     = 0x00,
39    AVS_P_FRAME_3X3 = 0x01,
40    AVS_P_FRAME_2X2 = 0x02,
41    AVS_P_FRAME_2X3 = 0x03,
42} AvsVideoSubType;
43
44
45static int
46avs_decode_frame(AVCodecContext * avctx,
47                 void *data, int *data_size, AVPacket *avpkt)
48{
49    const uint8_t *buf = avpkt->data;
50    int buf_size = avpkt->size;
51    AvsContext *const avs = avctx->priv_data;
52    AVFrame *picture = data;
53    AVFrame *const p = (AVFrame *) & avs->picture;
54    const uint8_t *table, *vect;
55    uint8_t *out;
56    int i, j, x, y, stride, vect_w = 3, vect_h = 3;
57    AvsVideoSubType sub_type;
58    AvsBlockType type;
59    GetBitContext change_map;
60
61    if (avctx->reget_buffer(avctx, p)) {
62        av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
63        return -1;
64    }
65    p->reference = 1;
66    p->pict_type = FF_P_TYPE;
67    p->key_frame = 0;
68
69    out = avs->picture.data[0];
70    stride = avs->picture.linesize[0];
71
72    sub_type = buf[0];
73    type = buf[1];
74    buf += 4;
75
76    if (type == AVS_PALETTE) {
77        int first, last;
78        uint32_t *pal = (uint32_t *) avs->picture.data[1];
79
80        first = AV_RL16(buf);
81        last = first + AV_RL16(buf + 2);
82        buf += 4;
83        for (i=first; i<last; i++, buf+=3)
84            pal[i] = (buf[0] << 18) | (buf[1] << 10) | (buf[2] << 2);
85
86        sub_type = buf[0];
87        type = buf[1];
88        buf += 4;
89    }
90
91    if (type != AVS_VIDEO)
92        return -1;
93
94    switch (sub_type) {
95    case AVS_I_FRAME:
96        p->pict_type = FF_I_TYPE;
97        p->key_frame = 1;
98    case AVS_P_FRAME_3X3:
99        vect_w = 3;
100        vect_h = 3;
101        break;
102
103    case AVS_P_FRAME_2X2:
104        vect_w = 2;
105        vect_h = 2;
106        break;
107
108    case AVS_P_FRAME_2X3:
109        vect_w = 2;
110        vect_h = 3;
111        break;
112
113    default:
114      return -1;
115    }
116
117    table = buf + (256 * vect_w * vect_h);
118    if (sub_type != AVS_I_FRAME) {
119        int map_size = ((318 / vect_w + 7) / 8) * (198 / vect_h);
120        init_get_bits(&change_map, table, map_size);
121        table += map_size;
122    }
123
124    for (y=0; y<198; y+=vect_h) {
125        for (x=0; x<318; x+=vect_w) {
126            if (sub_type == AVS_I_FRAME || get_bits1(&change_map)) {
127                vect = &buf[*table++ * (vect_w * vect_h)];
128                for (j=0; j<vect_w; j++) {
129                    out[(y + 0) * stride + x + j] = vect[(0 * vect_w) + j];
130                    out[(y + 1) * stride + x + j] = vect[(1 * vect_w) + j];
131                    if (vect_h == 3)
132                        out[(y + 2) * stride + x + j] =
133                            vect[(2 * vect_w) + j];
134                }
135            }
136        }
137        if (sub_type != AVS_I_FRAME)
138            align_get_bits(&change_map);
139    }
140
141    *picture = *(AVFrame *) & avs->picture;
142    *data_size = sizeof(AVPicture);
143
144    return buf_size;
145}
146
147static av_cold int avs_decode_init(AVCodecContext * avctx)
148{
149    avctx->pix_fmt = PIX_FMT_PAL8;
150    return 0;
151}
152
153AVCodec avs_decoder = {
154    "avs",
155    AVMEDIA_TYPE_VIDEO,
156    CODEC_ID_AVS,
157    sizeof(AvsContext),
158    avs_decode_init,
159    NULL,
160    NULL,
161    avs_decode_frame,
162    CODEC_CAP_DR1,
163    .long_name = NULL_IF_CONFIG_SMALL("AVS (Audio Video Standard) video"),
164};
165