1 |
|
|
/* |
2 |
|
|
* LOCO codec |
3 |
|
|
* Copyright (c) 2005 Konstantin Shishkov |
4 |
|
|
* |
5 |
|
|
* This file is part of FFmpeg. |
6 |
|
|
* |
7 |
|
|
* FFmpeg is free software; you can redistribute it and/or |
8 |
|
|
* modify it under the terms of the GNU Lesser General Public |
9 |
|
|
* License as published by the Free Software Foundation; either |
10 |
|
|
* version 2.1 of the License, or (at your option) any later version. |
11 |
|
|
* |
12 |
|
|
* FFmpeg is distributed in the hope that it will be useful, |
13 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 |
|
|
* Lesser General Public License for more details. |
16 |
|
|
* |
17 |
|
|
* You should have received a copy of the GNU Lesser General Public |
18 |
|
|
* License along with FFmpeg; if not, write to the Free Software |
19 |
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 |
|
|
*/ |
21 |
|
|
|
22 |
|
|
/** |
23 |
|
|
* @file |
24 |
|
|
* LOCO codec. |
25 |
|
|
*/ |
26 |
|
|
|
27 |
|
|
#include "avcodec.h" |
28 |
|
|
#include "get_bits.h" |
29 |
|
|
#include "golomb.h" |
30 |
|
|
#include "internal.h" |
31 |
|
|
#include "mathops.h" |
32 |
|
|
|
33 |
|
|
enum LOCO_MODE { |
34 |
|
|
LOCO_UNKN = 0, |
35 |
|
|
LOCO_CYUY2 = -1, |
36 |
|
|
LOCO_CRGB = -2, |
37 |
|
|
LOCO_CRGBA = -3, |
38 |
|
|
LOCO_CYV12 = -4, |
39 |
|
|
LOCO_YUY2 = 1, |
40 |
|
|
LOCO_UYVY = 2, |
41 |
|
|
LOCO_RGB = 3, |
42 |
|
|
LOCO_RGBA = 4, |
43 |
|
|
LOCO_YV12 = 5, |
44 |
|
|
}; |
45 |
|
|
|
46 |
|
|
typedef struct LOCOContext { |
47 |
|
|
AVCodecContext *avctx; |
48 |
|
|
int lossy; |
49 |
|
|
enum LOCO_MODE mode; |
50 |
|
|
} LOCOContext; |
51 |
|
|
|
52 |
|
|
typedef struct RICEContext { |
53 |
|
|
GetBitContext gb; |
54 |
|
|
int save, run, run2; /* internal rice decoder state */ |
55 |
|
|
int sum, count; /* sum and count for getting rice parameter */ |
56 |
|
|
int lossy; |
57 |
|
|
} RICEContext; |
58 |
|
|
|
59 |
|
500785 |
static int loco_get_rice_param(RICEContext *r) |
60 |
|
|
{ |
61 |
|
500785 |
int cnt = 0; |
62 |
|
500785 |
int val = r->count; |
63 |
|
|
|
64 |
✓✓✓✗
|
2389200 |
while (r->sum > val && cnt < 9) { |
65 |
|
1888415 |
val <<= 1; |
66 |
|
1888415 |
cnt++; |
67 |
|
|
} |
68 |
|
|
|
69 |
|
500785 |
return cnt; |
70 |
|
|
} |
71 |
|
|
|
72 |
|
505344 |
static inline void loco_update_rice_param(RICEContext *r, int val) |
73 |
|
|
{ |
74 |
|
505344 |
r->sum += val; |
75 |
|
505344 |
r->count++; |
76 |
|
|
|
77 |
✓✓ |
505344 |
if (r->count == 16) { |
78 |
|
63144 |
r->sum >>= 1; |
79 |
|
63144 |
r->count >>= 1; |
80 |
|
|
} |
81 |
|
505344 |
} |
82 |
|
|
|
83 |
|
505344 |
static inline int loco_get_rice(RICEContext *r) |
84 |
|
|
{ |
85 |
|
|
unsigned v; |
86 |
✓✓ |
505344 |
if (r->run > 0) { /* we have zero run */ |
87 |
|
4559 |
r->run--; |
88 |
|
4559 |
loco_update_rice_param(r, 0); |
89 |
|
4559 |
return 0; |
90 |
|
|
} |
91 |
✗✓ |
500785 |
if (get_bits_left(&r->gb) < 1) |
92 |
|
|
return INT_MIN; |
93 |
|
500785 |
v = get_ur_golomb_jpegls(&r->gb, loco_get_rice_param(r), INT_MAX, 0); |
94 |
|
500785 |
loco_update_rice_param(r, (v + 1) >> 1); |
95 |
✓✓ |
500785 |
if (!v) { |
96 |
✓✓ |
49474 |
if (r->save >= 0) { |
97 |
|
2574 |
r->run = get_ur_golomb_jpegls(&r->gb, 2, INT_MAX, 0); |
98 |
✓✓ |
2574 |
if (r->run > 1) |
99 |
|
901 |
r->save += r->run + 1; |
100 |
|
|
else |
101 |
|
1673 |
r->save -= 3; |
102 |
|
|
} else |
103 |
|
46900 |
r->run2++; |
104 |
|
|
} else { |
105 |
|
451311 |
v = ((v >> 1) + r->lossy) ^ -(v & 1); |
106 |
✓✓ |
451311 |
if (r->run2 > 0) { |
107 |
✓✓ |
27417 |
if (r->run2 > 2) |
108 |
|
3721 |
r->save += r->run2; |
109 |
|
|
else |
110 |
|
23696 |
r->save -= 3; |
111 |
|
27417 |
r->run2 = 0; |
112 |
|
|
} |
113 |
|
|
} |
114 |
|
|
|
115 |
|
500785 |
return v; |
116 |
|
|
} |
117 |
|
|
|
118 |
|
|
/* LOCO main predictor - LOCO-I/JPEG-LS predictor */ |
119 |
|
498348 |
static inline int loco_predict(uint8_t* data, int stride) |
120 |
|
|
{ |
121 |
|
|
int a, b, c; |
122 |
|
|
|
123 |
|
498348 |
a = data[-stride]; |
124 |
|
498348 |
b = data[-1]; |
125 |
|
498348 |
c = data[-stride - 1]; |
126 |
|
|
|
127 |
|
498348 |
return mid_pred(a, a + b - c, b); |
128 |
|
|
} |
129 |
|
|
|
130 |
|
24 |
static int loco_decode_plane(LOCOContext *l, uint8_t *data, int width, int height, |
131 |
|
|
int stride, const uint8_t *buf, int buf_size) |
132 |
|
|
{ |
133 |
|
|
RICEContext rc; |
134 |
|
|
unsigned val; |
135 |
|
|
int ret; |
136 |
|
|
int i, j; |
137 |
|
|
|
138 |
✗✓ |
24 |
if(buf_size<=0) |
139 |
|
|
return -1; |
140 |
|
|
|
141 |
✗✓ |
24 |
if ((ret = init_get_bits8(&rc.gb, buf, buf_size)) < 0) |
142 |
|
|
return ret; |
143 |
|
|
|
144 |
|
24 |
rc.save = 0; |
145 |
|
24 |
rc.run = 0; |
146 |
|
24 |
rc.run2 = 0; |
147 |
|
24 |
rc.lossy = l->lossy; |
148 |
|
|
|
149 |
|
24 |
rc.sum = 8; |
150 |
|
24 |
rc.count = 1; |
151 |
|
|
|
152 |
|
|
/* restore top left pixel */ |
153 |
|
24 |
val = loco_get_rice(&rc); |
154 |
|
24 |
data[0] = 128 + val; |
155 |
|
|
/* restore top line */ |
156 |
✓✓ |
3948 |
for (i = 1; i < width; i++) { |
157 |
|
3924 |
val = loco_get_rice(&rc); |
158 |
✗✓ |
3924 |
if (val == INT_MIN) |
159 |
|
|
return AVERROR_INVALIDDATA; |
160 |
|
3924 |
data[i] = data[i - 1] + val; |
161 |
|
|
} |
162 |
|
24 |
data += stride; |
163 |
✓✓ |
3072 |
for (j = 1; j < height; j++) { |
164 |
|
|
/* restore left column */ |
165 |
|
3048 |
val = loco_get_rice(&rc); |
166 |
✗✓ |
3048 |
if (val == INT_MIN) |
167 |
|
|
return AVERROR_INVALIDDATA; |
168 |
|
3048 |
data[0] = data[-stride] + val; |
169 |
|
|
/* restore all other pixels */ |
170 |
✓✓ |
501396 |
for (i = 1; i < width; i++) { |
171 |
|
498348 |
val = loco_get_rice(&rc); |
172 |
✗✓ |
498348 |
if (val == INT_MIN) |
173 |
|
|
return -1; |
174 |
|
498348 |
data[i] = loco_predict(&data[i], stride) + val; |
175 |
|
|
} |
176 |
|
3048 |
data += stride; |
177 |
|
|
} |
178 |
|
|
|
179 |
|
24 |
return (get_bits_count(&rc.gb) + 7) >> 3; |
180 |
|
|
} |
181 |
|
|
|
182 |
|
|
static void rotate_faulty_loco(uint8_t *data, int width, int height, int stride) |
183 |
|
|
{ |
184 |
|
|
int y; |
185 |
|
|
|
186 |
|
|
for (y=1; y<height; y++) { |
187 |
|
|
if (width>=y) { |
188 |
|
|
memmove(data + y*stride, |
189 |
|
|
data + y*(stride + 1), |
190 |
|
|
(width-y)); |
191 |
|
|
if (y+1 < height) |
192 |
|
|
memmove(data + y*stride + (width-y), |
193 |
|
|
data + (y+1)*stride, y); |
194 |
|
|
} |
195 |
|
|
} |
196 |
|
|
} |
197 |
|
|
|
198 |
|
8 |
static int decode_frame(AVCodecContext *avctx, |
199 |
|
|
void *data, int *got_frame, |
200 |
|
|
AVPacket *avpkt) |
201 |
|
|
{ |
202 |
|
8 |
LOCOContext * const l = avctx->priv_data; |
203 |
|
8 |
const uint8_t *buf = avpkt->data; |
204 |
|
8 |
int buf_size = avpkt->size; |
205 |
|
8 |
AVFrame * const p = data; |
206 |
|
|
int decoded, ret; |
207 |
|
|
|
208 |
✗✓ |
8 |
if ((ret = ff_get_buffer(avctx, p, 0)) < 0) |
209 |
|
|
return ret; |
210 |
|
8 |
p->key_frame = 1; |
211 |
|
|
|
212 |
|
|
#define ADVANCE_BY_DECODED do { \ |
213 |
|
|
if (decoded < 0 || decoded >= buf_size) goto buf_too_small; \ |
214 |
|
|
buf += decoded; buf_size -= decoded; \ |
215 |
|
|
} while(0) |
216 |
✓✗✓✗ ✗ |
8 |
switch(l->mode) { |
217 |
|
3 |
case LOCO_CYUY2: case LOCO_YUY2: case LOCO_UYVY: |
218 |
|
3 |
decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height, |
219 |
|
|
p->linesize[0], buf, buf_size); |
220 |
✓✗✗✓
|
3 |
ADVANCE_BY_DECODED; |
221 |
|
3 |
decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height, |
222 |
|
|
p->linesize[1], buf, buf_size); |
223 |
✓✗✗✓
|
3 |
ADVANCE_BY_DECODED; |
224 |
|
3 |
decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height, |
225 |
|
|
p->linesize[2], buf, buf_size); |
226 |
|
3 |
break; |
227 |
|
|
case LOCO_CYV12: case LOCO_YV12: |
228 |
|
|
decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height, |
229 |
|
|
p->linesize[0], buf, buf_size); |
230 |
|
|
ADVANCE_BY_DECODED; |
231 |
|
|
decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height / 2, |
232 |
|
|
p->linesize[2], buf, buf_size); |
233 |
|
|
ADVANCE_BY_DECODED; |
234 |
|
|
decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height / 2, |
235 |
|
|
p->linesize[1], buf, buf_size); |
236 |
|
|
break; |
237 |
|
5 |
case LOCO_CRGB: case LOCO_RGB: |
238 |
|
5 |
decoded = loco_decode_plane(l, p->data[1] + p->linesize[1]*(avctx->height-1), avctx->width, avctx->height, |
239 |
|
5 |
-p->linesize[1], buf, buf_size); |
240 |
✓✗✗✓
|
5 |
ADVANCE_BY_DECODED; |
241 |
|
5 |
decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height, |
242 |
|
5 |
-p->linesize[0], buf, buf_size); |
243 |
✓✗✗✓
|
5 |
ADVANCE_BY_DECODED; |
244 |
|
5 |
decoded = loco_decode_plane(l, p->data[2] + p->linesize[2]*(avctx->height-1), avctx->width, avctx->height, |
245 |
|
5 |
-p->linesize[2], buf, buf_size); |
246 |
✗✓ |
5 |
if (avctx->width & 1) { |
247 |
|
|
rotate_faulty_loco(p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height, -p->linesize[0]); |
248 |
|
|
rotate_faulty_loco(p->data[1] + p->linesize[1]*(avctx->height-1), avctx->width, avctx->height, -p->linesize[1]); |
249 |
|
|
rotate_faulty_loco(p->data[2] + p->linesize[2]*(avctx->height-1), avctx->width, avctx->height, -p->linesize[2]); |
250 |
|
|
} |
251 |
|
5 |
break; |
252 |
|
|
case LOCO_CRGBA: |
253 |
|
|
case LOCO_RGBA: |
254 |
|
|
decoded = loco_decode_plane(l, p->data[1] + p->linesize[1]*(avctx->height-1), avctx->width, avctx->height, |
255 |
|
|
-p->linesize[1], buf, buf_size); |
256 |
|
|
ADVANCE_BY_DECODED; |
257 |
|
|
decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height, |
258 |
|
|
-p->linesize[0], buf, buf_size); |
259 |
|
|
ADVANCE_BY_DECODED; |
260 |
|
|
decoded = loco_decode_plane(l, p->data[2] + p->linesize[2]*(avctx->height-1), avctx->width, avctx->height, |
261 |
|
|
-p->linesize[2], buf, buf_size); |
262 |
|
|
ADVANCE_BY_DECODED; |
263 |
|
|
decoded = loco_decode_plane(l, p->data[3] + p->linesize[3]*(avctx->height-1), avctx->width, avctx->height, |
264 |
|
|
-p->linesize[3], buf, buf_size); |
265 |
|
|
break; |
266 |
|
|
default: |
267 |
|
|
av_assert0(0); |
268 |
|
|
} |
269 |
|
|
|
270 |
✓✗✗✓
|
8 |
if (decoded < 0 || decoded > buf_size) |
271 |
|
|
goto buf_too_small; |
272 |
|
8 |
buf_size -= decoded; |
273 |
|
|
|
274 |
|
8 |
*got_frame = 1; |
275 |
|
|
|
276 |
|
8 |
return avpkt->size - buf_size; |
277 |
|
|
buf_too_small: |
278 |
|
|
av_log(avctx, AV_LOG_ERROR, "Input data too small.\n"); |
279 |
|
|
return AVERROR(EINVAL); |
280 |
|
|
} |
281 |
|
|
|
282 |
|
4 |
static av_cold int decode_init(AVCodecContext *avctx) |
283 |
|
|
{ |
284 |
|
4 |
LOCOContext * const l = avctx->priv_data; |
285 |
|
|
int version; |
286 |
|
|
|
287 |
|
4 |
l->avctx = avctx; |
288 |
✗✓ |
4 |
if (avctx->extradata_size < 12) { |
289 |
|
|
av_log(avctx, AV_LOG_ERROR, "Extradata size must be >= 12 instead of %i\n", |
290 |
|
|
avctx->extradata_size); |
291 |
|
|
return AVERROR_INVALIDDATA; |
292 |
|
|
} |
293 |
|
4 |
version = AV_RL32(avctx->extradata); |
294 |
✗✓✗ |
4 |
switch (version) { |
295 |
|
|
case 1: |
296 |
|
|
l->lossy = 0; |
297 |
|
|
break; |
298 |
|
4 |
case 2: |
299 |
|
4 |
l->lossy = AV_RL32(avctx->extradata + 8); |
300 |
|
4 |
break; |
301 |
|
|
default: |
302 |
|
|
l->lossy = AV_RL32(avctx->extradata + 8); |
303 |
|
|
avpriv_request_sample(avctx, "LOCO codec version %i", version); |
304 |
|
|
} |
305 |
|
|
|
306 |
✗✓ |
4 |
if (l->lossy > 65536U) { |
307 |
|
|
av_log(avctx, AV_LOG_ERROR, "lossy %i is too large\n", l->lossy); |
308 |
|
|
return AVERROR_INVALIDDATA; |
309 |
|
|
} |
310 |
|
|
|
311 |
|
4 |
l->mode = AV_RL32(avctx->extradata + 4); |
312 |
✓✓✗✗ ✗ |
4 |
switch (l->mode) { |
313 |
|
2 |
case LOCO_CYUY2: |
314 |
|
|
case LOCO_YUY2: |
315 |
|
|
case LOCO_UYVY: |
316 |
|
2 |
avctx->pix_fmt = AV_PIX_FMT_YUV422P; |
317 |
|
2 |
break; |
318 |
|
2 |
case LOCO_CRGB: |
319 |
|
|
case LOCO_RGB: |
320 |
|
2 |
avctx->pix_fmt = AV_PIX_FMT_GBRP; |
321 |
|
2 |
break; |
322 |
|
|
case LOCO_CYV12: |
323 |
|
|
case LOCO_YV12: |
324 |
|
|
avctx->pix_fmt = AV_PIX_FMT_YUV420P; |
325 |
|
|
break; |
326 |
|
|
case LOCO_CRGBA: |
327 |
|
|
case LOCO_RGBA: |
328 |
|
|
avctx->pix_fmt = AV_PIX_FMT_GBRAP; |
329 |
|
|
break; |
330 |
|
|
default: |
331 |
|
|
av_log(avctx, AV_LOG_INFO, "Unknown colorspace, index = %i\n", l->mode); |
332 |
|
|
return AVERROR_INVALIDDATA; |
333 |
|
|
} |
334 |
✗✓ |
4 |
if (avctx->debug & FF_DEBUG_PICT_INFO) |
335 |
|
|
av_log(avctx, AV_LOG_INFO, "lossy:%i, version:%i, mode: %i\n", l->lossy, version, l->mode); |
336 |
|
|
|
337 |
|
4 |
return 0; |
338 |
|
|
} |
339 |
|
|
|
340 |
|
|
AVCodec ff_loco_decoder = { |
341 |
|
|
.name = "loco", |
342 |
|
|
.long_name = NULL_IF_CONFIG_SMALL("LOCO"), |
343 |
|
|
.type = AVMEDIA_TYPE_VIDEO, |
344 |
|
|
.id = AV_CODEC_ID_LOCO, |
345 |
|
|
.priv_data_size = sizeof(LOCOContext), |
346 |
|
|
.init = decode_init, |
347 |
|
|
.decode = decode_frame, |
348 |
|
|
.capabilities = AV_CODEC_CAP_DR1, |
349 |
|
|
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, |
350 |
|
|
}; |