Commit | Line | Data |
---|---|---|
2ba45a60 DM |
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 | int 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 | static int loco_get_rice_param(RICEContext *r) | |
60 | { | |
61 | int cnt = 0; | |
62 | int val = r->count; | |
63 | ||
64 | while (r->sum > val && cnt < 9) { | |
65 | val <<= 1; | |
66 | cnt++; | |
67 | } | |
68 | ||
69 | return cnt; | |
70 | } | |
71 | ||
72 | static inline void loco_update_rice_param(RICEContext *r, int val) | |
73 | { | |
74 | r->sum += val; | |
75 | r->count++; | |
76 | ||
77 | if (r->count == 16) { | |
78 | r->sum >>= 1; | |
79 | r->count >>= 1; | |
80 | } | |
81 | } | |
82 | ||
83 | static inline int loco_get_rice(RICEContext *r) | |
84 | { | |
85 | int v; | |
86 | if (r->run > 0) { /* we have zero run */ | |
87 | r->run--; | |
88 | loco_update_rice_param(r, 0); | |
89 | return 0; | |
90 | } | |
91 | v = get_ur_golomb_jpegls(&r->gb, loco_get_rice_param(r), INT_MAX, 0); | |
92 | loco_update_rice_param(r, (v + 1) >> 1); | |
93 | if (!v) { | |
94 | if (r->save >= 0) { | |
95 | r->run = get_ur_golomb_jpegls(&r->gb, 2, INT_MAX, 0); | |
96 | if (r->run > 1) | |
97 | r->save += r->run + 1; | |
98 | else | |
99 | r->save -= 3; | |
100 | } else | |
101 | r->run2++; | |
102 | } else { | |
103 | v = ((v >> 1) + r->lossy) ^ -(v & 1); | |
104 | if (r->run2 > 0) { | |
105 | if (r->run2 > 2) | |
106 | r->save += r->run2; | |
107 | else | |
108 | r->save -= 3; | |
109 | r->run2 = 0; | |
110 | } | |
111 | } | |
112 | ||
113 | return v; | |
114 | } | |
115 | ||
116 | /* LOCO main predictor - LOCO-I/JPEG-LS predictor */ | |
117 | static inline int loco_predict(uint8_t* data, int stride, int step) | |
118 | { | |
119 | int a, b, c; | |
120 | ||
121 | a = data[-stride]; | |
122 | b = data[-step]; | |
123 | c = data[-stride - step]; | |
124 | ||
125 | return mid_pred(a, a + b - c, b); | |
126 | } | |
127 | ||
128 | static int loco_decode_plane(LOCOContext *l, uint8_t *data, int width, int height, | |
129 | int stride, const uint8_t *buf, int buf_size, int step) | |
130 | { | |
131 | RICEContext rc; | |
132 | int val; | |
133 | int i, j; | |
134 | ||
135 | if(buf_size<=0) | |
136 | return -1; | |
137 | ||
138 | init_get_bits8(&rc.gb, buf, buf_size); | |
139 | rc.save = 0; | |
140 | rc.run = 0; | |
141 | rc.run2 = 0; | |
142 | rc.lossy = l->lossy; | |
143 | ||
144 | rc.sum = 8; | |
145 | rc.count = 1; | |
146 | ||
147 | /* restore top left pixel */ | |
148 | val = loco_get_rice(&rc); | |
149 | data[0] = 128 + val; | |
150 | /* restore top line */ | |
151 | for (i = 1; i < width; i++) { | |
152 | val = loco_get_rice(&rc); | |
153 | data[i * step] = data[i * step - step] + val; | |
154 | } | |
155 | data += stride; | |
156 | for (j = 1; j < height; j++) { | |
157 | /* restore left column */ | |
158 | val = loco_get_rice(&rc); | |
159 | data[0] = data[-stride] + val; | |
160 | /* restore all other pixels */ | |
161 | for (i = 1; i < width; i++) { | |
162 | val = loco_get_rice(&rc); | |
163 | data[i * step] = loco_predict(&data[i * step], stride, step) + val; | |
164 | } | |
165 | data += stride; | |
166 | } | |
167 | ||
168 | return (get_bits_count(&rc.gb) + 7) >> 3; | |
169 | } | |
170 | ||
171 | static int decode_frame(AVCodecContext *avctx, | |
172 | void *data, int *got_frame, | |
173 | AVPacket *avpkt) | |
174 | { | |
175 | LOCOContext * const l = avctx->priv_data; | |
176 | const uint8_t *buf = avpkt->data; | |
177 | int buf_size = avpkt->size; | |
178 | AVFrame * const p = data; | |
179 | int decoded, ret; | |
180 | ||
181 | if ((ret = ff_get_buffer(avctx, p, 0)) < 0) | |
182 | return ret; | |
183 | p->key_frame = 1; | |
184 | ||
185 | #define ADVANCE_BY_DECODED do { \ | |
186 | if (decoded < 0 || decoded >= buf_size) goto buf_too_small; \ | |
187 | buf += decoded; buf_size -= decoded; \ | |
188 | } while(0) | |
189 | switch(l->mode) { | |
190 | case LOCO_CYUY2: case LOCO_YUY2: case LOCO_UYVY: | |
191 | decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height, | |
192 | p->linesize[0], buf, buf_size, 1); | |
193 | ADVANCE_BY_DECODED; | |
194 | decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height, | |
195 | p->linesize[1], buf, buf_size, 1); | |
196 | ADVANCE_BY_DECODED; | |
197 | decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height, | |
198 | p->linesize[2], buf, buf_size, 1); | |
199 | break; | |
200 | case LOCO_CYV12: case LOCO_YV12: | |
201 | decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height, | |
202 | p->linesize[0], buf, buf_size, 1); | |
203 | ADVANCE_BY_DECODED; | |
204 | decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height / 2, | |
205 | p->linesize[2], buf, buf_size, 1); | |
206 | ADVANCE_BY_DECODED; | |
207 | decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height / 2, | |
208 | p->linesize[1], buf, buf_size, 1); | |
209 | break; | |
210 | case LOCO_CRGB: case LOCO_RGB: | |
211 | decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height, | |
212 | -p->linesize[0], buf, buf_size, 3); | |
213 | ADVANCE_BY_DECODED; | |
214 | decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 1, avctx->width, avctx->height, | |
215 | -p->linesize[0], buf, buf_size, 3); | |
216 | ADVANCE_BY_DECODED; | |
217 | decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 2, avctx->width, avctx->height, | |
218 | -p->linesize[0], buf, buf_size, 3); | |
219 | break; | |
220 | case LOCO_CRGBA: | |
221 | case LOCO_RGBA: | |
222 | decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height, | |
223 | -p->linesize[0], buf, buf_size, 4); | |
224 | ADVANCE_BY_DECODED; | |
225 | decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 1, avctx->width, avctx->height, | |
226 | -p->linesize[0], buf, buf_size, 4); | |
227 | ADVANCE_BY_DECODED; | |
228 | decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 2, avctx->width, avctx->height, | |
229 | -p->linesize[0], buf, buf_size, 4); | |
230 | ADVANCE_BY_DECODED; | |
231 | decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 3, avctx->width, avctx->height, | |
232 | -p->linesize[0], buf, buf_size, 4); | |
233 | break; | |
234 | default: | |
235 | av_assert0(0); | |
236 | } | |
237 | ||
238 | if (decoded < 0 || decoded > buf_size) | |
239 | goto buf_too_small; | |
240 | buf_size -= decoded; | |
241 | ||
242 | *got_frame = 1; | |
243 | ||
244 | return avpkt->size - buf_size; | |
245 | buf_too_small: | |
246 | av_log(avctx, AV_LOG_ERROR, "Input data too small.\n"); | |
247 | return AVERROR(EINVAL); | |
248 | } | |
249 | ||
250 | static av_cold int decode_init(AVCodecContext *avctx) | |
251 | { | |
252 | LOCOContext * const l = avctx->priv_data; | |
253 | int version; | |
254 | ||
255 | l->avctx = avctx; | |
256 | if (avctx->extradata_size < 12) { | |
257 | av_log(avctx, AV_LOG_ERROR, "Extradata size must be >= 12 instead of %i\n", | |
258 | avctx->extradata_size); | |
259 | return AVERROR_INVALIDDATA; | |
260 | } | |
261 | version = AV_RL32(avctx->extradata); | |
262 | switch (version) { | |
263 | case 1: | |
264 | l->lossy = 0; | |
265 | break; | |
266 | case 2: | |
267 | l->lossy = AV_RL32(avctx->extradata + 8); | |
268 | break; | |
269 | default: | |
270 | l->lossy = AV_RL32(avctx->extradata + 8); | |
271 | avpriv_request_sample(avctx, "LOCO codec version %i", version); | |
272 | } | |
273 | ||
274 | l->mode = AV_RL32(avctx->extradata + 4); | |
275 | switch (l->mode) { | |
276 | case LOCO_CYUY2: | |
277 | case LOCO_YUY2: | |
278 | case LOCO_UYVY: | |
279 | avctx->pix_fmt = AV_PIX_FMT_YUV422P; | |
280 | break; | |
281 | case LOCO_CRGB: | |
282 | case LOCO_RGB: | |
283 | avctx->pix_fmt = AV_PIX_FMT_BGR24; | |
284 | break; | |
285 | case LOCO_CYV12: | |
286 | case LOCO_YV12: | |
287 | avctx->pix_fmt = AV_PIX_FMT_YUV420P; | |
288 | break; | |
289 | case LOCO_CRGBA: | |
290 | case LOCO_RGBA: | |
291 | avctx->pix_fmt = AV_PIX_FMT_BGRA; | |
292 | break; | |
293 | default: | |
294 | av_log(avctx, AV_LOG_INFO, "Unknown colorspace, index = %i\n", l->mode); | |
295 | return AVERROR_INVALIDDATA; | |
296 | } | |
297 | if (avctx->debug & FF_DEBUG_PICT_INFO) | |
298 | av_log(avctx, AV_LOG_INFO, "lossy:%i, version:%i, mode: %i\n", l->lossy, version, l->mode); | |
299 | ||
300 | return 0; | |
301 | } | |
302 | ||
303 | AVCodec ff_loco_decoder = { | |
304 | .name = "loco", | |
305 | .long_name = NULL_IF_CONFIG_SMALL("LOCO"), | |
306 | .type = AVMEDIA_TYPE_VIDEO, | |
307 | .id = AV_CODEC_ID_LOCO, | |
308 | .priv_data_size = sizeof(LOCOContext), | |
309 | .init = decode_init, | |
310 | .decode = decode_frame, | |
311 | .capabilities = CODEC_CAP_DR1, | |
312 | }; |