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