/src/ffmpeg/libavcodec/cri.c
Line | Count | Source |
1 | | /* |
2 | | * CRI image decoder |
3 | | * |
4 | | * Copyright (c) 2020 Paul B Mahol |
5 | | * |
6 | | * This file is part of FFmpeg. |
7 | | * |
8 | | * FFmpeg is free software; you can redistribute it and/or |
9 | | * modify it under the terms of the GNU Lesser General Public |
10 | | * License as published by the Free Software Foundation; either |
11 | | * version 2.1 of the License, or (at your option) any later version. |
12 | | * |
13 | | * FFmpeg is distributed in the hope that it will be useful, |
14 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | | * Lesser General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU Lesser General Public |
19 | | * License along with FFmpeg; if not, write to the Free Software |
20 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
21 | | */ |
22 | | |
23 | | /** |
24 | | * @file |
25 | | * Cintel RAW image decoder |
26 | | */ |
27 | | |
28 | | #define BITSTREAM_READER_LE |
29 | | |
30 | | #include "libavutil/attributes_internal.h" |
31 | | #include "libavutil/intfloat.h" |
32 | | #include "libavutil/display.h" |
33 | | #include "avcodec.h" |
34 | | #include "bytestream.h" |
35 | | #include "codec_internal.h" |
36 | | #include "decode.h" |
37 | | #include "get_bits.h" |
38 | | #include "thread.h" |
39 | | |
40 | | typedef struct CRIContext { |
41 | | AVCodecContext *jpeg_avctx; // wrapper context for MJPEG |
42 | | AVPacket *jpkt; // encoded JPEG tile |
43 | | AVFrame *jpgframe; // decoded JPEG tile |
44 | | |
45 | | GetByteContext gb; |
46 | | int color_model; |
47 | | const uint8_t *data; |
48 | | unsigned data_size; |
49 | | uint64_t tile_size[4]; |
50 | | } CRIContext; |
51 | | |
52 | | static av_cold int cri_decode_init(AVCodecContext *avctx) |
53 | 9.24k | { |
54 | 9.24k | CRIContext *s = avctx->priv_data; |
55 | 9.24k | int ret; |
56 | | |
57 | 9.24k | s->jpgframe = av_frame_alloc(); |
58 | 9.24k | if (!s->jpgframe) |
59 | 0 | return AVERROR(ENOMEM); |
60 | | |
61 | 9.24k | s->jpkt = av_packet_alloc(); |
62 | 9.24k | if (!s->jpkt) |
63 | 0 | return AVERROR(ENOMEM); |
64 | | |
65 | 9.24k | EXTERN const FFCodec ff_mjpeg_decoder; |
66 | 9.24k | s->jpeg_avctx = avcodec_alloc_context3(&ff_mjpeg_decoder.p); |
67 | 9.24k | if (!s->jpeg_avctx) |
68 | 0 | return AVERROR(ENOMEM); |
69 | 9.24k | s->jpeg_avctx->flags = avctx->flags; |
70 | 9.24k | s->jpeg_avctx->flags2 = avctx->flags2; |
71 | 9.24k | s->jpeg_avctx->idct_algo = avctx->idct_algo; |
72 | 9.24k | s->jpeg_avctx->max_pixels = avctx->max_pixels; |
73 | 9.24k | ret = avcodec_open2(s->jpeg_avctx, NULL, NULL); |
74 | 9.24k | if (ret < 0) |
75 | 0 | return ret; |
76 | | |
77 | 9.24k | return 0; |
78 | 9.24k | } |
79 | | |
80 | | static void unpack_10bit(GetByteContext *gb, uint16_t *dst, int shift, |
81 | | int w, int h, ptrdiff_t stride) |
82 | 60.1k | { |
83 | 60.1k | int count = w * h; |
84 | 60.1k | int pos = 0; |
85 | | |
86 | 220k | while (count > 0) { |
87 | 220k | uint32_t a0, a1, a2, a3; |
88 | 220k | if (bytestream2_get_bytes_left(gb) < 4) |
89 | 45.2k | break; |
90 | 175k | a0 = bytestream2_get_le32(gb); |
91 | 175k | a1 = bytestream2_get_le32(gb); |
92 | 175k | a2 = bytestream2_get_le32(gb); |
93 | 175k | a3 = bytestream2_get_le32(gb); |
94 | 175k | dst[pos] = (((a0 >> 1) & 0xE00) | (a0 & 0x1FF)) << shift; |
95 | 175k | pos++; |
96 | 175k | if (pos >= w) { |
97 | 4.48k | if (count == 1) |
98 | 269 | break; |
99 | 4.21k | dst += stride; |
100 | 4.21k | pos = 0; |
101 | 4.21k | } |
102 | 174k | dst[pos] = (((a0 >> 13) & 0x3F) | ((a0 >> 14) & 0xFC0)) << shift; |
103 | 174k | pos++; |
104 | 174k | if (pos >= w) { |
105 | 4.80k | if (count == 2) |
106 | 214 | break; |
107 | 4.58k | dst += stride; |
108 | 4.58k | pos = 0; |
109 | 4.58k | } |
110 | 174k | dst[pos] = (((a0 >> 26) & 7) | ((a1 & 0x1FF) << 3)) << shift; |
111 | 174k | pos++; |
112 | 174k | if (pos >= w) { |
113 | 15.4k | if (count == 3) |
114 | 11.1k | break; |
115 | 4.30k | dst += stride; |
116 | 4.30k | pos = 0; |
117 | 4.30k | } |
118 | 163k | dst[pos] = (((a1 >> 10) & 0x1FF) | ((a1 >> 11) & 0xE00)) << shift; |
119 | 163k | pos++; |
120 | 163k | if (pos >= w) { |
121 | 5.24k | if (count == 4) |
122 | 419 | break; |
123 | 4.82k | dst += stride; |
124 | 4.82k | pos = 0; |
125 | 4.82k | } |
126 | 163k | dst[pos] = (((a1 >> 23) & 0x3F) | ((a2 & 0x3F) << 6)) << shift; |
127 | 163k | pos++; |
128 | 163k | if (pos >= w) { |
129 | 4.42k | if (count == 5) |
130 | 211 | break; |
131 | 4.21k | dst += stride; |
132 | 4.21k | pos = 0; |
133 | 4.21k | } |
134 | 162k | dst[pos] = (((a2 >> 7) & 0xFF8) | ((a2 >> 6) & 7)) << shift; |
135 | 162k | pos++; |
136 | 162k | if (pos >= w) { |
137 | 5.36k | if (count == 6) |
138 | 286 | break; |
139 | 5.07k | dst += stride; |
140 | 5.07k | pos = 0; |
141 | 5.07k | } |
142 | 162k | dst[pos] = (((a3 & 7) << 9) | ((a2 >> 20) & 0x1FF)) << shift; |
143 | 162k | pos++; |
144 | 162k | if (pos >= w) { |
145 | 39.3k | if (count == 7) |
146 | 374 | break; |
147 | 38.9k | dst += stride; |
148 | 38.9k | pos = 0; |
149 | 38.9k | } |
150 | 162k | dst[pos] = (((a3 >> 4) & 0xFC0) | ((a3 >> 3) & 0x3F)) << shift; |
151 | 162k | pos++; |
152 | 162k | if (pos >= w) { |
153 | 6.56k | if (count == 8) |
154 | 1.65k | break; |
155 | 4.90k | dst += stride; |
156 | 4.90k | pos = 0; |
157 | 4.90k | } |
158 | 160k | dst[pos] = (((a3 >> 16) & 7) | ((a3 >> 17) & 0xFF8)) << shift; |
159 | 160k | pos++; |
160 | 160k | if (pos >= w) { |
161 | 6.72k | if (count == 9) |
162 | 324 | break; |
163 | 6.40k | dst += stride; |
164 | 6.40k | pos = 0; |
165 | 6.40k | } |
166 | | |
167 | 160k | count -= 9; |
168 | 160k | } |
169 | 60.1k | } |
170 | | |
171 | | static int cri_decode_frame(AVCodecContext *avctx, AVFrame *p, |
172 | | int *got_frame, AVPacket *avpkt) |
173 | 552k | { |
174 | 552k | CRIContext *s = avctx->priv_data; |
175 | 552k | GetByteContext *gb = &s->gb; |
176 | 552k | int ret, bps, hflip = 0, vflip = 0; |
177 | 552k | AVFrameSideData *rotation; |
178 | 552k | int compressed = 0; |
179 | | |
180 | 552k | s->data = NULL; |
181 | 552k | s->data_size = 0; |
182 | | |
183 | 552k | bytestream2_init(gb, avpkt->data, avpkt->size); |
184 | | |
185 | 1.50M | while (bytestream2_get_bytes_left(gb) > 8) { |
186 | 1.04M | char codec_name[1024]; |
187 | 1.04M | uint32_t key, length; |
188 | 1.04M | float framerate; |
189 | 1.04M | int width, height; |
190 | | |
191 | 1.04M | key = bytestream2_get_le32(gb); |
192 | 1.04M | length = bytestream2_get_le32(gb); |
193 | | |
194 | 1.04M | switch (key) { |
195 | 18.1k | case 1: |
196 | 18.1k | if (length != 4) |
197 | 1.48k | return AVERROR_INVALIDDATA; |
198 | | |
199 | 16.6k | if (bytestream2_get_le32(gb) != MKTAG('D', 'V', 'C', 'C')) |
200 | 2.87k | return AVERROR_INVALIDDATA; |
201 | 13.7k | break; |
202 | 26.9k | case 100: |
203 | 26.9k | if (length < 16) |
204 | 453 | return AVERROR_INVALIDDATA; |
205 | 26.4k | width = bytestream2_get_le32(gb); |
206 | 26.4k | height = bytestream2_get_le32(gb); |
207 | 26.4k | s->color_model = bytestream2_get_le32(gb); |
208 | 26.4k | if (bytestream2_get_le32(gb) != 1) |
209 | 4.01k | return AVERROR_INVALIDDATA; |
210 | 22.4k | ret = ff_set_dimensions(avctx, width, height); |
211 | 22.4k | if (ret < 0) |
212 | 2.60k | return ret; |
213 | 19.8k | length -= 16; |
214 | 19.8k | goto skip; |
215 | 3.03k | case 101: |
216 | 3.03k | if (length != 4) |
217 | 748 | return AVERROR_INVALIDDATA; |
218 | | |
219 | 2.28k | if (bytestream2_get_le32(gb) != 0) |
220 | 1.78k | return AVERROR_INVALIDDATA; |
221 | 505 | break; |
222 | 236k | case 102:; |
223 | 236k | int read_len = FFMIN(length, sizeof(codec_name) - 1); |
224 | 236k | if (read_len != bytestream2_get_buffer(gb, codec_name, read_len)) |
225 | 17.1k | return AVERROR_INVALIDDATA; |
226 | 219k | length -= read_len; |
227 | 219k | if (strncmp(codec_name, "cintel_craw", read_len)) |
228 | 4.93k | return AVERROR_INVALIDDATA; |
229 | 214k | compressed = 1; |
230 | 214k | goto skip; |
231 | 390k | case 103: |
232 | 390k | if (bytestream2_get_bytes_left(gb) < length) |
233 | 48.0k | return AVERROR_INVALIDDATA; |
234 | 342k | s->data = gb->buffer; |
235 | 342k | s->data_size = length; |
236 | 342k | goto skip; |
237 | 796 | case 105: |
238 | 796 | if (length <= 0) |
239 | 218 | return AVERROR_INVALIDDATA; |
240 | 578 | hflip = bytestream2_get_byte(gb) != 0; |
241 | 578 | length--; |
242 | 578 | goto skip; |
243 | 602 | case 106: |
244 | 602 | if (length <= 0) |
245 | 202 | return AVERROR_INVALIDDATA; |
246 | 400 | vflip = bytestream2_get_byte(gb) != 0; |
247 | 400 | length--; |
248 | 400 | goto skip; |
249 | 1.05k | case 107: |
250 | 1.05k | if (length != 4) |
251 | 279 | return AVERROR_INVALIDDATA; |
252 | 777 | framerate = av_int2float(bytestream2_get_le32(gb)); |
253 | 777 | avctx->framerate.num = framerate * 1000; |
254 | 777 | avctx->framerate.den = 1000; |
255 | 777 | break; |
256 | 50.0k | case 119: |
257 | 50.0k | if (length != 32) |
258 | 3.55k | return AVERROR_INVALIDDATA; |
259 | | |
260 | 232k | for (int i = 0; i < 4; i++) |
261 | 186k | s->tile_size[i] = bytestream2_get_le64(gb); |
262 | 46.5k | break; |
263 | 314k | default: |
264 | 314k | av_log(avctx, AV_LOG_DEBUG, "skipping unknown key %u of length %u\n", key, length); |
265 | 892k | skip: |
266 | 892k | bytestream2_skip(gb, length); |
267 | 1.04M | } |
268 | 1.04M | } |
269 | | |
270 | 464k | switch (s->color_model) { |
271 | 248 | case 76: |
272 | 4.12k | case 88: |
273 | 4.12k | avctx->pix_fmt = AV_PIX_FMT_BAYER_BGGR16; |
274 | 4.12k | break; |
275 | 96.5k | case 77: |
276 | 100k | case 89: |
277 | 100k | avctx->pix_fmt = AV_PIX_FMT_BAYER_GBRG16; |
278 | 100k | break; |
279 | 438 | case 78: |
280 | 765 | case 90: |
281 | 765 | avctx->pix_fmt = AV_PIX_FMT_BAYER_RGGB16; |
282 | 765 | break; |
283 | 288k | case 45: |
284 | 328k | case 79: |
285 | 329k | case 91: |
286 | 329k | avctx->pix_fmt = AV_PIX_FMT_BAYER_GRBG16; |
287 | 329k | break; |
288 | 464k | } |
289 | | |
290 | 464k | switch (s->color_model) { |
291 | 288k | case 45: |
292 | 288k | bps = 10; |
293 | 288k | break; |
294 | 248 | case 76: |
295 | 96.7k | case 77: |
296 | 97.1k | case 78: |
297 | 136k | case 79: |
298 | 136k | bps = 12; |
299 | 136k | break; |
300 | 3.87k | case 88: |
301 | 7.86k | case 89: |
302 | 8.18k | case 90: |
303 | 8.78k | case 91: |
304 | 8.78k | bps = 16; |
305 | 8.78k | break; |
306 | 29.8k | default: |
307 | 29.8k | return AVERROR_INVALIDDATA; |
308 | 464k | } |
309 | | |
310 | 434k | if (compressed) { |
311 | 968k | for (int i = 0; i < 4; i++) { |
312 | 779k | if (s->tile_size[i] >= s->data_size) |
313 | 18.1k | return AVERROR_INVALIDDATA; |
314 | 779k | } |
315 | | |
316 | 188k | if (s->tile_size[0] + s->tile_size[1] + s->tile_size[2] + s->tile_size[3] != |
317 | 188k | s->data_size) |
318 | 861 | return AVERROR_INVALIDDATA; |
319 | 188k | } |
320 | | |
321 | 415k | if (!s->data || !s->data_size) |
322 | 120k | return AVERROR_INVALIDDATA; |
323 | | |
324 | 295k | if (avctx->skip_frame >= AVDISCARD_ALL) |
325 | 14.7k | return avpkt->size; |
326 | | |
327 | 280k | if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0) |
328 | 4.24k | return ret; |
329 | | |
330 | 276k | avctx->bits_per_raw_sample = bps; |
331 | | |
332 | 276k | if (!compressed && s->color_model == 45) { |
333 | 60.1k | uint16_t *dst = (uint16_t *)p->data[0]; |
334 | 60.1k | GetByteContext gb; |
335 | | |
336 | 60.1k | bytestream2_init(&gb, s->data, s->data_size); |
337 | 60.1k | unpack_10bit(&gb, dst, 4, avctx->width, avctx->height, p->linesize[0] / 2); |
338 | 216k | } else if (!compressed) { |
339 | 29.4k | GetBitContext gbit; |
340 | 29.4k | const int shift = 16 - bps; |
341 | | |
342 | 29.4k | ret = init_get_bits8(&gbit, s->data, s->data_size); |
343 | 29.4k | if (ret < 0) |
344 | 0 | return ret; |
345 | | |
346 | 196k | for (int y = 0; y < avctx->height; y++) { |
347 | 194k | uint16_t *dst = (uint16_t *)(p->data[0] + y * p->linesize[0]); |
348 | | |
349 | 194k | if (get_bits_left(&gbit) < avctx->width * bps) |
350 | 26.8k | break; |
351 | | |
352 | 558k | for (int x = 0; x < avctx->width; x++) |
353 | 390k | dst[x] = get_bits(&gbit, bps) << shift; |
354 | 167k | } |
355 | 186k | } else { |
356 | 186k | unsigned offset = 0; |
357 | | |
358 | 187k | for (int tile = 0; tile < 4; tile++) { |
359 | 187k | av_packet_unref(s->jpkt); |
360 | 187k | s->jpkt->data = (uint8_t *)s->data + offset; |
361 | 187k | s->jpkt->size = s->tile_size[tile]; |
362 | | |
363 | 187k | ret = avcodec_send_packet(s->jpeg_avctx, s->jpkt); |
364 | 187k | if (ret < 0) { |
365 | 100k | av_log(avctx, AV_LOG_ERROR, "Error submitting a packet for decoding\n"); |
366 | 100k | return ret; |
367 | 100k | } |
368 | | |
369 | 86.6k | ret = avcodec_receive_frame(s->jpeg_avctx, s->jpgframe); |
370 | 86.6k | if (ret < 0 || s->jpgframe->format != AV_PIX_FMT_GRAY16 || |
371 | 32.7k | s->jpeg_avctx->width * 2 != avctx->width || |
372 | 86.0k | s->jpeg_avctx->height * 2 != avctx->height) { |
373 | 86.0k | if (ret < 0) { |
374 | 0 | av_log(avctx, AV_LOG_ERROR, |
375 | 0 | "JPEG decoding error (%d).\n", ret); |
376 | 86.0k | } else { |
377 | 86.0k | av_log(avctx, AV_LOG_ERROR, |
378 | 86.0k | "JPEG invalid format.\n"); |
379 | 86.0k | ret = AVERROR_INVALIDDATA; |
380 | 86.0k | } |
381 | | |
382 | | /* Normally skip, if error explode */ |
383 | 86.0k | if (avctx->err_recognition & AV_EF_EXPLODE) |
384 | 4.74k | return ret; |
385 | 81.2k | else |
386 | 81.2k | return 0; |
387 | 86.0k | } |
388 | | |
389 | 60.9k | for (int y = 0; y < s->jpeg_avctx->height; y++) { |
390 | 60.3k | const int hw = s->jpgframe->width / 2; |
391 | 60.3k | uint16_t *dst = (uint16_t *)(p->data[0] + (y * 2) * p->linesize[0] + tile * hw * 2); |
392 | 60.3k | const uint16_t *src = (const uint16_t *)(s->jpgframe->data[0] + y * s->jpgframe->linesize[0]); |
393 | | |
394 | 60.3k | memcpy(dst, src, hw * 2); |
395 | 60.3k | src += hw; |
396 | 60.3k | dst += p->linesize[0] / 2; |
397 | 60.3k | memcpy(dst, src, hw * 2); |
398 | 60.3k | } |
399 | | |
400 | 600 | av_frame_unref(s->jpgframe); |
401 | 600 | offset += s->tile_size[tile]; |
402 | 600 | } |
403 | 186k | } |
404 | | |
405 | 89.6k | if (hflip || vflip) { |
406 | 536 | ff_frame_new_side_data(avctx, p, AV_FRAME_DATA_DISPLAYMATRIX, |
407 | 536 | sizeof(int32_t) * 9, &rotation); |
408 | 536 | if (rotation) { |
409 | 536 | av_display_rotation_set((int32_t *)rotation->data, 0.f); |
410 | 536 | av_display_matrix_flip((int32_t *)rotation->data, hflip, vflip); |
411 | 536 | } |
412 | 536 | } |
413 | | |
414 | 89.6k | *got_frame = 1; |
415 | | |
416 | 89.6k | return 0; |
417 | 276k | } |
418 | | |
419 | | static av_cold int cri_decode_close(AVCodecContext *avctx) |
420 | 9.24k | { |
421 | 9.24k | CRIContext *s = avctx->priv_data; |
422 | | |
423 | 9.24k | av_frame_free(&s->jpgframe); |
424 | 9.24k | av_packet_free(&s->jpkt); |
425 | 9.24k | avcodec_free_context(&s->jpeg_avctx); |
426 | | |
427 | 9.24k | return 0; |
428 | 9.24k | } |
429 | | |
430 | | const FFCodec ff_cri_decoder = { |
431 | | .p.name = "cri", |
432 | | .p.type = AVMEDIA_TYPE_VIDEO, |
433 | | .p.id = AV_CODEC_ID_CRI, |
434 | | .priv_data_size = sizeof(CRIContext), |
435 | | .init = cri_decode_init, |
436 | | FF_CODEC_DECODE_CB(cri_decode_frame), |
437 | | .close = cri_decode_close, |
438 | | .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, |
439 | | .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | |
440 | | FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, |
441 | | CODEC_LONG_NAME("Cintel RAW"), |
442 | | }; |