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 palctrl;
29 * if it's present, then the data is PAL8; RGB555 otherwise.
41 #define PALETTE_COUNT 256
42 #define CHECK_STREAM_PTR(n) \
43 if ((stream_ptr + n) > s->size ) { \
44 av_log(s->avctx, AV_LOG_ERROR, " MS Video-1 warning: stream_ptr out of bounds (%d >= %d)\n", \
45 stream_ptr + n, s->size); \
49 typedef struct Msvideo1Context
{
51 AVCodecContext
*avctx
;
58 int mode_8bit
; /* if it's not 8-bit, it's 16-bit */
62 static int msvideo1_decode_init(AVCodecContext
*avctx
)
64 Msvideo1Context
*s
= (Msvideo1Context
*)avctx
->priv_data
;
68 /* figure out the colorspace based on the presence of a palette */
69 if (s
->avctx
->palctrl
) {
71 avctx
->pix_fmt
= PIX_FMT_PAL8
;
74 avctx
->pix_fmt
= PIX_FMT_RGB555
;
77 avctx
->has_b_frames
= 0;
78 dsputil_init(&s
->dsp
, avctx
);
80 s
->frame
.data
[0] = NULL
;
85 static void msvideo1_decode_8bit(Msvideo1Context
*s
)
87 int block_ptr
, pixel_ptr
;
89 int pixel_x
, pixel_y
; /* pixel width and height iterators */
90 int block_x
, block_y
; /* block width and height iterators */
91 int blocks_wide
, blocks_high
; /* width and height in 4x4 blocks */
95 /* decoding parameters */
97 unsigned char byte_a
, byte_b
;
100 unsigned char colors
[8];
101 unsigned char *pixels
= s
->frame
.data
[0];
102 int stride
= s
->frame
.linesize
[0];
106 blocks_wide
= s
->avctx
->width
/ 4;
107 blocks_high
= s
->avctx
->height
/ 4;
108 total_blocks
= blocks_wide
* blocks_high
;
110 row_dec
= stride
+ 4;
112 for (block_y
= blocks_high
; block_y
> 0; block_y
--) {
113 block_ptr
= ((block_y
* 4) - 1) * stride
;
114 for (block_x
= blocks_wide
; block_x
> 0; block_x
--) {
115 /* check if this block should be skipped */
117 block_ptr
+= block_inc
;
123 pixel_ptr
= block_ptr
;
125 /* get the next two bytes in the encoded data stream */
127 byte_a
= s
->buf
[stream_ptr
++];
128 byte_b
= s
->buf
[stream_ptr
++];
130 /* check if the decode is finished */
131 if ((byte_a
== 0) && (byte_b
== 0) && (total_blocks
== 0))
133 else if ((byte_b
& 0xFC) == 0x84) {
134 /* skip code, but don't count the current block */
135 skip_blocks
= ((byte_b
- 0x84) << 8) + byte_a
- 1;
136 } else if (byte_b
< 0x80) {
137 /* 2-color encoding */
138 flags
= (byte_b
<< 8) | byte_a
;
141 colors
[0] = s
->buf
[stream_ptr
++];
142 colors
[1] = s
->buf
[stream_ptr
++];
144 for (pixel_y
= 0; pixel_y
< 4; pixel_y
++) {
145 for (pixel_x
= 0; pixel_x
< 4; pixel_x
++, flags
>>= 1)
146 pixels
[pixel_ptr
++] = colors
[(flags
& 0x1) ^ 1];
147 pixel_ptr
-= row_dec
;
149 } else if (byte_b
>= 0x90) {
150 /* 8-color encoding */
151 flags
= (byte_b
<< 8) | byte_a
;
154 memcpy(colors
, &s
->buf
[stream_ptr
], 8);
157 for (pixel_y
= 0; pixel_y
< 4; pixel_y
++) {
158 for (pixel_x
= 0; pixel_x
< 4; pixel_x
++, flags
>>= 1)
159 pixels
[pixel_ptr
++] =
160 colors
[((pixel_y
& 0x2) << 1) +
161 (pixel_x
& 0x2) + ((flags
& 0x1) ^ 1)];
162 pixel_ptr
-= row_dec
;
165 /* 1-color encoding */
168 for (pixel_y
= 0; pixel_y
< 4; pixel_y
++) {
169 for (pixel_x
= 0; pixel_x
< 4; pixel_x
++)
170 pixels
[pixel_ptr
++] = colors
[0];
171 pixel_ptr
-= row_dec
;
175 block_ptr
+= block_inc
;
180 /* make the palette available on the way out */
181 if (s
->avctx
->pix_fmt
== PIX_FMT_PAL8
) {
182 memcpy(s
->frame
.data
[1], s
->avctx
->palctrl
->palette
, AVPALETTE_SIZE
);
183 if (s
->avctx
->palctrl
->palette_changed
) {
184 s
->frame
.palette_has_changed
= 1;
185 s
->avctx
->palctrl
->palette_changed
= 0;
190 static void msvideo1_decode_16bit(Msvideo1Context
*s
)
192 int block_ptr
, pixel_ptr
;
194 int pixel_x
, pixel_y
; /* pixel width and height iterators */
195 int block_x
, block_y
; /* block width and height iterators */
196 int blocks_wide
, blocks_high
; /* width and height in 4x4 blocks */
200 /* decoding parameters */
202 unsigned char byte_a
, byte_b
;
203 unsigned short flags
;
205 unsigned short colors
[8];
206 unsigned short *pixels
= (unsigned short *)s
->frame
.data
[0];
207 int stride
= s
->frame
.linesize
[0] / 2;
211 blocks_wide
= s
->avctx
->width
/ 4;
212 blocks_high
= s
->avctx
->height
/ 4;
213 total_blocks
= blocks_wide
* blocks_high
;
215 row_dec
= stride
+ 4;
217 for (block_y
= blocks_high
; block_y
> 0; block_y
--) {
218 block_ptr
= ((block_y
* 4) - 1) * stride
;
219 for (block_x
= blocks_wide
; block_x
> 0; block_x
--) {
220 /* check if this block should be skipped */
222 block_ptr
+= block_inc
;
228 pixel_ptr
= block_ptr
;
230 /* get the next two bytes in the encoded data stream */
232 byte_a
= s
->buf
[stream_ptr
++];
233 byte_b
= s
->buf
[stream_ptr
++];
235 /* check if the decode is finished */
236 if ((byte_a
== 0) && (byte_b
== 0) && (total_blocks
== 0)) {
238 } else if ((byte_b
& 0xFC) == 0x84) {
239 /* skip code, but don't count the current block */
240 skip_blocks
= ((byte_b
- 0x84) << 8) + byte_a
- 1;
241 } else if (byte_b
< 0x80) {
242 /* 2- or 8-color encoding modes */
243 flags
= (byte_b
<< 8) | byte_a
;
246 colors
[0] = LE_16(&s
->buf
[stream_ptr
]);
248 colors
[1] = LE_16(&s
->buf
[stream_ptr
]);
251 if (colors
[0] & 0x8000) {
252 /* 8-color encoding */
253 CHECK_STREAM_PTR(12);
254 colors
[2] = LE_16(&s
->buf
[stream_ptr
]);
256 colors
[3] = LE_16(&s
->buf
[stream_ptr
]);
258 colors
[4] = LE_16(&s
->buf
[stream_ptr
]);
260 colors
[5] = LE_16(&s
->buf
[stream_ptr
]);
262 colors
[6] = LE_16(&s
->buf
[stream_ptr
]);
264 colors
[7] = LE_16(&s
->buf
[stream_ptr
]);
267 for (pixel_y
= 0; pixel_y
< 4; pixel_y
++) {
268 for (pixel_x
= 0; pixel_x
< 4; pixel_x
++, flags
>>= 1)
269 pixels
[pixel_ptr
++] =
270 colors
[((pixel_y
& 0x2) << 1) +
271 (pixel_x
& 0x2) + ((flags
& 0x1) ^ 1)];
272 pixel_ptr
-= row_dec
;
275 /* 2-color encoding */
276 for (pixel_y
= 0; pixel_y
< 4; pixel_y
++) {
277 for (pixel_x
= 0; pixel_x
< 4; pixel_x
++, flags
>>= 1)
278 pixels
[pixel_ptr
++] = colors
[(flags
& 0x1) ^ 1];
279 pixel_ptr
-= row_dec
;
283 /* otherwise, it's a 1-color block */
284 colors
[0] = (byte_b
<< 8) | byte_a
;
286 for (pixel_y
= 0; pixel_y
< 4; pixel_y
++) {
287 for (pixel_x
= 0; pixel_x
< 4; pixel_x
++)
288 pixels
[pixel_ptr
++] = colors
[0];
289 pixel_ptr
-= row_dec
;
293 block_ptr
+= block_inc
;
299 static int msvideo1_decode_frame(AVCodecContext
*avctx
,
300 void *data
, int *data_size
,
301 uint8_t *buf
, int buf_size
)
303 Msvideo1Context
*s
= (Msvideo1Context
*)avctx
->priv_data
;
308 s
->frame
.reference
= 1;
309 s
->frame
.buffer_hints
= FF_BUFFER_HINTS_VALID
| FF_BUFFER_HINTS_PRESERVE
| FF_BUFFER_HINTS_REUSABLE
;
310 if (avctx
->reget_buffer(avctx
, &s
->frame
)) {
311 av_log(s
->avctx
, AV_LOG_ERROR
, "reget_buffer() failed\n");
316 msvideo1_decode_8bit(s
);
318 msvideo1_decode_16bit(s
);
320 *data_size
= sizeof(AVFrame
);
321 *(AVFrame
*)data
= s
->frame
;
323 /* report that the buffer was completely consumed */
327 static int msvideo1_decode_end(AVCodecContext
*avctx
)
329 Msvideo1Context
*s
= (Msvideo1Context
*)avctx
->priv_data
;
331 if (s
->frame
.data
[0])
332 avctx
->release_buffer(avctx
, &s
->frame
);
337 AVCodec msvideo1_decoder
= {
341 sizeof(Msvideo1Context
),
342 msvideo1_decode_init
,
345 msvideo1_decode_frame
,