FFmpeg  4.4.5
imm5.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019 Paul B Mahol
3  *
4  * This file is part of FFmpeg.
5  *
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.
10  *
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.
15  *
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
19  */
20 
21 #include "libavutil/intreadwrite.h"
22 
23 #include "avcodec.h"
24 #include "internal.h"
25 
26 typedef struct IMM5Context {
27  AVCodecContext *h264_avctx; // wrapper context for H264
28  AVCodecContext *hevc_avctx; // wrapper context for HEVC
29 } IMM5Context;
30 
31 static const struct IMM5_unit {
34 } IMM5_units[14] = {
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 },
49 };
50 
51 static av_cold int imm5_init(AVCodecContext *avctx)
52 {
53  IMM5Context *ctx = avctx->priv_data;
54  const AVCodec *codec;
55  int ret;
56 
58  if (!codec)
59  return AVERROR_BUG;
60  ctx->h264_avctx = avcodec_alloc_context3(codec);
61  if (!ctx->h264_avctx)
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);
67  if (ret < 0)
68  return ret;
69 
71  if (!codec)
72  return AVERROR_BUG;
73  ctx->hevc_avctx = avcodec_alloc_context3(codec);
74  if (!ctx->hevc_avctx)
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);
80  if (ret < 0)
81  return ret;
82 
83  return 0;
84 }
85 
86 static int imm5_decode_frame(AVCodecContext *avctx, void *data,
87  int *got_frame, AVPacket *avpkt)
88 {
89  IMM5Context *ctx = avctx->priv_data;
90  AVFrame *frame = data;
91  AVCodecContext *codec_avctx = ctx->h264_avctx;
92  int ret;
93 
94  if (avpkt->size > 24 && avpkt->data[8] <= 1 && AV_RL32(avpkt->data + 4) + 24ULL <= avpkt->size) {
95  int codec_type = avpkt->data[1];
96  int index = avpkt->data[10];
97  int new_size = AV_RL32(avpkt->data + 4);
98  int offset, off;
99 
100  if (codec_type == 0xA) {
101  codec_avctx = ctx->hevc_avctx;
102  } else if (index == 17) {
103  index = 4;
104  } else if (index == 18) {
105  index = 5;
106  }
107 
108  if (index >= 1 && index <= 12) {
109  ret = av_packet_make_writable(avpkt);
110  if (ret < 0)
111  return ret;
112 
113  index -= 1;
114  off = offset = IMM5_units[index].len;
115  if (codec_type == 2) {
116  offset += IMM5_units[12].len;
117  } else {
118  offset += IMM5_units[13].len;
119  }
120 
121  avpkt->data += 24 - offset;
122  avpkt->size = new_size + offset;
123 
124  memcpy(avpkt->data, IMM5_units[index].bits, IMM5_units[index].len);
125  if (codec_type == 2) {
126  memcpy(avpkt->data + off, IMM5_units[12].bits, IMM5_units[12].len);
127  } else {
128  memcpy(avpkt->data + off, IMM5_units[13].bits, IMM5_units[13].len);
129  }
130  } else {
131  avpkt->data += 24;
132  avpkt->size -= 24;
133  }
134  }
135 
136  ret = avcodec_send_packet(codec_avctx, avpkt);
137  if (ret < 0) {
138  av_log(avctx, AV_LOG_ERROR, "Error submitting a packet for decoding\n");
139  return ret;
140  }
141 
142  ret = avcodec_receive_frame(codec_avctx, frame);
143  if (ret < 0)
144  return ret;
145 
146  avctx->pix_fmt = codec_avctx->pix_fmt;
147  avctx->coded_width = codec_avctx->coded_width;
148  avctx->coded_height = codec_avctx->coded_height;
149  avctx->width = codec_avctx->width;
150  avctx->height = codec_avctx->height;
151  avctx->bit_rate = codec_avctx->bit_rate;
152  avctx->colorspace = codec_avctx->colorspace;
153  avctx->color_range = codec_avctx->color_range;
154  avctx->color_trc = codec_avctx->color_trc;
155  avctx->color_primaries = codec_avctx->color_primaries;
156  avctx->chroma_sample_location = codec_avctx->chroma_sample_location;
157 
158  *got_frame = 1;
159 
160  return avpkt->size;
161 }
162 
163 static void imm5_flush(AVCodecContext *avctx)
164 {
165  IMM5Context *ctx = avctx->priv_data;
166 
167  avcodec_flush_buffers(ctx->h264_avctx);
168  avcodec_flush_buffers(ctx->hevc_avctx);
169 }
170 
172 {
173  IMM5Context *ctx = avctx->priv_data;
174 
175  avcodec_free_context(&ctx->h264_avctx);
176  avcodec_free_context(&ctx->hevc_avctx);
177 
178  return 0;
179 }
180 
182  .name = "imm5",
183  .long_name = NULL_IF_CONFIG_SMALL("Infinity IMM5"),
184  .type = AVMEDIA_TYPE_VIDEO,
185  .id = AV_CODEC_ID_IMM5,
186  .init = imm5_init,
187  .decode = imm5_decode_frame,
188  .close = imm5_close,
189  .flush = imm5_flush,
190  .priv_data_size = sizeof(IMM5Context),
191  .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE |
193 };
#define av_cold
Definition: attributes.h:88
uint8_t
Libavcodec external API header.
#define AV_RL32
Definition: intreadwrite.h:146
#define NULL
Definition: coverity.c:32
static AVFrame * frame
int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options)
Initialize the AVCodecContext to use the given AVCodec.
Definition: avcodec.c:144
AVCodec * avcodec_find_decoder(enum AVCodecID id)
Find a registered decoder with a matching codec ID.
Definition: allcodecs.c:946
AVCodecContext * avcodec_alloc_context3(const AVCodec *codec)
Allocate an AVCodecContext and set its fields to default values.
Definition: options.c:173
void avcodec_free_context(AVCodecContext **avctx)
Free the codec context and everything associated with it and write NULL to the provided pointer.
Definition: options.c:188
@ AV_CODEC_ID_H264
Definition: codec_id.h:76
@ AV_CODEC_ID_HEVC
Definition: codec_id.h:223
@ AV_CODEC_ID_IMM5
Definition: codec_id.h:296
int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)
Return decoded output data from a decoder.
Definition: decode.c:652
int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt)
Supply raw packet data as input to a decoder.
Definition: decode.c:589
void avcodec_flush_buffers(AVCodecContext *avctx)
Reset the internal codec state / flush internal buffers.
Definition: avcodec.c:491
int av_packet_make_writable(AVPacket *pkt)
Create a writable reference for the data described by a given packet, avoiding data copy if possible.
Definition: avpacket.c:715
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:50
#define AVERROR(e)
Definition: error.h:43
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
int index
Definition: gxfenc.c:89
static int imm5_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: imm5.c:86
static void imm5_flush(AVCodecContext *avctx)
Definition: imm5.c:163
static const struct IMM5_unit IMM5_units[14]
static av_cold int imm5_init(AVCodecContext *avctx)
Definition: imm5.c:51
AVCodec ff_imm5_decoder
Definition: imm5.c:181
static av_cold int imm5_close(AVCodecContext *avctx)
Definition: imm5.c:171
#define FF_CODEC_CAP_INIT_THREADSAFE
The codec does not modify any global variables in the init function, allowing to call the init functi...
Definition: internal.h:41
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
Definition: internal.h:49
common internal API header
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
const char data[16]
Definition: mxf.c:142
enum AVMediaType codec_type
Definition: rtp.c:37
main external API structure.
Definition: avcodec.h:536
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:746
int width
picture width / height.
Definition: avcodec.h:709
int flags2
AV_CODEC_FLAG2_*.
Definition: avcodec.h:623
enum AVColorRange color_range
MPEG vs JPEG YUV range.
Definition: avcodec.h:1171
enum AVColorPrimaries color_primaries
Chromaticity coordinates of the source primaries.
Definition: avcodec.h:1150
int64_t bit_rate
the average bitrate
Definition: avcodec.h:586
enum AVColorSpace colorspace
YUV colorspace type.
Definition: avcodec.h:1164
int coded_height
Definition: avcodec.h:724
enum AVColorTransferCharacteristic color_trc
Color Transfer Characteristic.
Definition: avcodec.h:1157
int flags
AV_CODEC_FLAG_*.
Definition: avcodec.h:616
enum AVChromaLocation chroma_sample_location
This defines the location of chroma samples.
Definition: avcodec.h:1178
int coded_width
Bitstream width / height, may be different from width/height e.g.
Definition: avcodec.h:724
void * priv_data
Definition: avcodec.h:563
AVCodec.
Definition: codec.h:197
const char * name
Name of the codec implementation.
Definition: codec.h:204
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1363
This structure describes decoded (raw) audio or video data.
Definition: frame.h:318
This structure stores compressed data.
Definition: packet.h:346
int size
Definition: packet.h:370
uint8_t * data
Definition: packet.h:369
AVCodecContext * hevc_avctx
Definition: imm5.c:28
AVCodecContext * h264_avctx
Definition: imm5.c:27
Definition: imm5.c:31
uint8_t bits[14]
Definition: imm5.c:32
uint8_t len
Definition: imm5.c:33
#define av_log(a,...)
AVFormatContext * ctx
Definition: movenc.c:48
static const uint8_t offset[127][2]
Definition: vf_spp.c:107