annotate motionpixels.c @ 7744:7477cbdacb20 libavcodec

Fix lossless jpeg encoder to comply to spec and store full redundant residuals, Note this does not change RGB32 as we need to check this against some decoder that supports it.
author michael
date Sat, 30 Aug 2008 20:39:12 +0000
parents 21f5d934ccbd
children bf274494b66e
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
7231
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
1 /*
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
2 * Motion Pixels Video Decoder
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
3 * Copyright (c) 2008 Gregory Montoir (cyx@users.sourceforge.net)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
4 *
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
5 * This file is part of FFmpeg.
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
6 *
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
7 * FFmpeg is free software; you can redistribute it and/or
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
8 * modify it under the terms of the GNU Lesser General Public
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
9 * License as published by the Free Software Foundation; either
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
10 * version 2.1 of the License, or (at your option) any later version.
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
11 *
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
12 * FFmpeg is distributed in the hope that it will be useful,
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
15 * Lesser General Public License for more details.
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
16 *
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
17 * You should have received a copy of the GNU Lesser General Public
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
18 * License along with FFmpeg; if not, write to the Free Software
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
20 */
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
21
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
22 #include "avcodec.h"
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
23 #include "bitstream.h"
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
24 #include "dsputil.h"
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
25
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
26 #define MAX_HUFF_CODES 16
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
27
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
28 typedef struct YuvPixel {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
29 int8_t y, v, u;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
30 } YuvPixel;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
31
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
32 typedef struct HuffCode {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
33 int code;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
34 uint8_t size;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
35 uint8_t delta;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
36 } HuffCode;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
37
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
38 typedef struct MotionPixelsContext {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
39 AVCodecContext *avctx;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
40 AVFrame frame;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
41 DSPContext dsp;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
42 uint8_t *changes_map;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
43 int offset_bits_len;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
44 int codes_count, current_codes_count;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
45 int max_codes_bits;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
46 HuffCode codes[MAX_HUFF_CODES];
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
47 VLC vlc;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
48 YuvPixel *vpt, *hpt;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
49 uint8_t gradient_scale[3];
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
50 uint8_t *bswapbuf;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
51 int bswapbuf_size;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
52 } MotionPixelsContext;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
53
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
54 static YuvPixel mp_rgb_yuv_table[1 << 15];
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
55
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
56 static int mp_yuv_to_rgb(int y, int v, int u, int clip_rgb) {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
57 static const uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
58 int r, g, b;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
59
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
60 r = (1000 * y + 701 * v) / 1000;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
61 g = (1000 * y - 357 * v - 172 * u) / 1000;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
62 b = (1000 * y + 886 * u) / 1000;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
63 if (clip_rgb)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
64 return ((cm[r * 8] & 0xF8) << 7) | ((cm[g * 8] & 0xF8) << 2) | (cm[b * 8] >> 3);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
65 if ((unsigned)r < 32 && (unsigned)g < 32 && (unsigned)b < 32)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
66 return (r << 10) | (g << 5) | b;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
67 return 1 << 15;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
68 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
69
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
70 static void mp_set_zero_yuv(YuvPixel *p)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
71 {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
72 int i, j;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
73
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
74 for (i = 0; i < 31; ++i) {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
75 for (j = 31; j > i; --j)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
76 if (!(p[j].u | p[j].v | p[j].y))
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
77 p[j] = p[j - 1];
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
78 for (j = 0; j < 31 - i; ++j)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
79 if (!(p[j].u | p[j].v | p[j].y))
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
80 p[j] = p[j + 1];
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
81 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
82 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
83
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
84 static void mp_build_rgb_yuv_table(YuvPixel *p)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
85 {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
86 int y, v, u, i;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
87
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
88 for (y = 0; y <= 31; ++y)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
89 for (v = -31; v <= 31; ++v)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
90 for (u = -31; u <= 31; ++u) {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
91 i = mp_yuv_to_rgb(y, v, u, 0);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
92 if (i < (1 << 15) && !(p[i].u | p[i].v | p[i].y)) {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
93 p[i].y = y;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
94 p[i].v = v;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
95 p[i].u = u;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
96 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
97 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
98 for (i = 0; i < 1024; ++i)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
99 mp_set_zero_yuv(p + i * 32);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
100 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
101
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
102 static av_cold int mp_decode_init(AVCodecContext *avctx)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
103 {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
104 MotionPixelsContext *mp = avctx->priv_data;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
105
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
106 if (!mp_rgb_yuv_table[0].u) {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
107 mp_build_rgb_yuv_table(mp_rgb_yuv_table);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
108 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
109 mp->avctx = avctx;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
110 dsputil_init(&mp->dsp, avctx);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
111 mp->changes_map = av_mallocz(avctx->width * avctx->height);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
112 mp->offset_bits_len = av_log2(avctx->width * avctx->height) + 1;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
113 mp->vpt = av_mallocz(avctx->height * sizeof(YuvPixel));
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
114 mp->hpt = av_mallocz(avctx->height * avctx->width / 16 * sizeof(YuvPixel));
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
115 return 0;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
116 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
117
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
118 static void mp_read_changes_map(MotionPixelsContext *mp, GetBitContext *gb, int count, int bits_len, int read_color)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
119 {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
120 uint16_t *pixels;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
121 int offset, w, h, color = 0, x, y, i;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
122
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
123 while (count--) {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
124 offset = get_bits_long(gb, mp->offset_bits_len);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
125 w = get_bits(gb, bits_len) + 1;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
126 h = get_bits(gb, bits_len) + 1;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
127 if (read_color)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
128 color = get_bits(gb, 15);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
129 x = offset % mp->avctx->width;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
130 y = offset / mp->avctx->width;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
131 if (y >= mp->avctx->height)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
132 continue;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
133 w = FFMIN(w, mp->avctx->width - x);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
134 h = FFMIN(h, mp->avctx->height - y);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
135 pixels = (uint16_t *)&mp->frame.data[0][y * mp->frame.linesize[0] + x * 2];
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
136 while (h--) {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
137 mp->changes_map[offset] = w;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
138 if (read_color)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
139 for (i = 0; i < w; ++i)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
140 pixels[i] = color;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
141 offset += mp->avctx->width;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
142 pixels += mp->frame.linesize[0] / 2;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
143 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
144 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
145 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
146
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
147 static void mp_get_code(MotionPixelsContext *mp, GetBitContext *gb, int size, int code)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
148 {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
149 while (get_bits1(gb)) {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
150 ++size;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
151 if (size > mp->max_codes_bits) {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
152 av_log(mp->avctx, AV_LOG_ERROR, "invalid code size %d/%d\n", size, mp->max_codes_bits);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
153 return;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
154 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
155 code <<= 1;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
156 mp_get_code(mp, gb, size, code + 1);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
157 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
158 if (mp->current_codes_count >= MAX_HUFF_CODES) {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
159 av_log(mp->avctx, AV_LOG_ERROR, "too many codes\n");
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
160 return;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
161 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
162 mp->codes[mp->current_codes_count ].code = code;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
163 mp->codes[mp->current_codes_count++].size = size;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
164 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
165
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
166 static void mp_read_codes_table(MotionPixelsContext *mp, GetBitContext *gb)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
167 {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
168 if (mp->codes_count == 1) {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
169 mp->codes[0].delta = get_bits(gb, 4);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
170 } else {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
171 int i;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
172
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
173 mp->max_codes_bits = get_bits(gb, 4);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
174 for (i = 0; i < mp->codes_count; ++i)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
175 mp->codes[i].delta = get_bits(gb, 4);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
176 mp->current_codes_count = 0;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
177 mp_get_code(mp, gb, 0, 0);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
178 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
179 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
180
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
181 static int mp_gradient(MotionPixelsContext *mp, int component, int v)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
182 {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
183 int delta;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
184
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
185 delta = (v - 7) * mp->gradient_scale[component];
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
186 mp->gradient_scale[component] = (v == 0 || v == 14) ? 2 : 1;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
187 return delta;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
188 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
189
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
190 static YuvPixel mp_get_yuv_from_rgb(MotionPixelsContext *mp, int x, int y)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
191 {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
192 int color;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
193
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
194 color = *(uint16_t *)&mp->frame.data[0][y * mp->frame.linesize[0] + x * 2];
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
195 return mp_rgb_yuv_table[color];
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
196 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
197
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
198 static void mp_set_rgb_from_yuv(MotionPixelsContext *mp, int x, int y, const YuvPixel *p)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
199 {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
200 int color;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
201
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
202 color = mp_yuv_to_rgb(p->y, p->v, p->u, 1);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
203 *(uint16_t *)&mp->frame.data[0][y * mp->frame.linesize[0] + x * 2] = color;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
204 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
205
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
206 static int mp_get_vlc(MotionPixelsContext *mp, GetBitContext *gb)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
207 {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
208 int i;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
209
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
210 i = (mp->codes_count == 1) ? 0 : get_vlc2(gb, mp->vlc.table, mp->max_codes_bits, 1);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
211 return mp->codes[i].delta;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
212 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
213
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
214 static void mp_decode_line(MotionPixelsContext *mp, GetBitContext *gb, int y)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
215 {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
216 YuvPixel p;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
217 const int y0 = y * mp->avctx->width;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
218 int w, i, x = 0;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
219
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
220 p = mp->vpt[y];
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
221 if (mp->changes_map[y0 + x] == 0) {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
222 memset(mp->gradient_scale, 1, sizeof(mp->gradient_scale));
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
223 ++x;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
224 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
225 while (x < mp->avctx->width) {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
226 w = mp->changes_map[y0 + x];
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
227 if (w != 0) {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
228 if ((y & 3) == 0) {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
229 if (mp->changes_map[y0 + x + mp->avctx->width] < w ||
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
230 mp->changes_map[y0 + x + mp->avctx->width * 2] < w ||
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
231 mp->changes_map[y0 + x + mp->avctx->width * 3] < w) {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
232 for (i = (x + 3) & ~3; i < x + w; i += 4) {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
233 mp->hpt[((y / 4) * mp->avctx->width + i) / 4] = mp_get_yuv_from_rgb(mp, i, y);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
234 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
235 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
236 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
237 x += w;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
238 memset(mp->gradient_scale, 1, sizeof(mp->gradient_scale));
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
239 p = mp_get_yuv_from_rgb(mp, x - 1, y);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
240 } else {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
241 p.y += mp_gradient(mp, 0, mp_get_vlc(mp, gb));
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
242 if ((x & 3) == 0) {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
243 if ((y & 3) == 0) {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
244 p.v += mp_gradient(mp, 1, mp_get_vlc(mp, gb));
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
245 p.u += mp_gradient(mp, 2, mp_get_vlc(mp, gb));
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
246 mp->hpt[((y / 4) * mp->avctx->width + x) / 4] = p;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
247 } else {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
248 p.v = mp->hpt[((y / 4) * mp->avctx->width + x) / 4].v;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
249 p.u = mp->hpt[((y / 4) * mp->avctx->width + x) / 4].u;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
250 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
251 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
252 mp_set_rgb_from_yuv(mp, x, y, &p);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
253 ++x;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
254 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
255 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
256 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
257
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
258 static void mp_decode_frame_helper(MotionPixelsContext *mp, GetBitContext *gb)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
259 {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
260 YuvPixel p;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
261 int y, y0;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
262
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
263 for (y = 0; y < mp->avctx->height; ++y) {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
264 if (mp->changes_map[y * mp->avctx->width] != 0) {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
265 memset(mp->gradient_scale, 1, sizeof(mp->gradient_scale));
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
266 p = mp_get_yuv_from_rgb(mp, 0, y);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
267 } else {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
268 p.y += mp_gradient(mp, 0, mp_get_vlc(mp, gb));
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
269 if ((y & 3) == 0) {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
270 p.v += mp_gradient(mp, 1, mp_get_vlc(mp, gb));
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
271 p.u += mp_gradient(mp, 2, mp_get_vlc(mp, gb));
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
272 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
273 mp->vpt[y] = p;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
274 mp_set_rgb_from_yuv(mp, 0, y, &p);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
275 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
276 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
277 for (y0 = 0; y0 < 2; ++y0)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
278 for (y = y0; y < mp->avctx->height; y += 2)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
279 mp_decode_line(mp, gb, y);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
280 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
281
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
282 static int mp_decode_frame(AVCodecContext *avctx,
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
283 void *data, int *data_size,
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
284 const uint8_t *buf, int buf_size)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
285 {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
286 MotionPixelsContext *mp = avctx->priv_data;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
287 GetBitContext gb;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
288 int i, count1, count2, sz;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
289
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
290 mp->frame.reference = 1;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
291 mp->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
292 if (avctx->reget_buffer(avctx, &mp->frame)) {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
293 av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
294 return -1;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
295 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
296
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
297 /* le32 bitstream msb first */
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
298 mp->bswapbuf = av_fast_realloc(mp->bswapbuf, &mp->bswapbuf_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
299 mp->dsp.bswap_buf((uint32_t *)mp->bswapbuf, (const uint32_t *)buf, buf_size / 4);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
300 if (buf_size & 3)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
301 memcpy(mp->bswapbuf + (buf_size & ~3), buf + (buf_size & ~3), buf_size & 3);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
302 init_get_bits(&gb, mp->bswapbuf, buf_size * 8);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
303
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
304 memset(mp->changes_map, 0, avctx->width * avctx->height);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
305 for (i = !(avctx->extradata[1] & 2); i < 2; ++i) {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
306 count1 = get_bits(&gb, 12);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
307 count2 = get_bits(&gb, 12);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
308 mp_read_changes_map(mp, &gb, count1, 8, i);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
309 mp_read_changes_map(mp, &gb, count2, 4, i);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
310 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
311
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
312 mp->codes_count = get_bits(&gb, 4);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
313 if (mp->codes_count == 0)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
314 goto end;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
315
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
316 if (mp->changes_map[0] == 0) {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
317 *(uint16_t *)mp->frame.data[0] = get_bits(&gb, 15);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
318 mp->changes_map[0] = 1;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
319 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
320 mp_read_codes_table(mp, &gb);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
321
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
322 sz = get_bits(&gb, 18);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
323 if (avctx->extradata[0] != 5)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
324 sz += get_bits(&gb, 18);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
325 if (sz == 0)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
326 goto end;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
327
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
328 init_vlc(&mp->vlc, mp->max_codes_bits, mp->codes_count, &mp->codes[0].size, sizeof(HuffCode), 1, &mp->codes[0].code, sizeof(HuffCode), 4, 0);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
329 mp_decode_frame_helper(mp, &gb);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
330 free_vlc(&mp->vlc);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
331
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
332 end:
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
333 *data_size = sizeof(AVFrame);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
334 *(AVFrame *)data = mp->frame;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
335 return buf_size;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
336 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
337
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
338 static av_cold int mp_decode_end(AVCodecContext *avctx)
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
339 {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
340 MotionPixelsContext *mp = avctx->priv_data;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
341
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
342 av_freep(&mp->changes_map);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
343 av_freep(&mp->vpt);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
344 av_freep(&mp->hpt);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
345 av_freep(&mp->bswapbuf);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
346 if (mp->frame.data[0])
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
347 avctx->release_buffer(avctx, &mp->frame);
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
348
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
349 return 0;
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
350 }
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
351
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
352 AVCodec motionpixels_decoder = {
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
353 "motionpixels",
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
354 CODEC_TYPE_VIDEO,
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
355 CODEC_ID_MOTIONPIXELS,
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
356 sizeof(MotionPixelsContext),
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
357 mp_decode_init,
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
358 NULL,
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
359 mp_decode_end,
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
360 mp_decode_frame,
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
361 CODEC_CAP_DR1,
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
362 .long_name = NULL_IF_CONFIG_SMALL("Motion Pixels Video"),
21f5d934ccbd Motion Pixels Video Decoder.
ramiro
parents:
diff changeset
363 };