Imported Debian version 2.4.3~trusty1
[deb_ffmpeg.git] / ffmpeg / libavcodec / jvdec.c
CommitLineData
2ba45a60
DM
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};