4 * Copyright (c) 2020 Paul B Mahol
6 * This file is part of FFmpeg.
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.
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.
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
25 * Cintel RAW image decoder
28 #define BITSTREAM_READER_LE
30 #include "libavutil/intfloat.h"
31 #include "libavutil/display.h"
33 #include "bytestream.h"
34 #include "codec_internal.h"
39 typedef struct CRIContext
{
40 AVCodecContext
*jpeg_avctx
; // wrapper context for MJPEG
41 AVPacket
*jpkt
; // encoded JPEG tile
42 AVFrame
*jpgframe
; // decoded JPEG tile
48 uint64_t tile_size
[4];
51 static av_cold
int cri_decode_init(AVCodecContext
*avctx
)
53 CRIContext
*s
= avctx
->priv_data
;
57 s
->jpgframe
= av_frame_alloc();
59 return AVERROR(ENOMEM
);
61 s
->jpkt
= av_packet_alloc();
63 return AVERROR(ENOMEM
);
65 codec
= avcodec_find_decoder(AV_CODEC_ID_MJPEG
);
68 s
->jpeg_avctx
= avcodec_alloc_context3(codec
);
70 return AVERROR(ENOMEM
);
71 s
->jpeg_avctx
->flags
= avctx
->flags
;
72 s
->jpeg_avctx
->flags2
= avctx
->flags2
;
73 s
->jpeg_avctx
->idct_algo
= avctx
->idct_algo
;
74 ret
= avcodec_open2(s
->jpeg_avctx
, codec
, NULL
);
81 static void unpack_10bit(GetByteContext
*gb
, uint16_t *dst
, int shift
,
82 int w
, int h
, ptrdiff_t stride
)
88 uint32_t a0
, a1
, a2
, a3
;
89 if (bytestream2_get_bytes_left(gb
) < 4)
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
;
103 dst
[pos
] = (((a0
>> 13) & 0x3F) | ((a0
>> 14) & 0xFC0)) << shift
;
111 dst
[pos
] = (((a0
>> 26) & 7) | ((a1
& 0x1FF) << 3)) << shift
;
119 dst
[pos
] = (((a1
>> 10) & 0x1FF) | ((a1
>> 11) & 0xE00)) << shift
;
127 dst
[pos
] = (((a1
>> 23) & 0x3F) | ((a2
& 0x3F) << 6)) << shift
;
135 dst
[pos
] = (((a2
>> 7) & 0xFF8) | ((a2
>> 6) & 7)) << shift
;
143 dst
[pos
] = (((a3
& 7) << 9) | ((a2
>> 20) & 0x1FF)) << shift
;
151 dst
[pos
] = (((a3
>> 4) & 0xFC0) | ((a3
>> 3) & 0x3F)) << shift
;
159 dst
[pos
] = (((a3
>> 16) & 7) | ((a3
>> 17) & 0xFF8)) << shift
;
172 static int cri_decode_frame(AVCodecContext
*avctx
, AVFrame
*p
,
173 int *got_frame
, AVPacket
*avpkt
)
175 CRIContext
*s
= avctx
->priv_data
;
176 GetByteContext
*gb
= &s
->gb
;
177 int ret
, bps
, hflip
= 0, vflip
= 0;
178 AVFrameSideData
*rotation
;
184 bytestream2_init(gb
, avpkt
->data
, avpkt
->size
);
186 while (bytestream2_get_bytes_left(gb
) > 8) {
187 char codec_name
[1024];
188 uint32_t key
, length
;
192 key
= bytestream2_get_le32(gb
);
193 length
= bytestream2_get_le32(gb
);
198 return AVERROR_INVALIDDATA
;
200 if (bytestream2_get_le32(gb
) != MKTAG('D', 'V', 'C', 'C'))
201 return AVERROR_INVALIDDATA
;
205 return AVERROR_INVALIDDATA
;
206 width
= bytestream2_get_le32(gb
);
207 height
= bytestream2_get_le32(gb
);
208 s
->color_model
= bytestream2_get_le32(gb
);
209 if (bytestream2_get_le32(gb
) != 1)
210 return AVERROR_INVALIDDATA
;
211 ret
= ff_set_dimensions(avctx
, width
, height
);
218 return AVERROR_INVALIDDATA
;
220 if (bytestream2_get_le32(gb
) != 0)
221 return AVERROR_INVALIDDATA
;
224 bytestream2_get_buffer(gb
, codec_name
, FFMIN(length
, sizeof(codec_name
) - 1));
225 length
-= FFMIN(length
, sizeof(codec_name
) - 1);
226 if (strncmp(codec_name
, "cintel_craw", FFMIN(length
, sizeof(codec_name
) - 1)))
227 return AVERROR_INVALIDDATA
;
231 if (bytestream2_get_bytes_left(gb
) < length
)
232 return AVERROR_INVALIDDATA
;
233 s
->data
= gb
->buffer
;
234 s
->data_size
= length
;
238 return AVERROR_INVALIDDATA
;
239 hflip
= bytestream2_get_byte(gb
) != 0;
244 return AVERROR_INVALIDDATA
;
245 vflip
= bytestream2_get_byte(gb
) != 0;
250 return AVERROR_INVALIDDATA
;
251 framerate
= av_int2float(bytestream2_get_le32(gb
));
252 avctx
->framerate
.num
= framerate
* 1000;
253 avctx
->framerate
.den
= 1000;
257 return AVERROR_INVALIDDATA
;
259 for (int i
= 0; i
< 4; i
++)
260 s
->tile_size
[i
] = bytestream2_get_le64(gb
);
263 av_log(avctx
, AV_LOG_DEBUG
, "skipping unknown key %u of length %u\n", key
, length
);
265 bytestream2_skip(gb
, length
);
269 switch (s
->color_model
) {
272 avctx
->pix_fmt
= AV_PIX_FMT_BAYER_BGGR16
;
276 avctx
->pix_fmt
= AV_PIX_FMT_BAYER_GBRG16
;
280 avctx
->pix_fmt
= AV_PIX_FMT_BAYER_RGGB16
;
285 avctx
->pix_fmt
= AV_PIX_FMT_BAYER_GRBG16
;
289 switch (s
->color_model
) {
306 return AVERROR_INVALIDDATA
;
310 for (int i
= 0; i
< 4; i
++) {
311 if (s
->tile_size
[i
] >= s
->data_size
)
312 return AVERROR_INVALIDDATA
;
315 if (s
->tile_size
[0] + s
->tile_size
[1] + s
->tile_size
[2] + s
->tile_size
[3] !=
317 return AVERROR_INVALIDDATA
;
320 if (!s
->data
|| !s
->data_size
)
321 return AVERROR_INVALIDDATA
;
323 if (avctx
->skip_frame
>= AVDISCARD_ALL
)
326 if ((ret
= ff_thread_get_buffer(avctx
, p
, 0)) < 0)
329 avctx
->bits_per_raw_sample
= bps
;
331 if (!compressed
&& s
->color_model
== 45) {
332 uint16_t *dst
= (uint16_t *)p
->data
[0];
335 bytestream2_init(&gb
, s
->data
, s
->data_size
);
336 unpack_10bit(&gb
, dst
, 4, avctx
->width
, avctx
->height
, p
->linesize
[0] / 2);
337 } else if (!compressed
) {
339 const int shift
= 16 - bps
;
341 ret
= init_get_bits8(&gbit
, s
->data
, s
->data_size
);
345 for (int y
= 0; y
< avctx
->height
; y
++) {
346 uint16_t *dst
= (uint16_t *)(p
->data
[0] + y
* p
->linesize
[0]);
348 if (get_bits_left(&gbit
) < avctx
->width
* bps
)
351 for (int x
= 0; x
< avctx
->width
; x
++)
352 dst
[x
] = get_bits(&gbit
, bps
) << shift
;
357 for (int tile
= 0; tile
< 4; tile
++) {
358 av_packet_unref(s
->jpkt
);
359 s
->jpkt
->data
= (uint8_t *)s
->data
+ offset
;
360 s
->jpkt
->size
= s
->tile_size
[tile
];
362 ret
= avcodec_send_packet(s
->jpeg_avctx
, s
->jpkt
);
364 av_log(avctx
, AV_LOG_ERROR
, "Error submitting a packet for decoding\n");
368 ret
= avcodec_receive_frame(s
->jpeg_avctx
, s
->jpgframe
);
369 if (ret
< 0 || s
->jpgframe
->format
!= AV_PIX_FMT_GRAY16
||
370 s
->jpeg_avctx
->width
* 2 != avctx
->width
||
371 s
->jpeg_avctx
->height
* 2 != avctx
->height
) {
373 av_log(avctx
, AV_LOG_ERROR
,
374 "JPEG decoding error (%d).\n", ret
);
376 av_log(avctx
, AV_LOG_ERROR
,
377 "JPEG invalid format.\n");
378 ret
= AVERROR_INVALIDDATA
;
381 /* Normally skip, if error explode */
382 if (avctx
->err_recognition
& AV_EF_EXPLODE
)
388 for (int y
= 0; y
< s
->jpeg_avctx
->height
; y
++) {
389 const int hw
= s
->jpgframe
->width
/ 2;
390 uint16_t *dst
= (uint16_t *)(p
->data
[0] + (y
* 2) * p
->linesize
[0] + tile
* hw
* 2);
391 const uint16_t *src
= (const uint16_t *)(s
->jpgframe
->data
[0] + y
* s
->jpgframe
->linesize
[0]);
393 memcpy(dst
, src
, hw
* 2);
395 dst
+= p
->linesize
[0] / 2;
396 memcpy(dst
, src
, hw
* 2);
399 av_frame_unref(s
->jpgframe
);
400 offset
+= s
->tile_size
[tile
];
404 if (hflip
|| vflip
) {
405 ff_frame_new_side_data(avctx
, p
, AV_FRAME_DATA_DISPLAYMATRIX
,
406 sizeof(int32_t) * 9, &rotation
);
408 av_display_rotation_set((int32_t *)rotation
->data
, 0.f
);
409 av_display_matrix_flip((int32_t *)rotation
->data
, hflip
, vflip
);
418 static av_cold
int cri_decode_close(AVCodecContext
*avctx
)
420 CRIContext
*s
= avctx
->priv_data
;
422 av_frame_free(&s
->jpgframe
);
423 av_packet_free(&s
->jpkt
);
424 avcodec_free_context(&s
->jpeg_avctx
);
429 const FFCodec ff_cri_decoder
= {
431 .p
.type
= AVMEDIA_TYPE_VIDEO
,
432 .p
.id
= AV_CODEC_ID_CRI
,
433 .priv_data_size
= sizeof(CRIContext
),
434 .init
= cri_decode_init
,
435 FF_CODEC_DECODE_CB(cri_decode_frame
),
436 .close
= cri_decode_close
,
437 .p
.capabilities
= AV_CODEC_CAP_DR1
| AV_CODEC_CAP_FRAME_THREADS
,
438 .caps_internal
= FF_CODEC_CAP_INIT_CLEANUP
|
439 FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM
,
440 CODEC_LONG_NAME("Cintel RAW"),