Statistics
| Branch: | Revision:

ffmpeg / libavcodec / msvideo1.c @ 11e29a41

History | View | Annotate | Download (12.5 KB)

1 2fdf638b Mike Melanson
/*
2
 * Microsoft Video-1 Decoder
3
 * Copyright (C) 2003 the ffmpeg project
4
 *
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.
9
 *
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.
14
 *
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
18
 *
19
 */
20
21
/**
22
 * @file msvideo1.c
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/
26
 *
27
 * This decoder outputs either PAL8 or RGB555 data, depending on the
28 875efafa Roberto Togni
 * whether a RGB palette was passed through palctrl;
29
 * if it's present, then the data is PAL8; RGB555 otherwise.
30 2fdf638b Mike Melanson
 */
31
32
#include <stdio.h>
33
#include <stdlib.h>
34
#include <string.h>
35
#include <unistd.h>
36
37
#include "common.h"
38
#include "avcodec.h"
39
#include "dsputil.h"
40
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 9b879566 Michel Bardiaux
    av_log(s->avctx, AV_LOG_ERROR, " MS Video-1 warning: stream_ptr out of bounds (%d >= %d)\n", \
46 2fdf638b Mike Melanson
      stream_ptr + n, s->size); \
47
    return; \
48
  }
49
50
#define COPY_PREV_BLOCK() \
51 e02c251e Roberto Togni
  if (!s->avctx->cr_available) {\
52 2fdf638b Mike Melanson
    pixel_ptr = block_ptr; \
53
    for (pixel_y = 0; pixel_y < 4; pixel_y++) { \
54
        for (pixel_x = 0; pixel_x < 4; pixel_x++, pixel_ptr++) \
55
            pixels[pixel_ptr] = prev_pixels[pixel_ptr]; \
56
        pixel_ptr -= row_dec; \
57 e02c251e Roberto Togni
    } \
58
  }
59 2fdf638b Mike Melanson
60
typedef struct Msvideo1Context {
61
62
    AVCodecContext *avctx;
63
    DSPContext dsp;
64
    AVFrame frame;
65
    AVFrame prev_frame;
66
67
    unsigned char *buf;
68
    int size;
69
70
    int mode_8bit;  /* if it's not 8-bit, it's 16-bit */
71
72
} Msvideo1Context;
73
74
static int msvideo1_decode_init(AVCodecContext *avctx)
75
{
76
    Msvideo1Context *s = (Msvideo1Context *)avctx->priv_data;
77
78
    s->avctx = avctx;
79
80 875efafa Roberto Togni
    /* figure out the colorspace based on the presence of a palette */
81
    if (s->avctx->palctrl) {
82 2fdf638b Mike Melanson
        s->mode_8bit = 1;
83
        avctx->pix_fmt = PIX_FMT_PAL8;
84
    } else {
85
        s->mode_8bit = 0;
86
        avctx->pix_fmt = PIX_FMT_RGB555;
87
    }
88
89
    avctx->has_b_frames = 0;
90
    dsputil_init(&s->dsp, avctx);
91
92
    s->frame.data[0] = s->prev_frame.data[0] = NULL;
93
94
    return 0;
95
}
96
97
static void msvideo1_decode_8bit(Msvideo1Context *s)
98
{
99
    int block_ptr, pixel_ptr;
100
    int total_blocks;
101
    int pixel_x, pixel_y;  /* pixel width and height iterators */
102
    int block_x, block_y;  /* block width and height iterators */
103
    int blocks_wide, blocks_high;  /* width and height in 4x4 blocks */
104
    int block_inc;
105
    int row_dec;
106
107
    /* decoding parameters */
108
    int stream_ptr;
109
    unsigned char byte_a, byte_b;
110
    unsigned short flags;
111
    int skip_blocks;
112
    unsigned char colors[8];
113
    unsigned char *pixels = s->frame.data[0];
114
    unsigned char *prev_pixels = s->prev_frame.data[0];
115
    int stride = s->frame.linesize[0];
116
117
    stream_ptr = 0;
118
    skip_blocks = 0;
119
    blocks_wide = s->avctx->width / 4;
120
    blocks_high = s->avctx->height / 4;
121
    total_blocks = blocks_wide * blocks_high;
122
    block_inc = 4;
123
    row_dec = stride + 4;
124
125
    for (block_y = blocks_high; block_y > 0; block_y--) {
126
        block_ptr = ((block_y * 4) - 1) * stride;
127
        for (block_x = blocks_wide; block_x > 0; block_x--) {
128
            /* check if this block should be skipped */
129
            if (skip_blocks) {
130
                COPY_PREV_BLOCK();
131
                block_ptr += block_inc;
132
                skip_blocks--;
133
                total_blocks--;
134
                continue;
135
            }
136
137
            pixel_ptr = block_ptr;
138
139
            /* get the next two bytes in the encoded data stream */
140
            CHECK_STREAM_PTR(2);
141
            byte_a = s->buf[stream_ptr++];
142
            byte_b = s->buf[stream_ptr++];
143
144
            /* check if the decode is finished */
145
            if ((byte_a == 0) && (byte_b == 0) && (total_blocks == 0))
146
                return;
147
            else if ((byte_b & 0xFC) == 0x84) {
148
                /* skip code, but don't count the current block */
149
                skip_blocks = ((byte_b - 0x84) << 8) + byte_a - 1;
150
                COPY_PREV_BLOCK();
151
            } else if (byte_b < 0x80) {
152
                /* 2-color encoding */
153
                flags = (byte_b << 8) | byte_a;
154
155
                CHECK_STREAM_PTR(2);
156
                colors[0] = s->buf[stream_ptr++];
157
                colors[1] = s->buf[stream_ptr++];
158
159
                for (pixel_y = 0; pixel_y < 4; pixel_y++) {
160
                    for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
161
                        pixels[pixel_ptr++] = colors[(flags & 0x1) ^ 1];
162
                    pixel_ptr -= row_dec;
163
                }
164
            } else if (byte_b >= 0x90) {
165
                /* 8-color encoding */
166
                flags = (byte_b << 8) | byte_a;
167
168
                CHECK_STREAM_PTR(8);
169
                memcpy(colors, &s->buf[stream_ptr], 8);
170
                stream_ptr += 8;
171
172
                for (pixel_y = 0; pixel_y < 4; pixel_y++) {
173
                    for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
174
                        pixels[pixel_ptr++] = 
175
                            colors[((pixel_y & 0x2) << 1) + 
176
                                (pixel_x & 0x2) + ((flags & 0x1) ^ 1)];
177
                    pixel_ptr -= row_dec;
178
                }
179
            } else {
180
                /* 1-color encoding */
181
                colors[0] = byte_a;
182
183
                for (pixel_y = 0; pixel_y < 4; pixel_y++) {
184
                    for (pixel_x = 0; pixel_x < 4; pixel_x++)
185
                        pixels[pixel_ptr++] = colors[0];
186
                    pixel_ptr -= row_dec;
187
                }
188
            }
189
190
            block_ptr += block_inc;
191
            total_blocks--;
192
        }
193
    }
194
195
    /* make the palette available on the way out */
196 875efafa Roberto Togni
    if (s->avctx->pix_fmt == PIX_FMT_PAL8) {
197
        memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
198
        if (s->avctx->palctrl->palette_changed) {
199
            s->frame.palette_has_changed = 1;
200
            s->avctx->palctrl->palette_changed = 0;
201
        }
202
    }
203 2fdf638b Mike Melanson
}
204
205
static void msvideo1_decode_16bit(Msvideo1Context *s)
206
{
207
    int block_ptr, pixel_ptr;
208
    int total_blocks;
209
    int pixel_x, pixel_y;  /* pixel width and height iterators */
210
    int block_x, block_y;  /* block width and height iterators */
211
    int blocks_wide, blocks_high;  /* width and height in 4x4 blocks */
212
    int block_inc;
213
    int row_dec;
214
215
    /* decoding parameters */
216
    int stream_ptr;
217
    unsigned char byte_a, byte_b;
218
    unsigned short flags;
219
    int skip_blocks;
220
    unsigned short colors[8];
221
    unsigned short *pixels = (unsigned short *)s->frame.data[0];
222
    unsigned short *prev_pixels = (unsigned short *)s->prev_frame.data[0];
223
    int stride = s->frame.linesize[0] / 2;
224
225
    stream_ptr = 0;
226
    skip_blocks = 0;
227
    blocks_wide = s->avctx->width / 4;
228
    blocks_high = s->avctx->height / 4;
229
    total_blocks = blocks_wide * blocks_high;
230
    block_inc = 4;
231
    row_dec = stride + 4;
232
233
    for (block_y = blocks_high; block_y > 0; block_y--) {
234
        block_ptr = ((block_y * 4) - 1) * stride;
235
        for (block_x = blocks_wide; block_x > 0; block_x--) {
236
            /* check if this block should be skipped */
237
            if (skip_blocks) {
238
                COPY_PREV_BLOCK();
239
                block_ptr += block_inc;
240
                skip_blocks--;
241
                total_blocks--;
242
                continue;
243
            }
244
245
            pixel_ptr = block_ptr;
246
247
            /* get the next two bytes in the encoded data stream */
248
            CHECK_STREAM_PTR(2);
249
            byte_a = s->buf[stream_ptr++];
250
            byte_b = s->buf[stream_ptr++];
251
252
            /* check if the decode is finished */
253
            if ((byte_a == 0) && (byte_b == 0) && (total_blocks == 0)) {
254
                return;
255
            } else if ((byte_b & 0xFC) == 0x84) {
256
                /* skip code, but don't count the current block */
257
                skip_blocks = ((byte_b - 0x84) << 8) + byte_a - 1;
258
                COPY_PREV_BLOCK();
259
            } else if (byte_b < 0x80) {
260
                /* 2- or 8-color encoding modes */
261
                flags = (byte_b << 8) | byte_a;
262
263
                CHECK_STREAM_PTR(4);
264
                colors[0] = LE_16(&s->buf[stream_ptr]);
265
                stream_ptr += 2;
266
                colors[1] = LE_16(&s->buf[stream_ptr]);
267
                stream_ptr += 2;
268
269
                if (colors[0] & 0x8000) {
270
                    /* 8-color encoding */
271
                    CHECK_STREAM_PTR(12);
272
                    colors[2] = LE_16(&s->buf[stream_ptr]);
273
                    stream_ptr += 2;
274
                    colors[3] = LE_16(&s->buf[stream_ptr]);
275
                    stream_ptr += 2;
276
                    colors[4] = LE_16(&s->buf[stream_ptr]);
277
                    stream_ptr += 2;
278
                    colors[5] = LE_16(&s->buf[stream_ptr]);
279
                    stream_ptr += 2;
280
                    colors[6] = LE_16(&s->buf[stream_ptr]);
281
                    stream_ptr += 2;
282
                    colors[7] = LE_16(&s->buf[stream_ptr]);
283
                    stream_ptr += 2;
284
285
                    for (pixel_y = 0; pixel_y < 4; pixel_y++) {
286
                        for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
287
                            pixels[pixel_ptr++] = 
288
                                colors[((pixel_y & 0x2) << 1) + 
289
                                    (pixel_x & 0x2) + ((flags & 0x1) ^ 1)];
290
                        pixel_ptr -= row_dec;
291
                    }
292
                } else {
293
                    /* 2-color encoding */
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++] = colors[(flags & 0x1) ^ 1];
297
                        pixel_ptr -= row_dec;
298
                    }
299
                }
300
            } else {
301
                /* otherwise, it's a 1-color block */
302
                colors[0] = (byte_b << 8) | byte_a;
303
304
                for (pixel_y = 0; pixel_y < 4; pixel_y++) {
305
                    for (pixel_x = 0; pixel_x < 4; pixel_x++)
306
                        pixels[pixel_ptr++] = colors[0];
307
                    pixel_ptr -= row_dec;
308
                }
309
            }
310
311
            block_ptr += block_inc;
312
            total_blocks--;
313
        }
314
    }
315
}
316
317
static int msvideo1_decode_frame(AVCodecContext *avctx,
318
                                void *data, int *data_size,
319
                                uint8_t *buf, int buf_size)
320
{
321
    Msvideo1Context *s = (Msvideo1Context *)avctx->priv_data;
322
323 e02c251e Roberto Togni
        /* no supplementary picture */
324
        if (buf_size == 0)
325
                return 0;
326
327 2fdf638b Mike Melanson
    s->buf = buf;
328
    s->size = buf_size;
329
330 e02c251e Roberto Togni
        s->frame.reference = 1;
331
        s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE;
332
    if (avctx->cr_available)
333
        s->frame.buffer_hints |= FF_BUFFER_HINTS_REUSABLE;
334
    else
335
        s->frame.buffer_hints |= FF_BUFFER_HINTS_READABLE;
336 2fdf638b Mike Melanson
    if (avctx->get_buffer(avctx, &s->frame)) {
337 9b879566 Michel Bardiaux
        av_log(s->avctx, AV_LOG_ERROR, "  MS Video-1 Video: get_buffer() failed\n");
338 2fdf638b Mike Melanson
        return -1;
339
    }
340
341 875efafa Roberto Togni
    if (s->prev_frame.data[0] &&(s->frame.linesize[0] != s->prev_frame.linesize[0]))
342 9b879566 Michel Bardiaux
        av_log(avctx, AV_LOG_ERROR, "  MS Video-1: Buffer linesize changed: current %u, previous %u.\n"
343 875efafa Roberto Togni
                "              Expect wrong image and/or crash!\n",
344
                s->frame.linesize[0], s->prev_frame.linesize[0]);
345
346 2fdf638b Mike Melanson
    if (s->mode_8bit)
347
        msvideo1_decode_8bit(s);
348
    else
349
        msvideo1_decode_16bit(s);
350
351
    if (s->prev_frame.data[0])
352
        avctx->release_buffer(avctx, &s->prev_frame);
353
354
    /* shuffle frames */
355 e02c251e Roberto Togni
  if (!avctx->cr_available)
356 2fdf638b Mike Melanson
    s->prev_frame = s->frame;
357
358
    *data_size = sizeof(AVFrame);
359
    *(AVFrame*)data = s->frame;
360
361
    /* report that the buffer was completely consumed */
362
    return buf_size;
363
}
364
365
static int msvideo1_decode_end(AVCodecContext *avctx)
366
{
367
    Msvideo1Context *s = (Msvideo1Context *)avctx->priv_data;
368
369
    if (s->prev_frame.data[0])
370
        avctx->release_buffer(avctx, &s->prev_frame);
371
372
    return 0;
373
}
374
375
AVCodec msvideo1_decoder = {
376
    "msvideo1",
377
    CODEC_TYPE_VIDEO,
378
    CODEC_ID_MSVIDEO1,
379
    sizeof(Msvideo1Context),
380
    msvideo1_decode_init,
381
    NULL,
382
    msvideo1_decode_end,
383
    msvideo1_decode_frame,
384 e02c251e Roberto Togni
    CODEC_CAP_DR1 | CODEC_CAP_CR,
385 2fdf638b Mike Melanson
};