FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/cri.c
Date: 2026-08-11 17:55:23
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