Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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