1/*
2 * Bitmap Brothers JV video decoder
3 * Copyright (c) 2011 Peter Ross <pross@xvid.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/**
23 * @file
24 * Bitmap Brothers JV video decoder
25 * @author Peter Ross <pross@xvid.org>
26 */
27
28#include "libavutil/intreadwrite.h"
29
30#include "avcodec.h"
31#include "blockdsp.h"
32#include "get_bits.h"
33#include "internal.h"
34
35typedef struct JvContext {
36    BlockDSPContext bdsp;
37    AVFrame   *frame;
38    uint32_t   palette[AVPALETTE_COUNT];
39    int        palette_has_changed;
40} JvContext;
41
42static av_cold int decode_init(AVCodecContext *avctx)
43{
44    JvContext *s = avctx->priv_data;
45
46    s->frame = av_frame_alloc();
47    if (!s->frame)
48        return AVERROR(ENOMEM);
49
50    avctx->pix_fmt = AV_PIX_FMT_PAL8;
51    ff_blockdsp_init(&s->bdsp, avctx);
52    return 0;
53}
54
55/**
56 * Decode 2x2 block
57 */
58static inline void decode2x2(GetBitContext *gb, uint8_t *dst, int linesize)
59{
60    int i, j, v[2];
61
62    switch (get_bits(gb, 2)) {
63    case 1:
64        v[0] = get_bits(gb, 8);
65        for (j = 0; j < 2; j++)
66            memset(dst + j * linesize, v[0], 2);
67        break;
68    case 2:
69        v[0] = get_bits(gb, 8);
70        v[1] = get_bits(gb, 8);
71        for (j = 0; j < 2; j++)
72            for (i = 0; i < 2; i++)
73                dst[j * linesize + i] = v[get_bits1(gb)];
74        break;
75    case 3:
76        for (j = 0; j < 2; j++)
77            for (i = 0; i < 2; i++)
78                dst[j * linesize + i] = get_bits(gb, 8);
79    }
80}
81
82/**
83 * Decode 4x4 block
84 */
85static inline void decode4x4(GetBitContext *gb, uint8_t *dst, int linesize)
86{
87    int i, j, v[2];
88
89    switch (get_bits(gb, 2)) {
90    case 1:
91        v[0] = get_bits(gb, 8);
92        for (j = 0; j < 4; j++)
93            memset(dst + j * linesize, v[0], 4);
94        break;
95    case 2:
96        v[0] = get_bits(gb, 8);
97        v[1] = get_bits(gb, 8);
98        for (j = 2; j >= 0; j -= 2) {
99            for (i = 0; i < 4; i++)
100                dst[j * linesize + i] = v[get_bits1(gb)];
101            for (i = 0; i < 4; i++)
102                dst[(j + 1) * linesize + i] = v[get_bits1(gb)];
103        }
104        break;
105    case 3:
106        for (j = 0; j < 4; j += 2)
107            for (i = 0; i < 4; i += 2)
108                decode2x2(gb, dst + j * linesize + i, linesize);
109    }
110}
111
112/**
113 * Decode 8x8 block
114 */
115static inline void decode8x8(GetBitContext *gb, uint8_t *dst, int linesize,
116                             BlockDSPContext *bdsp)
117{
118    int i, j, v[2];
119
120    switch (get_bits(gb, 2)) {
121    case 1:
122        v[0] = get_bits(gb, 8);
123        bdsp->fill_block_tab[1](dst, v[0], linesize, 8);
124        break;
125    case 2:
126        v[0] = get_bits(gb, 8);
127        v[1] = get_bits(gb, 8);
128        for (j = 7; j >= 0; j--)
129            for (i = 0; i < 8; i++)
130                dst[j * linesize + i] = v[get_bits1(gb)];
131        break;
132    case 3:
133        for (j = 0; j < 8; j += 4)
134            for (i = 0; i < 8; i += 4)
135                decode4x4(gb, dst + j * linesize + i, linesize);
136    }
137}
138
139static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
140                        AVPacket *avpkt)
141{
142    JvContext *s = avctx->priv_data;
143    const uint8_t *buf = avpkt->data;
144    const uint8_t *buf_end = buf + avpkt->size;
145    int video_size, video_type, i, j, ret;
146
147    if (avpkt->size < 6)
148        return AVERROR_INVALIDDATA;
149
150    video_size = AV_RL32(buf);
151    video_type = buf[4];
152    buf += 5;
153
154    if (video_size) {
155        if (video_size < 0 || video_size > avpkt->size - 5) {
156            av_log(avctx, AV_LOG_ERROR, "video size %d invalid\n", video_size);
157            return AVERROR_INVALIDDATA;
158        }
159        if ((ret = ff_reget_buffer(avctx, s->frame)) < 0)
160            return ret;
161
162        if (video_type == 0 || video_type == 1) {
163            GetBitContext gb;
164            init_get_bits(&gb, buf, 8 * video_size);
165
166            for (j = 0; j < avctx->height; j += 8)
167                for (i = 0; i < avctx->width; i += 8)
168                    decode8x8(&gb,
169                              s->frame->data[0] + j * s->frame->linesize[0] + i,
170                              s->frame->linesize[0], &s->bdsp);
171
172            buf += video_size;
173        } else if (video_type == 2) {
174            int v = *buf++;
175            for (j = 0; j < avctx->height; j++)
176                memset(s->frame->data[0] + j * s->frame->linesize[0],
177                       v, avctx->width);
178        } else {
179            av_log(avctx, AV_LOG_WARNING,
180                   "unsupported frame type %i\n", video_type);
181            return AVERROR_INVALIDDATA;
182        }
183    }
184
185    if (buf_end - buf >= AVPALETTE_COUNT * 3) {
186        for (i = 0; i < AVPALETTE_COUNT; i++) {
187            uint32_t pal = AV_RB24(buf);
188            s->palette[i] = 0xFFU << 24 | pal << 2 | ((pal >> 4) & 0x30303);
189            buf += 3;
190        }
191        s->palette_has_changed = 1;
192    }
193
194    if (video_size) {
195        s->frame->key_frame           = 1;
196        s->frame->pict_type           = AV_PICTURE_TYPE_I;
197        s->frame->palette_has_changed = s->palette_has_changed;
198        s->palette_has_changed        = 0;
199        memcpy(s->frame->data[1], s->palette, AVPALETTE_SIZE);
200
201        if ((ret = av_frame_ref(data, s->frame)) < 0)
202            return ret;
203        *got_frame = 1;
204    }
205
206    return avpkt->size;
207}
208
209static av_cold int decode_close(AVCodecContext *avctx)
210{
211    JvContext *s = avctx->priv_data;
212
213    av_frame_free(&s->frame);
214
215    return 0;
216}
217
218AVCodec ff_jv_decoder = {
219    .name           = "jv",
220    .long_name      = NULL_IF_CONFIG_SMALL("Bitmap Brothers JV video"),
221    .type           = AVMEDIA_TYPE_VIDEO,
222    .id             = AV_CODEC_ID_JV,
223    .priv_data_size = sizeof(JvContext),
224    .init           = decode_init,
225    .close          = decode_close,
226    .decode         = decode_frame,
227    .capabilities   = CODEC_CAP_DR1,
228};
229