Coverage Report

Created: 2026-07-25 07:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
};