annotate src/ffmpeg/libavcodec/msvideo1.c @ 808:e8776388b02a trunk

[svn] - add ffmpeg
author nenolod
date Mon, 12 Mar 2007 11:18:54 -0700
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
808
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
1 /*
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
2 * Microsoft Video-1 Decoder
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
3 * Copyright (C) 2003 the ffmpeg project
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
4 *
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
5 * This file is part of FFmpeg.
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
6 *
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
7 * FFmpeg is free software; you can redistribute it and/or
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
8 * modify it under the terms of the GNU Lesser General Public
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
9 * License as published by the Free Software Foundation; either
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
10 * version 2.1 of the License, or (at your option) any later version.
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
11 *
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
12 * FFmpeg is distributed in the hope that it will be useful,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
15 * Lesser General Public License for more details.
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
16 *
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
17 * You should have received a copy of the GNU Lesser General Public
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
18 * License along with FFmpeg; if not, write to the Free Software
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
20 *
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
21 */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
22
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
23 /**
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
24 * @file msvideo1.c
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
25 * Microsoft Video-1 Decoder by Mike Melanson (melanson@pcisys.net)
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
26 * For more information about the MS Video-1 format, visit:
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
27 * http://www.pcisys.net/~melanson/codecs/
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
28 *
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
29 * This decoder outputs either PAL8 or RGB555 data, depending on the
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
30 * whether a RGB palette was passed through palctrl;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
31 * if it's present, then the data is PAL8; RGB555 otherwise.
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
32 */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
33
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
34 #include <stdio.h>
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
35 #include <stdlib.h>
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
36 #include <string.h>
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
37 #include <unistd.h>
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
38
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
39 #include "common.h"
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
40 #include "avcodec.h"
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
41 #include "dsputil.h"
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
42
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
43 #define PALETTE_COUNT 256
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
44 #define CHECK_STREAM_PTR(n) \
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
45 if ((stream_ptr + n) > s->size ) { \
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
46 av_log(s->avctx, AV_LOG_ERROR, " MS Video-1 warning: stream_ptr out of bounds (%d >= %d)\n", \
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
47 stream_ptr + n, s->size); \
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
48 return; \
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
49 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
50
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
51 typedef struct Msvideo1Context {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
52
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
53 AVCodecContext *avctx;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
54 DSPContext dsp;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
55 AVFrame frame;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
56
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
57 unsigned char *buf;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
58 int size;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
59
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
60 int mode_8bit; /* if it's not 8-bit, it's 16-bit */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
61
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
62 } Msvideo1Context;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
63
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
64 static int msvideo1_decode_init(AVCodecContext *avctx)
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
65 {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
66 Msvideo1Context *s = (Msvideo1Context *)avctx->priv_data;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
67
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
68 s->avctx = avctx;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
69
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
70 /* figure out the colorspace based on the presence of a palette */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
71 if (s->avctx->palctrl) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
72 s->mode_8bit = 1;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
73 avctx->pix_fmt = PIX_FMT_PAL8;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
74 } else {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
75 s->mode_8bit = 0;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
76 avctx->pix_fmt = PIX_FMT_RGB555;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
77 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
78
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
79 avctx->has_b_frames = 0;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
80 dsputil_init(&s->dsp, avctx);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
81
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
82 s->frame.data[0] = NULL;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
83
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
84 return 0;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
85 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
86
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
87 static void msvideo1_decode_8bit(Msvideo1Context *s)
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
88 {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
89 int block_ptr, pixel_ptr;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
90 int total_blocks;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
91 int pixel_x, pixel_y; /* pixel width and height iterators */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
92 int block_x, block_y; /* block width and height iterators */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
93 int blocks_wide, blocks_high; /* width and height in 4x4 blocks */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
94 int block_inc;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
95 int row_dec;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
96
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
97 /* decoding parameters */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
98 int stream_ptr;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
99 unsigned char byte_a, byte_b;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
100 unsigned short flags;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
101 int skip_blocks;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
102 unsigned char colors[8];
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
103 unsigned char *pixels = s->frame.data[0];
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
104 int stride = s->frame.linesize[0];
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
105
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
106 stream_ptr = 0;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
107 skip_blocks = 0;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
108 blocks_wide = s->avctx->width / 4;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
109 blocks_high = s->avctx->height / 4;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
110 total_blocks = blocks_wide * blocks_high;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
111 block_inc = 4;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
112 row_dec = stride + 4;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
113
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
114 for (block_y = blocks_high; block_y > 0; block_y--) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
115 block_ptr = ((block_y * 4) - 1) * stride;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
116 for (block_x = blocks_wide; block_x > 0; block_x--) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
117 /* check if this block should be skipped */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
118 if (skip_blocks) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
119 block_ptr += block_inc;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
120 skip_blocks--;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
121 total_blocks--;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
122 continue;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
123 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
124
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
125 pixel_ptr = block_ptr;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
126
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
127 /* get the next two bytes in the encoded data stream */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
128 CHECK_STREAM_PTR(2);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
129 byte_a = s->buf[stream_ptr++];
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
130 byte_b = s->buf[stream_ptr++];
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
131
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
132 /* check if the decode is finished */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
133 if ((byte_a == 0) && (byte_b == 0) && (total_blocks == 0))
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
134 return;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
135 else if ((byte_b & 0xFC) == 0x84) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
136 /* skip code, but don't count the current block */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
137 skip_blocks = ((byte_b - 0x84) << 8) + byte_a - 1;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
138 } else if (byte_b < 0x80) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
139 /* 2-color encoding */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
140 flags = (byte_b << 8) | byte_a;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
141
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
142 CHECK_STREAM_PTR(2);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
143 colors[0] = s->buf[stream_ptr++];
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
144 colors[1] = s->buf[stream_ptr++];
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
145
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
146 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
147 for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
148 pixels[pixel_ptr++] = colors[(flags & 0x1) ^ 1];
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
149 pixel_ptr -= row_dec;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
150 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
151 } else if (byte_b >= 0x90) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
152 /* 8-color encoding */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
153 flags = (byte_b << 8) | byte_a;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
154
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
155 CHECK_STREAM_PTR(8);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
156 memcpy(colors, &s->buf[stream_ptr], 8);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
157 stream_ptr += 8;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
158
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
159 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
160 for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
161 pixels[pixel_ptr++] =
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
162 colors[((pixel_y & 0x2) << 1) +
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
163 (pixel_x & 0x2) + ((flags & 0x1) ^ 1)];
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
164 pixel_ptr -= row_dec;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
165 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
166 } else {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
167 /* 1-color encoding */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
168 colors[0] = byte_a;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
169
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
170 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
171 for (pixel_x = 0; pixel_x < 4; pixel_x++)
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
172 pixels[pixel_ptr++] = colors[0];
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
173 pixel_ptr -= row_dec;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
174 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
175 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
176
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
177 block_ptr += block_inc;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
178 total_blocks--;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
179 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
180 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
181
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
182 /* make the palette available on the way out */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
183 if (s->avctx->pix_fmt == PIX_FMT_PAL8) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
184 memcpy(s->frame.data[1], s->avctx->palctrl->palette, AVPALETTE_SIZE);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
185 if (s->avctx->palctrl->palette_changed) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
186 s->frame.palette_has_changed = 1;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
187 s->avctx->palctrl->palette_changed = 0;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
188 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
189 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
190 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
191
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
192 static void msvideo1_decode_16bit(Msvideo1Context *s)
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
193 {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
194 int block_ptr, pixel_ptr;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
195 int total_blocks;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
196 int pixel_x, pixel_y; /* pixel width and height iterators */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
197 int block_x, block_y; /* block width and height iterators */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
198 int blocks_wide, blocks_high; /* width and height in 4x4 blocks */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
199 int block_inc;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
200 int row_dec;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
201
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
202 /* decoding parameters */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
203 int stream_ptr;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
204 unsigned char byte_a, byte_b;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
205 unsigned short flags;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
206 int skip_blocks;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
207 unsigned short colors[8];
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
208 unsigned short *pixels = (unsigned short *)s->frame.data[0];
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
209 int stride = s->frame.linesize[0] / 2;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
210
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
211 stream_ptr = 0;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
212 skip_blocks = 0;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
213 blocks_wide = s->avctx->width / 4;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
214 blocks_high = s->avctx->height / 4;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
215 total_blocks = blocks_wide * blocks_high;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
216 block_inc = 4;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
217 row_dec = stride + 4;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
218
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
219 for (block_y = blocks_high; block_y > 0; block_y--) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
220 block_ptr = ((block_y * 4) - 1) * stride;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
221 for (block_x = blocks_wide; block_x > 0; block_x--) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
222 /* check if this block should be skipped */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
223 if (skip_blocks) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
224 block_ptr += block_inc;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
225 skip_blocks--;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
226 total_blocks--;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
227 continue;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
228 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
229
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
230 pixel_ptr = block_ptr;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
231
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
232 /* get the next two bytes in the encoded data stream */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
233 CHECK_STREAM_PTR(2);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
234 byte_a = s->buf[stream_ptr++];
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
235 byte_b = s->buf[stream_ptr++];
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
236
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
237 /* check if the decode is finished */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
238 if ((byte_a == 0) && (byte_b == 0) && (total_blocks == 0)) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
239 return;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
240 } else if ((byte_b & 0xFC) == 0x84) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
241 /* skip code, but don't count the current block */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
242 skip_blocks = ((byte_b - 0x84) << 8) + byte_a - 1;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
243 } else if (byte_b < 0x80) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
244 /* 2- or 8-color encoding modes */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
245 flags = (byte_b << 8) | byte_a;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
246
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
247 CHECK_STREAM_PTR(4);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
248 colors[0] = LE_16(&s->buf[stream_ptr]);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
249 stream_ptr += 2;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
250 colors[1] = LE_16(&s->buf[stream_ptr]);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
251 stream_ptr += 2;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
252
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
253 if (colors[0] & 0x8000) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
254 /* 8-color encoding */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
255 CHECK_STREAM_PTR(12);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
256 colors[2] = LE_16(&s->buf[stream_ptr]);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
257 stream_ptr += 2;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
258 colors[3] = LE_16(&s->buf[stream_ptr]);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
259 stream_ptr += 2;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
260 colors[4] = LE_16(&s->buf[stream_ptr]);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
261 stream_ptr += 2;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
262 colors[5] = LE_16(&s->buf[stream_ptr]);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
263 stream_ptr += 2;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
264 colors[6] = LE_16(&s->buf[stream_ptr]);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
265 stream_ptr += 2;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
266 colors[7] = LE_16(&s->buf[stream_ptr]);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
267 stream_ptr += 2;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
268
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
269 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
270 for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
271 pixels[pixel_ptr++] =
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
272 colors[((pixel_y & 0x2) << 1) +
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
273 (pixel_x & 0x2) + ((flags & 0x1) ^ 1)];
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
274 pixel_ptr -= row_dec;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
275 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
276 } else {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
277 /* 2-color encoding */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
278 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
279 for (pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
280 pixels[pixel_ptr++] = colors[(flags & 0x1) ^ 1];
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
281 pixel_ptr -= row_dec;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
282 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
283 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
284 } else {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
285 /* otherwise, it's a 1-color block */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
286 colors[0] = (byte_b << 8) | byte_a;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
287
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
288 for (pixel_y = 0; pixel_y < 4; pixel_y++) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
289 for (pixel_x = 0; pixel_x < 4; pixel_x++)
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
290 pixels[pixel_ptr++] = colors[0];
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
291 pixel_ptr -= row_dec;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
292 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
293 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
294
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
295 block_ptr += block_inc;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
296 total_blocks--;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
297 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
298 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
299 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
300
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
301 static int msvideo1_decode_frame(AVCodecContext *avctx,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
302 void *data, int *data_size,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
303 uint8_t *buf, int buf_size)
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
304 {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
305 Msvideo1Context *s = (Msvideo1Context *)avctx->priv_data;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
306
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
307 s->buf = buf;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
308 s->size = buf_size;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
309
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
310 s->frame.reference = 1;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
311 s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
312 if (avctx->reget_buffer(avctx, &s->frame)) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
313 av_log(s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
314 return -1;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
315 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
316
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
317 if (s->mode_8bit)
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
318 msvideo1_decode_8bit(s);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
319 else
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
320 msvideo1_decode_16bit(s);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
321
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
322 *data_size = sizeof(AVFrame);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
323 *(AVFrame*)data = s->frame;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
324
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
325 /* report that the buffer was completely consumed */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
326 return buf_size;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
327 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
328
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
329 static int msvideo1_decode_end(AVCodecContext *avctx)
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
330 {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
331 Msvideo1Context *s = (Msvideo1Context *)avctx->priv_data;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
332
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
333 if (s->frame.data[0])
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
334 avctx->release_buffer(avctx, &s->frame);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
335
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
336 return 0;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
337 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
338
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
339 AVCodec msvideo1_decoder = {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
340 "msvideo1",
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
341 CODEC_TYPE_VIDEO,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
342 CODEC_ID_MSVIDEO1,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
343 sizeof(Msvideo1Context),
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
344 msvideo1_decode_init,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
345 NULL,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
346 msvideo1_decode_end,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
347 msvideo1_decode_frame,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
348 CODEC_CAP_DR1,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
349 };