FFmpeg
lcevc.c
Go to the documentation of this file.
1 /*
2  * LCEVC helper functions for muxers
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/error.h"
22 #include "libavutil/intreadwrite.h"
23 #include "libavutil/mem.h"
24 #include "libavcodec/bytestream.h"
25 #include "libavcodec/h2645_parse.h"
26 #include "libavcodec/lcevc.h"
27 #include "libavcodec/lcevctab.h"
28 #include "libavcodec/lcevc_parse.h"
29 #include "avio.h"
30 #include "avio_internal.h"
31 #include "lcevc.h"
32 
34  uint8_t profile_idc;
35  uint8_t level_idc;
42 
43 /**
44  * Rewrite the NALu stripping the unneeded blocks.
45  * Given that length fields coded inside the NALu are not aware of any emulation_3bytes
46  * present in the bitstream, we need to keep track of the raw buffer as we navigate
47  * the stripped buffer in order to write proper NALu sizes.
48  */
50  const H2645NAL *nal)
51 {
52  GetByteContext gbc, raw_gbc;
53  int64_t start = avio_tell(pb), end;
54  int sc = 0, gc = 0;
55  int skipped_byte_pos = 0, nalu_length = 3;
56 
57  bytestream2_init(&gbc, nal->data, nal->size);
58  bytestream2_init(&raw_gbc, nal->raw_data, nal->raw_size);
59  avio_wb16(pb, 0); // size placeholder
60  avio_wb16(pb, bytestream2_get_be16(&gbc)); // nal_unit_header
61  bytestream2_skip(&raw_gbc, 2);
62 
63  while (bytestream2_get_bytes_left(&gbc) > 1 && (!sc || !gc)) {
64  GetBitContext gb;
65  uint64_t payload_size;
66  int payload_size_type, payload_type;
67  int block_size, raw_block_size, block_end;
68 
70 
71  payload_size_type = get_bits(&gb, 3);
72  payload_type = get_bits(&gb, 5);
73  payload_size = payload_size_type;
74  if (payload_size_type == 6)
75  return AVERROR_PATCHWELCOME;
76  if (payload_size_type == 7)
77  payload_size = get_mb(&gb);
78 
79  if (payload_size > INT_MAX - (get_bits_count(&gb) >> 3))
80  return AVERROR_INVALIDDATA;
81 
82  block_size = raw_block_size = payload_size + (get_bits_count(&gb) >> 3);
83  if (block_size >= bytestream2_get_bytes_left(&gbc))
84  return AVERROR_INVALIDDATA;
85 
86  block_end = bytestream2_tell(&gbc) + block_size;
87  // Take into account removed emulation 3bytes, as payload_size in
88  // the bitstream is not aware of them.
89  for (; skipped_byte_pos < nal->skipped_bytes; skipped_byte_pos++) {
90  if (nal->skipped_bytes_pos[skipped_byte_pos] >= block_end)
91  break;
92  raw_block_size++;
93  }
94 
95  switch (payload_type) {
96  case 0:
97  if (sc)
98  break;
99 
100  lvcc->profile_idc = get_bits(&gb, 4);
101  lvcc->level_idc = get_bits(&gb, 4);
102 
103  avio_write(pb, raw_gbc.buffer, raw_block_size);
104  nalu_length += raw_block_size;
105  sc = 1;
106  break;
107  case 1: {
108  int resolution_type, bit_depth;
109  int processed_planes_type_flag;
110 
111  if (gc)
112  break;
113 
114  processed_planes_type_flag = get_bits1(&gb);
115  resolution_type = get_bits(&gb, 6);
116 
117  skip_bits1(&gb);
118  lvcc->chroma_format_idc = get_bits(&gb, 2);
119 
120  skip_bits(&gb, 2);
121  bit_depth = get_bits(&gb, 2) * 2; // enhancement_depth_type
124 
125  if (resolution_type < 63) {
128  } else {
129  int upsample_type, tile_dimensions_type;
130  int temporal_step_width_modifier_signalled_flag, level1_filtering_signalled_flag;
131  // Skip syntax elements until we get to the custom dimension ones
132  temporal_step_width_modifier_signalled_flag = get_bits1(&gb);
133  skip_bits(&gb, 3);
134  upsample_type = get_bits(&gb, 3);
135  level1_filtering_signalled_flag = get_bits1(&gb);
136  skip_bits(&gb, 4);
137  tile_dimensions_type = get_bits(&gb, 2);
138  skip_bits(&gb, 4);
139  if (processed_planes_type_flag)
140  skip_bits(&gb, 4);
141  if (temporal_step_width_modifier_signalled_flag)
142  skip_bits(&gb, 8);
143  if (upsample_type)
144  skip_bits_long(&gb, 64);
145  if (level1_filtering_signalled_flag)
146  skip_bits(&gb, 8);
147  if (tile_dimensions_type) {
148  if (tile_dimensions_type == 3)
149  skip_bits_long(&gb, 32);
150  skip_bits(&gb, 8);
151  }
152 
153  lvcc->pic_width_in_luma_samples = get_bits(&gb, 16);
154  lvcc->pic_height_in_luma_samples = get_bits(&gb, 16);
155  }
156 
158  break;
159 
160  avio_write(pb, raw_gbc.buffer, raw_block_size);
161  nalu_length += raw_block_size;
162  gc = 1;
163  break;
164  }
165  case 5:
166  avio_write(pb, raw_gbc.buffer, raw_block_size);
167  nalu_length += raw_block_size;
168  break;
169  default:
170  break;
171  }
172 
173  bytestream2_skip(&gbc, block_size);
174  bytestream2_skip(&raw_gbc, raw_block_size);
175  }
176 
177  if (!sc || !gc)
178  return AVERROR_INVALIDDATA;
179 
180  avio_w8(pb, 0x80); // rbsp_alignment bits
181 
182  end = avio_tell(pb);
183  avio_seek(pb, start, SEEK_SET);
184  avio_wb16(pb, nalu_length);
185  avio_seek(pb, end, SEEK_SET);
186 
187  return 0;
188 }
189 
190 int ff_isom_write_lvcc(AVIOContext *pb, const uint8_t *data, int len)
191 {
192  LCEVCDecoderConfigurationRecord lvcc = { 0 };
193  AVIOContext *idr_pb = NULL, *nidr_pb = NULL;
194  H2645Packet h2645_pkt = { 0 };
195  uint8_t *idr, *nidr;
196  uint32_t idr_size = 0, nidr_size = 0;
197  int ret, nb_idr = 0, nb_nidr = 0;
198 
199  if (len <= 6)
200  return AVERROR_INVALIDDATA;
201 
202  /* check for start code */
203  if (AV_RB32(data) != 0x00000001 &&
204  AV_RB24(data) != 0x000001) {
205  avio_write(pb, data, len);
206  return 0;
207  }
208 
209  ret = ff_h2645_packet_split(&h2645_pkt, data, len, NULL, 0, AV_CODEC_ID_LCEVC, 0);
210  if (ret < 0)
211  return ret;
212 
213  ret = avio_open_dyn_buf(&idr_pb);
214  if (ret < 0)
215  goto fail;
216  ret = avio_open_dyn_buf(&nidr_pb);
217  if (ret < 0)
218  goto fail;
219 
220  /* look for IDR or NON_IDR */
221  for (int i = 0; i < h2645_pkt.nb_nals; i++) {
222  const H2645NAL *nal = &h2645_pkt.nals[i];
223 
224  if (nal->type == LCEVC_IDR_NUT) {
225  nb_idr++;
226 
227  ret = write_nalu(&lvcc, idr_pb, nal);
228  if (ret < 0)
229  goto fail;
230  } else if (nal->type == LCEVC_NON_IDR_NUT) {
231  nb_nidr++;
232 
233  ret = write_nalu(&lvcc, nidr_pb, nal);
234  if (ret < 0)
235  goto fail;
236  }
237  }
238  idr_size = avio_get_dyn_buf(idr_pb, &idr);
239  nidr_size = avio_get_dyn_buf(nidr_pb, &nidr);
240 
241  if (!idr_size && !nidr_size) {
243  goto fail;
244  }
245 
246  avio_w8(pb, 1); /* version */
247  avio_w8(pb, lvcc.profile_idc);
248  avio_w8(pb, lvcc.level_idc);
249  avio_w8(pb, (lvcc.chroma_format_idc << 6) |
250  (lvcc.bit_depth_luma_minus8 << 3) |
252  avio_w8(pb, 0xff); /* 2 bits nal size length - 1 (11) + 6 bits reserved (111111)*/
255  avio_w8(pb, 0xff);
256 
257  int nb_arrays = !!nb_idr + !!nb_nidr;
258  avio_w8(pb, nb_arrays);
259 
260  if (nb_idr) {
261  avio_w8(pb, LCEVC_IDR_NUT);
262  avio_wb16(pb, nb_idr);
263  avio_write(pb, idr, idr_size);
264  }
265  if (nb_nidr) {
267  avio_wb16(pb, nb_nidr);
268  avio_write(pb, nidr, nidr_size);
269  }
270 
271  ret = 0;
272 fail:
273  ffio_free_dyn_buf(&idr_pb);
274  ffio_free_dyn_buf(&nidr_pb);
275  ff_h2645_packet_uninit(&h2645_pkt);
276 
277  return ret;
278 }
skip_bits_long
static void skip_bits_long(GetBitContext *s, int n)
Skips the specified number of bits.
Definition: get_bits.h:280
h2645_parse.h
bytestream2_get_bytes_left
static av_always_inline int bytestream2_get_bytes_left(const GetByteContext *g)
Definition: bytestream.h:158
idr
static void idr(H264Context *h)
instantaneous decoder refresh.
Definition: h264dec.c:438
GetByteContext
Definition: bytestream.h:33
bytestream2_tell
static av_always_inline int bytestream2_tell(const GetByteContext *g)
Definition: bytestream.h:192
ff_h2645_packet_split
int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, void *logctx, int nal_length_size, enum AVCodecID codec_id, int flags)
Split an input packet into NAL units.
Definition: h2645_parse.c:527
int64_t
long long int64_t
Definition: coverity.c:34
get_bits_count
static int get_bits_count(const GetBitContext *s)
Definition: get_bits.h:254
data
const char data[16]
Definition: mxf.c:149
ff_isom_write_lvcc
int ff_isom_write_lvcc(AVIOContext *pb, const uint8_t *data, int len)
Definition: lcevc.c:190
lcevc_parse.h
ff_lcevc_resolution_type
const struct FFLCEVCDim ff_lcevc_resolution_type[63]
Definition: lcevctab.c:21
LCEVCDecoderConfigurationRecord::chroma_format_idc
uint8_t chroma_format_idc
Definition: lcevc.c:36
bit_depth
static void bit_depth(AudioStatsContext *s, const uint64_t *const mask, uint8_t *depth)
Definition: af_astats.c:246
avio_get_dyn_buf
int avio_get_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition: aviobuf.c:1377
H2645Packet::nb_nals
int nb_nals
Definition: h2645_parse.h:85
get_mb
static uint64_t get_mb(GetBitContext *s)
Definition: lcevc_parse.h:26
skip_bits
static void skip_bits(GetBitContext *s, int n)
Definition: get_bits.h:383
bytestream2_skip
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:168
get_bits
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition: get_bits.h:337
lcevc.h
fail
#define fail()
Definition: checkasm.h:220
GetBitContext
Definition: get_bits.h:109
avio_tell
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:494
LCEVCDecoderConfigurationRecord::bit_depth_luma_minus8
uint8_t bit_depth_luma_minus8
Definition: lcevc.c:37
LCEVC_NON_IDR_NUT
@ LCEVC_NON_IDR_NUT
Definition: lcevc.h:60
ff_h2645_packet_uninit
void ff_h2645_packet_uninit(H2645Packet *pkt)
Free all the allocated memory in the packet.
Definition: h2645_parse.c:685
init_get_bits8
static int init_get_bits8(GetBitContext *s, const uint8_t *buffer, int byte_size)
Initialize GetBitContext.
Definition: get_bits.h:544
avio_open_dyn_buf
int avio_open_dyn_buf(AVIOContext **s)
Open a write only memory stream.
Definition: aviobuf.c:1365
intreadwrite.h
GetByteContext::buffer
const uint8_t * buffer
Definition: bytestream.h:34
write_nalu
static int write_nalu(LCEVCDecoderConfigurationRecord *lvcc, AVIOContext *pb, const H2645NAL *nal)
Rewrite the NALu stripping the unneeded blocks.
Definition: lcevc.c:49
NULL
#define NULL
Definition: coverity.c:32
AVERROR_PATCHWELCOME
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:64
get_bits1
static unsigned int get_bits1(GetBitContext *s)
Definition: get_bits.h:391
avio_w8
void avio_w8(AVIOContext *s, int b)
Definition: aviobuf.c:184
error.h
AVIOContext
Bytestream IO Context.
Definition: avio.h:160
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
LCEVCDecoderConfigurationRecord::pic_width_in_luma_samples
uint32_t pic_width_in_luma_samples
Definition: lcevc.c:39
avio.h
AV_RB32
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_RB32
Definition: bytestream.h:96
H2645NAL
Definition: h2645_parse.h:34
LCEVCDecoderConfigurationRecord::pic_height_in_luma_samples
uint32_t pic_height_in_luma_samples
Definition: lcevc.c:40
avio_write
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:206
avio_wb32
void avio_wb32(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:368
AV_CODEC_ID_LCEVC
@ AV_CODEC_ID_LCEVC
Definition: codec_id.h:615
skip_bits1
static void skip_bits1(GetBitContext *s)
Definition: get_bits.h:416
LCEVCDecoderConfigurationRecord::bit_depth_chroma_minus8
uint8_t bit_depth_chroma_minus8
Definition: lcevc.c:38
FFLCEVCDim::height
uint16_t height
Definition: lcevctab.h:28
H2645Packet::nals
H2645NAL * nals
Definition: h2645_parse.h:83
avio_internal.h
nal
static int FUNC() nal(CodedBitstreamContext *ctx, RWContext *rw, LCEVCRawNAL *current, int nal_unit_type)
Definition: cbs_lcevc_syntax_template.c:655
LCEVCDecoderConfigurationRecord
Definition: lcevc.c:33
len
int len
Definition: vorbis_enc_data.h:426
FFLCEVCDim::width
uint16_t width
Definition: lcevctab.h:27
ffio_free_dyn_buf
void ffio_free_dyn_buf(AVIOContext **s)
Free a dynamic buffer.
Definition: aviobuf.c:1438
ret
ret
Definition: filter_design.txt:187
avio_seek
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:236
lcevctab.h
LCEVCDecoderConfigurationRecord::level_idc
uint8_t level_idc
Definition: lcevc.c:35
mem.h
LCEVCDecoderConfigurationRecord::profile_idc
uint8_t profile_idc
Definition: lcevc.c:34
bytestream.h
bytestream2_init
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:137
avio_wb16
void avio_wb16(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:446
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
AV_RB24
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_WB32 unsigned int_TMPL AV_RB24
Definition: bytestream.h:97
LCEVC_IDR_NUT
@ LCEVC_IDR_NUT
Definition: lcevc.h:61
H2645Packet
Definition: h2645_parse.h:82