Statistics
| Branch: | Revision:

ffmpeg / libavcodec / msvideo1.c @ 5509bffa

History | View | Annotate | Download (11.1 KB)

1
/*
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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
 * whether a RGB palette was passed through palctrl;
29
 * if it's present, then the data is PAL8; RGB555 otherwise.
30
 */
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 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); \
46
    return; \
47
  }
48

    
49
typedef struct Msvideo1Context {
50

    
51
    AVCodecContext *avctx;
52
    DSPContext dsp;
53
    AVFrame frame;
54

    
55
    unsigned char *buf;
56
    int size;
57

    
58
    int mode_8bit;  /* if it's not 8-bit, it's 16-bit */
59

    
60
} Msvideo1Context;
61

    
62
static int msvideo1_decode_init(AVCodecContext *avctx)
63
{
64
    Msvideo1Context *s = (Msvideo1Context *)avctx->priv_data;
65

    
66
    s->avctx = avctx;
67

    
68
    /* figure out the colorspace based on the presence of a palette */
69
    if (s->avctx->palctrl) {
70
        s->mode_8bit = 1;
71
        avctx->pix_fmt = PIX_FMT_PAL8;
72
    } else {
73
        s->mode_8bit = 0;
74
        avctx->pix_fmt = PIX_FMT_RGB555;
75
    }
76

    
77
    avctx->has_b_frames = 0;
78
    dsputil_init(&s->dsp, avctx);
79

    
80
    s->frame.data[0] = NULL;
81

    
82
    return 0;
83
}
84

    
85
static void msvideo1_decode_8bit(Msvideo1Context *s)
86
{
87
    int block_ptr, pixel_ptr;
88
    int total_blocks;
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 */
92
    int block_inc;
93
    int row_dec;
94

    
95
    /* decoding parameters */
96
    int stream_ptr;
97
    unsigned char byte_a, byte_b;
98
    unsigned short flags;
99
    int skip_blocks;
100
    unsigned char colors[8];
101
    unsigned char *pixels = s->frame.data[0];
102
    int stride = s->frame.linesize[0];
103

    
104
    stream_ptr = 0;
105
    skip_blocks = 0;
106
    blocks_wide = s->avctx->width / 4;
107
    blocks_high = s->avctx->height / 4;
108
    total_blocks = blocks_wide * blocks_high;
109
    block_inc = 4;
110
    row_dec = stride + 4;
111

    
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 */
116
            if (skip_blocks) {
117
                block_ptr += block_inc;
118
                skip_blocks--;
119
                total_blocks--;
120
                continue;
121
            }
122

    
123
            pixel_ptr = block_ptr;
124

    
125
            /* get the next two bytes in the encoded data stream */
126
            CHECK_STREAM_PTR(2);
127
            byte_a = s->buf[stream_ptr++];
128
            byte_b = s->buf[stream_ptr++];
129

    
130
            /* check if the decode is finished */
131
            if ((byte_a == 0) && (byte_b == 0) && (total_blocks == 0))
132
                return;
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;
139

    
140
                CHECK_STREAM_PTR(2);
141
                colors[0] = s->buf[stream_ptr++];
142
                colors[1] = s->buf[stream_ptr++];
143

    
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;
148
                }
149
            } else if (byte_b >= 0x90) {
150
                /* 8-color encoding */
151
                flags = (byte_b << 8) | byte_a;
152

    
153
                CHECK_STREAM_PTR(8);
154
                memcpy(colors, &s->buf[stream_ptr], 8);
155
                stream_ptr += 8;
156

    
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;
163
                }
164
            } else {
165
                /* 1-color encoding */
166
                colors[0] = byte_a;
167

    
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;
172
                }
173
            }
174

    
175
            block_ptr += block_inc;
176
            total_blocks--;
177
        }
178
    }
179

    
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;
186
        }
187
    }
188
}
189

    
190
static void msvideo1_decode_16bit(Msvideo1Context *s)
191
{
192
    int block_ptr, pixel_ptr;
193
    int total_blocks;
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 */
197
    int block_inc;
198
    int row_dec;
199

    
200
    /* decoding parameters */
201
    int stream_ptr;
202
    unsigned char byte_a, byte_b;
203
    unsigned short flags;
204
    int skip_blocks;
205
    unsigned short colors[8];
206
    unsigned short *pixels = (unsigned short *)s->frame.data[0];
207
    int stride = s->frame.linesize[0] / 2;
208

    
209
    stream_ptr = 0;
210
    skip_blocks = 0;
211
    blocks_wide = s->avctx->width / 4;
212
    blocks_high = s->avctx->height / 4;
213
    total_blocks = blocks_wide * blocks_high;
214
    block_inc = 4;
215
    row_dec = stride + 4;
216

    
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 */
221
            if (skip_blocks) {
222
                block_ptr += block_inc;
223
                skip_blocks--;
224
                total_blocks--;
225
                continue;
226
            }
227

    
228
            pixel_ptr = block_ptr;
229

    
230
            /* get the next two bytes in the encoded data stream */
231
            CHECK_STREAM_PTR(2);
232
            byte_a = s->buf[stream_ptr++];
233
            byte_b = s->buf[stream_ptr++];
234

    
235
            /* check if the decode is finished */
236
            if ((byte_a == 0) && (byte_b == 0) && (total_blocks == 0)) {
237
                return;
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;
244

    
245
                CHECK_STREAM_PTR(4);
246
                colors[0] = LE_16(&s->buf[stream_ptr]);
247
                stream_ptr += 2;
248
                colors[1] = LE_16(&s->buf[stream_ptr]);
249
                stream_ptr += 2;
250

    
251
                if (colors[0] & 0x8000) {
252
                    /* 8-color encoding */
253
                    CHECK_STREAM_PTR(12);
254
                    colors[2] = LE_16(&s->buf[stream_ptr]);
255
                    stream_ptr += 2;
256
                    colors[3] = LE_16(&s->buf[stream_ptr]);
257
                    stream_ptr += 2;
258
                    colors[4] = LE_16(&s->buf[stream_ptr]);
259
                    stream_ptr += 2;
260
                    colors[5] = LE_16(&s->buf[stream_ptr]);
261
                    stream_ptr += 2;
262
                    colors[6] = LE_16(&s->buf[stream_ptr]);
263
                    stream_ptr += 2;
264
                    colors[7] = LE_16(&s->buf[stream_ptr]);
265
                    stream_ptr += 2;
266

    
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;
273
                    }
274
                } else {
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;
280
                    }
281
                }
282
            } else {
283
                /* otherwise, it's a 1-color block */
284
                colors[0] = (byte_b << 8) | byte_a;
285

    
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;
290
                }
291
            }
292

    
293
            block_ptr += block_inc;
294
            total_blocks--;
295
        }
296
    }
297
}
298

    
299
static int msvideo1_decode_frame(AVCodecContext *avctx,
300
                                void *data, int *data_size,
301
                                uint8_t *buf, int buf_size)
302
{
303
    Msvideo1Context *s = (Msvideo1Context *)avctx->priv_data;
304

    
305
    s->buf = buf;
306
    s->size = buf_size;
307

    
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");
312
        return -1;
313
    }
314

    
315
    if (s->mode_8bit)
316
        msvideo1_decode_8bit(s);
317
    else
318
        msvideo1_decode_16bit(s);
319

    
320
    *data_size = sizeof(AVFrame);
321
    *(AVFrame*)data = s->frame;
322

    
323
    /* report that the buffer was completely consumed */
324
    return buf_size;
325
}
326

    
327
static int msvideo1_decode_end(AVCodecContext *avctx)
328
{
329
    Msvideo1Context *s = (Msvideo1Context *)avctx->priv_data;
330

    
331
    if (s->frame.data[0])
332
        avctx->release_buffer(avctx, &s->frame);
333

    
334
    return 0;
335
}
336

    
337
AVCodec msvideo1_decoder = {
338
    "msvideo1",
339
    CODEC_TYPE_VIDEO,
340
    CODEC_ID_MSVIDEO1,
341
    sizeof(Msvideo1Context),
342
    msvideo1_decode_init,
343
    NULL,
344
    msvideo1_decode_end,
345
    msvideo1_decode_frame,
346
    CODEC_CAP_DR1,
347
};