2 * Copyright (c) 2019 Paul B Mahol
4 * This file is part of FFmpeg.
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "libavutil/intreadwrite.h"
24 #include "codec_internal.h"
26 typedef struct IMM5Context
{
27 AVCodecContext
*h264_avctx
; // wrapper context for H264
28 AVCodecContext
*hevc_avctx
; // wrapper context for HEVC
31 static const struct IMM5_unit
{
35 { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x80, 0x1E, 0xF4, 0x0B, 0x0F, 0x88 }, 12 },
36 { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x80, 0x1E, 0xF4, 0x05, 0x83, 0xE2 }, 12 },
37 { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x80, 0x1E, 0xF4, 0x05, 0x81, 0xE8, 0x80 }, 13 },
38 { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x80, 0x1E, 0xF4, 0x0B, 0x04, 0xA2 }, 12 },
39 { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x80, 0x1E, 0xF4, 0x05, 0x81, 0x28, 0x80 }, 13 },
40 { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x80, 0x1E, 0xF4, 0x05, 0x80, 0x92, 0x20 }, 13 },
41 { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1E, 0x9A, 0x74, 0x0B, 0x0F, 0xC8 }, 13 },
42 { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1E, 0x9A, 0x74, 0x05, 0x83, 0xF2 }, 13 },
43 { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1E, 0x9A, 0x74, 0x05, 0x81, 0xEC, 0x80 }, 14 },
44 { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1E, 0x9A, 0x74, 0x0B, 0x04, 0xB2 }, 13 },
45 { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1E, 0x9A, 0x74, 0x05, 0x81, 0x2C, 0x80 }, 14 },
46 { { 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1E, 0x9A, 0x74, 0x05, 0x80, 0x93, 0x20 }, 14 },
47 { { 0x00, 0x00, 0x00, 0x01, 0x68, 0xDE, 0x3C, 0x80 }, 8 },
48 { { 0x00, 0x00, 0x00, 0x01, 0x68, 0xCE, 0x32, 0x28 }, 8 },
51 static av_cold
int imm5_init(AVCodecContext
*avctx
)
53 IMM5Context
*ctx
= avctx
->priv_data
;
57 codec
= avcodec_find_decoder(AV_CODEC_ID_H264
);
60 ctx
->h264_avctx
= avcodec_alloc_context3(codec
);
62 return AVERROR(ENOMEM
);
63 ctx
->h264_avctx
->thread_count
= 1;
64 ctx
->h264_avctx
->flags
= avctx
->flags
;
65 ctx
->h264_avctx
->flags2
= avctx
->flags2
;
66 ret
= avcodec_open2(ctx
->h264_avctx
, codec
, NULL
);
70 codec
= avcodec_find_decoder(AV_CODEC_ID_HEVC
);
73 ctx
->hevc_avctx
= avcodec_alloc_context3(codec
);
75 return AVERROR(ENOMEM
);
76 ctx
->hevc_avctx
->thread_count
= 1;
77 ctx
->hevc_avctx
->flags
= avctx
->flags
;
78 ctx
->hevc_avctx
->flags2
= avctx
->flags2
;
79 ret
= avcodec_open2(ctx
->hevc_avctx
, codec
, NULL
);
86 static int imm5_decode_frame(AVCodecContext
*avctx
, AVFrame
*frame
,
87 int *got_frame
, AVPacket
*avpkt
)
89 IMM5Context
*ctx
= avctx
->priv_data
;
90 AVCodecContext
*codec_avctx
= ctx
->h264_avctx
;
93 if (avpkt
->size
> 24 && avpkt
->data
[8] <= 1 && AV_RL32(avpkt
->data
+ 4) + 24ULL <= avpkt
->size
) {
94 int codec_type
= avpkt
->data
[1];
95 int index
= avpkt
->data
[10];
96 int new_size
= AV_RL32(avpkt
->data
+ 4);
99 if (codec_type
== 0xA) {
100 codec_avctx
= ctx
->hevc_avctx
;
101 } else if (index
== 17) {
103 } else if (index
== 18) {
107 if (index
>= 1 && index
<= 12) {
108 ret
= av_packet_make_writable(avpkt
);
113 off
= offset
= IMM5_units
[index
].len
;
114 if (codec_type
== 2) {
115 offset
+= IMM5_units
[12].len
;
117 offset
+= IMM5_units
[13].len
;
120 avpkt
->data
+= 24 - offset
;
121 avpkt
->size
= new_size
+ offset
;
123 memcpy(avpkt
->data
, IMM5_units
[index
].bits
, IMM5_units
[index
].len
);
124 if (codec_type
== 2) {
125 memcpy(avpkt
->data
+ off
, IMM5_units
[12].bits
, IMM5_units
[12].len
);
127 memcpy(avpkt
->data
+ off
, IMM5_units
[13].bits
, IMM5_units
[13].len
);
135 ret
= avcodec_send_packet(codec_avctx
, avpkt
);
137 av_log(avctx
, AV_LOG_ERROR
, "Error submitting a packet for decoding\n");
141 ret
= avcodec_receive_frame(codec_avctx
, frame
);
145 avctx
->pix_fmt
= codec_avctx
->pix_fmt
;
146 avctx
->coded_width
= codec_avctx
->coded_width
;
147 avctx
->coded_height
= codec_avctx
->coded_height
;
148 avctx
->width
= codec_avctx
->width
;
149 avctx
->height
= codec_avctx
->height
;
150 avctx
->bit_rate
= codec_avctx
->bit_rate
;
151 avctx
->colorspace
= codec_avctx
->colorspace
;
152 avctx
->color_range
= codec_avctx
->color_range
;
153 avctx
->color_trc
= codec_avctx
->color_trc
;
154 avctx
->color_primaries
= codec_avctx
->color_primaries
;
155 avctx
->chroma_sample_location
= codec_avctx
->chroma_sample_location
;
162 static void imm5_flush(AVCodecContext
*avctx
)
164 IMM5Context
*ctx
= avctx
->priv_data
;
166 avcodec_flush_buffers(ctx
->h264_avctx
);
167 avcodec_flush_buffers(ctx
->hevc_avctx
);
170 static av_cold
int imm5_close(AVCodecContext
*avctx
)
172 IMM5Context
*ctx
= avctx
->priv_data
;
174 avcodec_free_context(&ctx
->h264_avctx
);
175 avcodec_free_context(&ctx
->hevc_avctx
);
180 const FFCodec ff_imm5_decoder
= {
182 CODEC_LONG_NAME("Infinity IMM5"),
183 .p
.type
= AVMEDIA_TYPE_VIDEO
,
184 .p
.id
= AV_CODEC_ID_IMM5
,
186 FF_CODEC_DECODE_CB(imm5_decode_frame
),
189 .priv_data_size
= sizeof(IMM5Context
),
190 .caps_internal
= FF_CODEC_CAP_INIT_CLEANUP
,