2 * Microsoft Video-1 Decoder
3 * Copyright (C) 2003 the ffmpeg project
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * Microsoft Video-1 Decoder by Mike Melanson (melanson@pcisys.net)
24 * For more information about the MS Video-1 format, visit:
25 * http://www.pcisys.net/~melanson/codecs/
27 * This decoder outputs either PAL8 or RGB555 data, depending on the
28 * whether a RGB palette was passed through via extradata; if the extradata
29 * is present, then the data is PAL8; RGB555 otherwise.
41 #define PALETTE_COUNT 256
42 #define LE_16(x) ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0])
43 #define CHECK_STREAM_PTR(n) \
44 if ((stream_ptr + n) > s->size ) { \
45 printf (" MS Video-1 warning: stream_ptr out of bounds (%d >= %d)\n", \
46 stream_ptr + n, s->size); \
50 #define COPY_PREV_BLOCK() \
51 pixel_ptr = block_ptr; \
52 for (pixel_y = 0; pixel_y < 4; pixel_y++) { \
53 for (pixel_x = 0; pixel_x < 4; pixel_x++, pixel_ptr++) \
54 pixels[pixel_ptr] = prev_pixels[pixel_ptr]; \
55 pixel_ptr -= row_dec; \
58 typedef struct Msvideo1Context
{
60 AVCodecContext
*avctx
;
68 int mode_8bit
; /* if it's not 8-bit, it's 16-bit */
69 unsigned char palette
[PALETTE_COUNT
* 4];
73 static int msvideo1_decode_init(AVCodecContext
*avctx
)
75 Msvideo1Context
*s
= (Msvideo1Context
*)avctx
->priv_data
;
77 unsigned char r
, g
, b
;
78 unsigned char *raw_palette
;
79 unsigned int *palette32
;
83 /* figure out the colorspace based on the presence of a palette in
85 if (s
->avctx
->extradata_size
) {
87 /* load up the palette */
88 palette32
= (unsigned int *)s
->palette
;
89 raw_palette
= (unsigned char *)s
->avctx
->extradata
;
90 for (i
= 0; i
< s
->avctx
->extradata_size
/ 4; i
++) {
95 palette32
[i
] = (r
<< 16) | (g
<< 8) | (b
);
97 avctx
->pix_fmt
= PIX_FMT_PAL8
;
100 avctx
->pix_fmt
= PIX_FMT_RGB555
;
103 avctx
->has_b_frames
= 0;
104 dsputil_init(&s
->dsp
, avctx
);
106 s
->frame
.data
[0] = s
->prev_frame
.data
[0] = NULL
;
111 static void msvideo1_decode_8bit(Msvideo1Context
*s
)
113 int block_ptr
, pixel_ptr
;
115 int pixel_x
, pixel_y
; /* pixel width and height iterators */
116 int block_x
, block_y
; /* block width and height iterators */
117 int blocks_wide
, blocks_high
; /* width and height in 4x4 blocks */
121 /* decoding parameters */
123 unsigned char byte_a
, byte_b
;
124 unsigned short flags
;
126 unsigned char colors
[8];
127 unsigned char *pixels
= s
->frame
.data
[0];
128 unsigned char *prev_pixels
= s
->prev_frame
.data
[0];
129 int stride
= s
->frame
.linesize
[0];
133 blocks_wide
= s
->avctx
->width
/ 4;
134 blocks_high
= s
->avctx
->height
/ 4;
135 total_blocks
= blocks_wide
* blocks_high
;
137 row_dec
= stride
+ 4;
139 for (block_y
= blocks_high
; block_y
> 0; block_y
--) {
140 block_ptr
= ((block_y
* 4) - 1) * stride
;
141 for (block_x
= blocks_wide
; block_x
> 0; block_x
--) {
142 /* check if this block should be skipped */
145 block_ptr
+= block_inc
;
151 pixel_ptr
= block_ptr
;
153 /* get the next two bytes in the encoded data stream */
155 byte_a
= s
->buf
[stream_ptr
++];
156 byte_b
= s
->buf
[stream_ptr
++];
158 /* check if the decode is finished */
159 if ((byte_a
== 0) && (byte_b
== 0) && (total_blocks
== 0))
161 else if ((byte_b
& 0xFC) == 0x84) {
162 /* skip code, but don't count the current block */
163 skip_blocks
= ((byte_b
- 0x84) << 8) + byte_a
- 1;
165 } else if (byte_b
< 0x80) {
166 /* 2-color encoding */
167 flags
= (byte_b
<< 8) | byte_a
;
170 colors
[0] = s
->buf
[stream_ptr
++];
171 colors
[1] = s
->buf
[stream_ptr
++];
173 for (pixel_y
= 0; pixel_y
< 4; pixel_y
++) {
174 for (pixel_x
= 0; pixel_x
< 4; pixel_x
++, flags
>>= 1)
175 pixels
[pixel_ptr
++] = colors
[(flags
& 0x1) ^ 1];
176 pixel_ptr
-= row_dec
;
178 } else if (byte_b
>= 0x90) {
179 /* 8-color encoding */
180 flags
= (byte_b
<< 8) | byte_a
;
183 memcpy(colors
, &s
->buf
[stream_ptr
], 8);
186 for (pixel_y
= 0; pixel_y
< 4; pixel_y
++) {
187 for (pixel_x
= 0; pixel_x
< 4; pixel_x
++, flags
>>= 1)
188 pixels
[pixel_ptr
++] =
189 colors
[((pixel_y
& 0x2) << 1) +
190 (pixel_x
& 0x2) + ((flags
& 0x1) ^ 1)];
191 pixel_ptr
-= row_dec
;
194 /* 1-color encoding */
197 for (pixel_y
= 0; pixel_y
< 4; pixel_y
++) {
198 for (pixel_x
= 0; pixel_x
< 4; pixel_x
++)
199 pixels
[pixel_ptr
++] = colors
[0];
200 pixel_ptr
-= row_dec
;
204 block_ptr
+= block_inc
;
209 /* make the palette available on the way out */
210 if (s
->avctx
->pix_fmt
== PIX_FMT_PAL8
)
211 memcpy(s
->frame
.data
[1], s
->palette
, PALETTE_COUNT
* 4);
214 static void msvideo1_decode_16bit(Msvideo1Context
*s
)
216 int block_ptr
, pixel_ptr
;
218 int pixel_x
, pixel_y
; /* pixel width and height iterators */
219 int block_x
, block_y
; /* block width and height iterators */
220 int blocks_wide
, blocks_high
; /* width and height in 4x4 blocks */
224 /* decoding parameters */
226 unsigned char byte_a
, byte_b
;
227 unsigned short flags
;
229 unsigned short colors
[8];
230 unsigned short *pixels
= (unsigned short *)s
->frame
.data
[0];
231 unsigned short *prev_pixels
= (unsigned short *)s
->prev_frame
.data
[0];
232 int stride
= s
->frame
.linesize
[0] / 2;
236 blocks_wide
= s
->avctx
->width
/ 4;
237 blocks_high
= s
->avctx
->height
/ 4;
238 total_blocks
= blocks_wide
* blocks_high
;
240 row_dec
= stride
+ 4;
242 for (block_y
= blocks_high
; block_y
> 0; block_y
--) {
243 block_ptr
= ((block_y
* 4) - 1) * stride
;
244 for (block_x
= blocks_wide
; block_x
> 0; block_x
--) {
245 /* check if this block should be skipped */
248 block_ptr
+= block_inc
;
254 pixel_ptr
= block_ptr
;
256 /* get the next two bytes in the encoded data stream */
258 byte_a
= s
->buf
[stream_ptr
++];
259 byte_b
= s
->buf
[stream_ptr
++];
261 /* check if the decode is finished */
262 if ((byte_a
== 0) && (byte_b
== 0) && (total_blocks
== 0)) {
264 } else if ((byte_b
& 0xFC) == 0x84) {
265 /* skip code, but don't count the current block */
266 skip_blocks
= ((byte_b
- 0x84) << 8) + byte_a
- 1;
268 } else if (byte_b
< 0x80) {
269 /* 2- or 8-color encoding modes */
270 flags
= (byte_b
<< 8) | byte_a
;
273 colors
[0] = LE_16(&s
->buf
[stream_ptr
]);
275 colors
[1] = LE_16(&s
->buf
[stream_ptr
]);
278 if (colors
[0] & 0x8000) {
279 /* 8-color encoding */
280 CHECK_STREAM_PTR(12);
281 colors
[2] = LE_16(&s
->buf
[stream_ptr
]);
283 colors
[3] = LE_16(&s
->buf
[stream_ptr
]);
285 colors
[4] = LE_16(&s
->buf
[stream_ptr
]);
287 colors
[5] = LE_16(&s
->buf
[stream_ptr
]);
289 colors
[6] = LE_16(&s
->buf
[stream_ptr
]);
291 colors
[7] = LE_16(&s
->buf
[stream_ptr
]);
294 for (pixel_y
= 0; pixel_y
< 4; pixel_y
++) {
295 for (pixel_x
= 0; pixel_x
< 4; pixel_x
++, flags
>>= 1)
296 pixels
[pixel_ptr
++] =
297 colors
[((pixel_y
& 0x2) << 1) +
298 (pixel_x
& 0x2) + ((flags
& 0x1) ^ 1)];
299 pixel_ptr
-= row_dec
;
302 /* 2-color encoding */
303 for (pixel_y
= 0; pixel_y
< 4; pixel_y
++) {
304 for (pixel_x
= 0; pixel_x
< 4; pixel_x
++, flags
>>= 1)
305 pixels
[pixel_ptr
++] = colors
[(flags
& 0x1) ^ 1];
306 pixel_ptr
-= row_dec
;
310 /* otherwise, it's a 1-color block */
311 colors
[0] = (byte_b
<< 8) | byte_a
;
313 for (pixel_y
= 0; pixel_y
< 4; pixel_y
++) {
314 for (pixel_x
= 0; pixel_x
< 4; pixel_x
++)
315 pixels
[pixel_ptr
++] = colors
[0];
316 pixel_ptr
-= row_dec
;
320 block_ptr
+= block_inc
;
326 static int msvideo1_decode_frame(AVCodecContext
*avctx
,
327 void *data
, int *data_size
,
328 uint8_t *buf
, int buf_size
)
330 Msvideo1Context
*s
= (Msvideo1Context
*)avctx
->priv_data
;
335 if (avctx
->get_buffer(avctx
, &s
->frame
)) {
336 printf (" MS Video-1 Video: get_buffer() failed\n");
341 msvideo1_decode_8bit(s
);
343 msvideo1_decode_16bit(s
);
345 if (s
->prev_frame
.data
[0])
346 avctx
->release_buffer(avctx
, &s
->prev_frame
);
349 s
->prev_frame
= s
->frame
;
351 *data_size
= sizeof(AVFrame
);
352 *(AVFrame
*)data
= s
->frame
;
354 /* report that the buffer was completely consumed */
358 static int msvideo1_decode_end(AVCodecContext
*avctx
)
360 Msvideo1Context
*s
= (Msvideo1Context
*)avctx
->priv_data
;
362 if (s
->prev_frame
.data
[0])
363 avctx
->release_buffer(avctx
, &s
->prev_frame
);
368 AVCodec msvideo1_decoder
= {
372 sizeof(Msvideo1Context
),
373 msvideo1_decode_init
,
376 msvideo1_decode_frame
,