FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/cri.c
Date: 2026-09-26 05:01:43
Exec Total Coverage
Lines: 0 272 0.0%
Functions: 0 4 0.0%
Branches: 0 153 0.0%

Line Branch Exec 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 {
54 ✗ CRIContext *s = avctx->priv_data;
55 int ret;
56
57 ✗ s->jpgframe = av_frame_alloc();
58 ✗ if (!s->jpgframe)
59 ✗ return AVERROR(ENOMEM);
60
61 ✗ s->jpkt = av_packet_alloc();
62 ✗ if (!s->jpkt)
63 ✗ return AVERROR(ENOMEM);
64
65 EXTERN const FFCodec ff_mjpeg_decoder;
66 ✗ s->jpeg_avctx = avcodec_alloc_context3(&ff_mjpeg_decoder.p);
67 ✗ if (!s->jpeg_avctx)
68 ✗ return AVERROR(ENOMEM);
69 ✗ s->jpeg_avctx->flags = avctx->flags;
70 ✗ s->jpeg_avctx->flags2 = avctx->flags2;
71 ✗ s->jpeg_avctx->idct_algo = avctx->idct_algo;
72 ✗ s->jpeg_avctx->max_pixels = avctx->max_pixels;
73 ✗ ret = avcodec_open2(s->jpeg_avctx, NULL, NULL);
74 ✗ if (ret < 0)
75 ✗ return ret;
76
77 ✗ return 0;
78 }
79
80 ✗ static void unpack_10bit(GetByteContext *gb, uint16_t *dst, int shift,
81 int w, int h, ptrdiff_t stride)
82 {
83 ✗ int count = w * h;
84 ✗ int pos = 0;
85
86 ✗ while (count > 0) {
87 uint32_t a0, a1, a2, a3;
88 ✗ if (bytestream2_get_bytes_left(gb) < 4)
89 ✗ break;
90 ✗ a0 = bytestream2_get_le32(gb);
91 ✗ a1 = bytestream2_get_le32(gb);
92 ✗ a2 = bytestream2_get_le32(gb);
93 ✗ a3 = bytestream2_get_le32(gb);
94 ✗ dst[pos] = (((a0 >> 1) & 0xE00) | (a0 & 0x1FF)) << shift;
95 ✗ pos++;
96 ✗ if (pos >= w) {
97 ✗ if (count == 1)
98 ✗ break;
99 ✗ dst += stride;
100 ✗ pos = 0;
101 }
102 ✗ dst[pos] = (((a0 >> 13) & 0x3F) | ((a0 >> 14) & 0xFC0)) << shift;
103 ✗ pos++;
104 ✗ if (pos >= w) {
105 ✗ if (count == 2)
106 ✗ break;
107 ✗ dst += stride;
108 ✗ pos = 0;
109 }
110 ✗ dst[pos] = (((a0 >> 26) & 7) | ((a1 & 0x1FF) << 3)) << shift;
111 ✗ pos++;
112 ✗ if (pos >= w) {
113 ✗ if (count == 3)
114 ✗ break;
115 ✗ dst += stride;
116 ✗ pos = 0;
117 }
118 ✗ dst[pos] = (((a1 >> 10) & 0x1FF) | ((a1 >> 11) & 0xE00)) << shift;
119 ✗ pos++;
120 ✗ if (pos >= w) {
121 ✗ if (count == 4)
122 ✗ break;
123 ✗ dst += stride;
124 ✗ pos = 0;
125 }
126 ✗ dst[pos] = (((a1 >> 23) & 0x3F) | ((a2 & 0x3F) << 6)) << shift;
127 ✗ pos++;
128 ✗ if (pos >= w) {
129 ✗ if (count == 5)
130 ✗ break;
131 ✗ dst += stride;
132 ✗ pos = 0;
133 }
134 ✗ dst[pos] = (((a2 >> 7) & 0xFF8) | ((a2 >> 6) & 7)) << shift;
135 ✗ pos++;
136 ✗ if (pos >= w) {
137 ✗ if (count == 6)
138 ✗ break;
139 ✗ dst += stride;
140 ✗ pos = 0;
141 }
142 ✗ dst[pos] = (((a3 & 7) << 9) | ((a2 >> 20) & 0x1FF)) << shift;
143 ✗ pos++;
144 ✗ if (pos >= w) {
145 ✗ if (count == 7)
146 ✗ break;
147 ✗ dst += stride;
148 ✗ pos = 0;
149 }
150 ✗ dst[pos] = (((a3 >> 4) & 0xFC0) | ((a3 >> 3) & 0x3F)) << shift;
151 ✗ pos++;
152 ✗ if (pos >= w) {
153 ✗ if (count == 8)
154 ✗ break;
155 ✗ dst += stride;
156 ✗ pos = 0;
157 }
158 ✗ dst[pos] = (((a3 >> 16) & 7) | ((a3 >> 17) & 0xFF8)) << shift;
159 ✗ pos++;
160 ✗ if (pos >= w) {
161 ✗ if (count == 9)
162 ✗ break;
163 ✗ dst += stride;
164 ✗ pos = 0;
165 }
166
167 ✗ count -= 9;
168 }
169 ✗ }
170
171 ✗ static int cri_decode_frame(AVCodecContext *avctx, AVFrame *p,
172 int *got_frame, AVPacket *avpkt)
173 {
174 ✗ CRIContext *s = avctx->priv_data;
175 ✗ GetByteContext *gb = &s->gb;
176 ✗ int ret, bps, hflip = 0, vflip = 0;
177 AVFrameSideData *rotation;
178 ✗ int compressed = 0;
179
180 ✗ s->data = NULL;
181 ✗ s->data_size = 0;
182
183 ✗ bytestream2_init(gb, avpkt->data, avpkt->size);
184
185 ✗ while (bytestream2_get_bytes_left(gb) > 8) {
186 char codec_name[1024];
187 uint32_t key, length;
188 float framerate;
189 int width, height;
190
191 ✗ key = bytestream2_get_le32(gb);
192 ✗ length = bytestream2_get_le32(gb);
193
194 ✗ switch (key) {
195 ✗ case 1:
196 ✗ if (length != 4)
197 ✗ return AVERROR_INVALIDDATA;
198
199 ✗ if (bytestream2_get_le32(gb) != MKTAG('D', 'V', 'C', 'C'))
200 ✗ return AVERROR_INVALIDDATA;
201 ✗ break;
202 ✗ case 100:
203 ✗ if (length < 16)
204 ✗ return AVERROR_INVALIDDATA;
205 ✗ width = bytestream2_get_le32(gb);
206 ✗ height = bytestream2_get_le32(gb);
207 ✗ s->color_model = bytestream2_get_le32(gb);
208 ✗ if (bytestream2_get_le32(gb) != 1)
209 ✗ return AVERROR_INVALIDDATA;
210 ✗ ret = ff_set_dimensions(avctx, width, height);
211 ✗ if (ret < 0)
212 ✗ return ret;
213 ✗ length -= 16;
214 ✗ goto skip;
215 ✗ case 101:
216 ✗ if (length != 4)
217 ✗ return AVERROR_INVALIDDATA;
218
219 ✗ if (bytestream2_get_le32(gb) != 0)
220 ✗ return AVERROR_INVALIDDATA;
221 ✗ break;
222 ✗ case 102:;
223 ✗ int read_len = FFMIN(length, sizeof(codec_name) - 1);
224 ✗ if (read_len != bytestream2_get_buffer(gb, codec_name, read_len))
225 ✗ return AVERROR_INVALIDDATA;
226 ✗ length -= read_len;
227 ✗ if (strncmp(codec_name, "cintel_craw", read_len))
228 ✗ return AVERROR_INVALIDDATA;
229 ✗ compressed = 1;
230 ✗ goto skip;
231 ✗ case 103:
232 ✗ if (bytestream2_get_bytes_left(gb) < length)
233 ✗ return AVERROR_INVALIDDATA;
234 ✗ s->data = gb->buffer;
235 ✗ s->data_size = length;
236 ✗ goto skip;
237 ✗ case 105:
238 ✗ if (length <= 0)
239 ✗ return AVERROR_INVALIDDATA;
240 ✗ hflip = bytestream2_get_byte(gb) != 0;
241 ✗ length--;
242 ✗ goto skip;
243 ✗ case 106:
244 ✗ if (length <= 0)
245 ✗ return AVERROR_INVALIDDATA;
246 ✗ vflip = bytestream2_get_byte(gb) != 0;
247 ✗ length--;
248 ✗ goto skip;
249 ✗ case 107:
250 ✗ if (length != 4)
251 ✗ return AVERROR_INVALIDDATA;
252 ✗ framerate = av_int2float(bytestream2_get_le32(gb));
253 ✗ avctx->framerate.num = framerate * 1000;
254 ✗ avctx->framerate.den = 1000;
255 ✗ break;
256 ✗ case 119:
257 ✗ if (length != 32)
258 ✗ return AVERROR_INVALIDDATA;
259
260 ✗ for (int i = 0; i < 4; i++)
261 ✗ s->tile_size[i] = bytestream2_get_le64(gb);
262 ✗ break;
263 ✗ default:
264 ✗ av_log(avctx, AV_LOG_DEBUG, "skipping unknown key %u of length %u\n", key, length);
265 ✗ skip:
266 ✗ bytestream2_skip(gb, length);
267 }
268 }
269
270 ✗ switch (s->color_model) {
271 ✗ case 76:
272 case 88:
273 ✗ avctx->pix_fmt = AV_PIX_FMT_BAYER_BGGR16;
274 ✗ break;
275 ✗ case 77:
276 case 89:
277 ✗ avctx->pix_fmt = AV_PIX_FMT_BAYER_GBRG16;
278 ✗ break;
279 ✗ case 78:
280 case 90:
281 ✗ avctx->pix_fmt = AV_PIX_FMT_BAYER_RGGB16;
282 ✗ break;
283 ✗ case 45:
284 case 79:
285 case 91:
286 ✗ avctx->pix_fmt = AV_PIX_FMT_BAYER_GRBG16;
287 ✗ break;
288 }
289
290 ✗ switch (s->color_model) {
291 ✗ case 45:
292 ✗ bps = 10;
293 ✗ break;
294 ✗ case 76:
295 case 77:
296 case 78:
297 case 79:
298 ✗ bps = 12;
299 ✗ break;
300 ✗ case 88:
301 case 89:
302 case 90:
303 case 91:
304 ✗ bps = 16;
305 ✗ break;
306 ✗ default:
307 ✗ return AVERROR_INVALIDDATA;
308 }
309
310 ✗ if (compressed) {
311 ✗ for (int i = 0; i < 4; i++) {
312 ✗ if (s->tile_size[i] >= s->data_size)
313 ✗ return AVERROR_INVALIDDATA;
314 }
315
316 ✗ if (s->tile_size[0] + s->tile_size[1] + s->tile_size[2] + s->tile_size[3] !=
317 ✗ s->data_size)
318 ✗ return AVERROR_INVALIDDATA;
319 }
320
321 ✗ if (!s->data || !s->data_size)
322 ✗ return AVERROR_INVALIDDATA;
323
324 ✗ if (avctx->skip_frame >= AVDISCARD_ALL)
325 ✗ return avpkt->size;
326
327 ✗ if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0)
328 ✗ return ret;
329
330 ✗ avctx->bits_per_raw_sample = bps;
331
332 ✗ if (!compressed && s->color_model == 45) {
333 ✗ uint16_t *dst = (uint16_t *)p->data[0];
334 GetByteContext gb;
335
336 ✗ bytestream2_init(&gb, s->data, s->data_size);
337 ✗ unpack_10bit(&gb, dst, 4, avctx->width, avctx->height, p->linesize[0] / 2);
338 ✗ } else if (!compressed) {
339 GetBitContext gbit;
340 ✗ const int shift = 16 - bps;
341
342 ✗ ret = init_get_bits8(&gbit, s->data, s->data_size);
343 ✗ if (ret < 0)
344 ✗ return ret;
345
346 ✗ for (int y = 0; y < avctx->height; y++) {
347 ✗ uint16_t *dst = (uint16_t *)(p->data[0] + y * p->linesize[0]);
348
349 ✗ if (get_bits_left(&gbit) < avctx->width * bps)
350 ✗ break;
351
352 ✗ for (int x = 0; x < avctx->width; x++)
353 ✗ dst[x] = get_bits(&gbit, bps) << shift;
354 }
355 } else {
356 ✗ unsigned offset = 0;
357
358 ✗ for (int tile = 0; tile < 4; tile++) {
359 ✗ av_packet_unref(s->jpkt);
360 ✗ s->jpkt->data = (uint8_t *)s->data + offset;
361 ✗ s->jpkt->size = s->tile_size[tile];
362
363 ✗ ret = avcodec_send_packet(s->jpeg_avctx, s->jpkt);
364 ✗ if (ret < 0) {
365 ✗ av_log(avctx, AV_LOG_ERROR, "Error submitting a packet for decoding\n");
366 ✗ return ret;
367 }
368
369 ✗ ret = avcodec_receive_frame(s->jpeg_avctx, s->jpgframe);
370 ✗ if (ret < 0 || s->jpgframe->format != AV_PIX_FMT_GRAY16 ||
371 ✗ s->jpeg_avctx->width * 2 != avctx->width ||
372 ✗ s->jpeg_avctx->height * 2 != avctx->height) {
373 ✗ if (ret < 0) {
374 ✗ av_log(avctx, AV_LOG_ERROR,
375 "JPEG decoding error (%d).\n", ret);
376 } else {
377 ✗ av_log(avctx, AV_LOG_ERROR,
378 "JPEG invalid format.\n");
379 ✗ ret = AVERROR_INVALIDDATA;
380 }
381
382 /* Normally skip, if error explode */
383 ✗ if (avctx->err_recognition & AV_EF_EXPLODE)
384 ✗ return ret;
385 else
386 ✗ return 0;
387 }
388
389 ✗ for (int y = 0; y < s->jpeg_avctx->height; y++) {
390 ✗ const int hw = s->jpgframe->width / 2;
391 ✗ uint16_t *dst = (uint16_t *)(p->data[0] + (y * 2) * p->linesize[0] + tile * hw * 2);
392 ✗ const uint16_t *src = (const uint16_t *)(s->jpgframe->data[0] + y * s->jpgframe->linesize[0]);
393
394 ✗ memcpy(dst, src, hw * 2);
395 ✗ src += hw;
396 ✗ dst += p->linesize[0] / 2;
397 ✗ memcpy(dst, src, hw * 2);
398 }
399
400 ✗ av_frame_unref(s->jpgframe);
401 ✗ offset += s->tile_size[tile];
402 }
403 }
404
405 ✗ if (hflip || vflip) {
406 ✗ ff_frame_new_side_data(avctx, p, AV_FRAME_DATA_DISPLAYMATRIX,
407 sizeof(int32_t) * 9, &rotation);
408 ✗ if (rotation) {
409 ✗ av_display_rotation_set((int32_t *)rotation->data, 0.f);
410 ✗ av_display_matrix_flip((int32_t *)rotation->data, hflip, vflip);
411 }
412 }
413
414 ✗ *got_frame = 1;
415
416 ✗ return 0;
417 }
418
419 ✗ static av_cold int cri_decode_close(AVCodecContext *avctx)
420 {
421 ✗ CRIContext *s = avctx->priv_data;
422
423 ✗ av_frame_free(&s->jpgframe);
424 ✗ av_packet_free(&s->jpkt);
425 ✗ avcodec_free_context(&s->jpeg_avctx);
426
427 ✗ return 0;
428 }
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 };
443