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