• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
39 typedef 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 
cri_decode_init(AVCodecContext * avctx)51 static 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 
unpack_10bit(GetByteContext * gb,uint16_t * dst,int shift,int w,int h,ptrdiff_t stride)82 static 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 
cri_decode_frame(AVCodecContext * avctx,AVFrame * p,int * got_frame,AVPacket * avpkt)173 static 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);
261 skip:
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 
cri_decode_close(AVCodecContext * avctx)415 static 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 
426 const 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