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 
33 /**
34  * Rewrite the NALu stripping the unneeded blocks.
35  * Given that length fields coded inside the NALu are not aware of any emulation_3bytes
36  * present in the bitstream, we need to keep track of the raw buffer as we navigate
37  * the stripped buffer in order to write proper NALu sizes.
38  */
40  const H2645NAL *nal)
41 {
42  GetByteContext gbc, raw_gbc;
43  int64_t start = avio_tell(pb), end;
44  int sc = 0, gc = 0;
45  int skipped_byte_pos = 0, nalu_length = 3;
46 
47  bytestream2_init(&gbc, nal->data, nal->size);
48  bytestream2_init(&raw_gbc, nal->raw_data, nal->raw_size);
49  avio_wb16(pb, 0); // size placeholder
50  avio_wb16(pb, bytestream2_get_be16(&gbc)); // nal_unit_header
51  bytestream2_skip(&raw_gbc, 2);
52 
53  while (bytestream2_get_bytes_left(&gbc) > 1 && (!sc || !gc)) {
54  GetBitContext gb;
55  uint64_t payload_size;
56  int payload_size_type, payload_type;
57  int block_size, raw_block_size, block_end;
58 
60 
61  payload_size_type = get_bits(&gb, 3);
62  payload_type = get_bits(&gb, 5);
63  payload_size = payload_size_type;
64  if (payload_size_type == 6)
65  return AVERROR_PATCHWELCOME;
66  if (payload_size_type == 7)
67  payload_size = get_mb(&gb);
68 
69  if (payload_size > INT_MAX - (get_bits_count(&gb) >> 3))
70  return AVERROR_INVALIDDATA;
71 
72  block_size = raw_block_size = payload_size + (get_bits_count(&gb) >> 3);
73  if (block_size >= bytestream2_get_bytes_left(&gbc))
74  return AVERROR_INVALIDDATA;
75 
76  block_end = bytestream2_tell(&gbc) + block_size;
77  // Take into account removed emulation 3bytes, as payload_size in
78  // the bitstream is not aware of them.
79  for (; skipped_byte_pos < nal->skipped_bytes; skipped_byte_pos++) {
80  if (nal->skipped_bytes_pos[skipped_byte_pos] >= block_end)
81  break;
82  raw_block_size++;
83  }
84 
85  switch (payload_type) {
86  case 0:
87  if (sc)
88  break;
89 
90  lvcc->profile_idc = get_bits(&gb, 4);
91  lvcc->level_idc = get_bits(&gb, 4);
92 
93  avio_write(pb, raw_gbc.buffer, raw_block_size);
94  nalu_length += raw_block_size;
95  sc = 1;
96  break;
97  case 1: {
98  int resolution_type, bit_depth;
99  int processed_planes_type_flag;
100 
101  if (gc)
102  break;
103 
104  processed_planes_type_flag = get_bits1(&gb);
105  resolution_type = get_bits(&gb, 6);
106 
107  skip_bits1(&gb);
108  lvcc->chroma_format_idc = get_bits(&gb, 2);
109 
110  skip_bits(&gb, 2);
111  bit_depth = get_bits(&gb, 2) * 2; // enhancement_depth_type
114 
115  if (resolution_type < 63) {
118  } else {
119  int upsample_type, tile_dimensions_type;
120  int temporal_step_width_modifier_signalled_flag, level1_filtering_signalled_flag;
121  // Skip syntax elements until we get to the custom dimension ones
122  temporal_step_width_modifier_signalled_flag = get_bits1(&gb);
123  skip_bits(&gb, 3);
124  upsample_type = get_bits(&gb, 3);
125  level1_filtering_signalled_flag = get_bits1(&gb);
126  skip_bits(&gb, 4);
127  tile_dimensions_type = get_bits(&gb, 2);
128  skip_bits(&gb, 4);
129  if (processed_planes_type_flag)
130  skip_bits(&gb, 4);
131  if (temporal_step_width_modifier_signalled_flag)
132  skip_bits(&gb, 8);
133  if (upsample_type)
134  skip_bits_long(&gb, 64);
135  if (level1_filtering_signalled_flag)
136  skip_bits(&gb, 8);
137  if (tile_dimensions_type) {
138  if (tile_dimensions_type == 3)
139  skip_bits_long(&gb, 32);
140  skip_bits(&gb, 8);
141  }
142 
143  lvcc->pic_width_in_luma_samples = get_bits(&gb, 16);
144  lvcc->pic_height_in_luma_samples = get_bits(&gb, 16);
145  }
146 
148  break;
149 
150  avio_write(pb, raw_gbc.buffer, raw_block_size);
151  nalu_length += raw_block_size;
152  gc = 1;
153  break;
154  }
155  case 5:
156  avio_write(pb, raw_gbc.buffer, raw_block_size);
157  nalu_length += raw_block_size;
158  break;
159  default:
160  break;
161  }
162 
163  bytestream2_skip(&gbc, block_size);
164  bytestream2_skip(&raw_gbc, raw_block_size);
165  }
166 
167  if (!sc || !gc)
168  return AVERROR_INVALIDDATA;
169 
170  avio_w8(pb, 0x80); // rbsp_alignment bits
171 
172  end = avio_tell(pb);
173  avio_seek(pb, start, SEEK_SET);
174  avio_wb16(pb, nalu_length);
175  avio_seek(pb, end, SEEK_SET);
176 
177  return 0;
178 }
179 
181  const uint8_t *buf, int size)
182 {
183  H2645Packet h2645_pkt = { 0 };
184  AVIOContext *pb;
185  int ret;
186 
187  if (size <= 0)
188  return AVERROR_INVALIDDATA;
189 
190  if (buf[0] == 1) {
191  GetBitContext gb;
192 
193  if (size < 13)
194  return AVERROR_INVALIDDATA;
195 
196  ret = init_get_bits8(&gb, buf, 13);
197  if (ret < 0)
198  return ret;
199 
200  memset(lvcc, 0, sizeof(*lvcc));
201 
202  skip_bits(&gb, 8);
203  lvcc->profile_idc = get_bits(&gb, 8);
204  lvcc->level_idc = get_bits(&gb, 8);
205  lvcc->chroma_format_idc = get_bits(&gb, 2);
206  lvcc->bit_depth_luma_minus8 = get_bits(&gb, 3);
207  lvcc->bit_depth_chroma_minus8 = get_bits(&gb, 3);
208  skip_bits(&gb, 8);
209  lvcc->pic_width_in_luma_samples = get_bits_long(&gb, 32);
210  lvcc->pic_height_in_luma_samples = get_bits_long(&gb, 32);
211 
212  return 0;
213  }
214 
215  ret = ffio_open_null_buf(&pb);
216  if (ret < 0)
217  return ret;
218 
219  ret = ff_h2645_packet_split(&h2645_pkt, buf, size, NULL, 0, AV_CODEC_ID_LCEVC, 0);
220  if (ret < 0)
221  goto fail;
222 
223  /* look for IDR or NON_IDR */
224  for (int i = 0; i < h2645_pkt.nb_nals; i++) {
225  const H2645NAL *nal = &h2645_pkt.nals[i];
226 
227  if (nal->type == LCEVC_IDR_NUT) {
228  ret = write_nalu(lvcc, pb, nal);
229  if (ret < 0)
230  goto fail;
231  } else if (nal->type == LCEVC_NON_IDR_NUT) {
232  ret = write_nalu(lvcc, pb, nal);
233  if (ret < 0)
234  goto fail;
235  }
236  }
237 
238  ret = 0;
239 fail:
241  ff_h2645_packet_uninit(&h2645_pkt);
242 
243  return ret;
244 }
245 
246 int ff_isom_write_lvcc(AVIOContext *pb, const uint8_t *data, int len)
247 {
248  LCEVCDecoderConfigurationRecord lvcc = { 0 };
249  AVIOContext *idr_pb = NULL, *nidr_pb = NULL;
250  H2645Packet h2645_pkt = { 0 };
251  uint8_t *idr, *nidr;
252  uint32_t idr_size = 0, nidr_size = 0;
253  int ret, nb_idr = 0, nb_nidr = 0;
254 
255  if (len <= 6)
256  return AVERROR_INVALIDDATA;
257 
258  /* check for start code */
259  if (AV_RB32(data) != 0x00000001 &&
260  AV_RB24(data) != 0x000001) {
261  avio_write(pb, data, len);
262  return 0;
263  }
264 
265  ret = ff_h2645_packet_split(&h2645_pkt, data, len, NULL, 0, AV_CODEC_ID_LCEVC, 0);
266  if (ret < 0)
267  return ret;
268 
269  ret = avio_open_dyn_buf(&idr_pb);
270  if (ret < 0)
271  goto fail;
272  ret = avio_open_dyn_buf(&nidr_pb);
273  if (ret < 0)
274  goto fail;
275 
276  /* look for IDR or NON_IDR */
277  for (int i = 0; i < h2645_pkt.nb_nals; i++) {
278  const H2645NAL *nal = &h2645_pkt.nals[i];
279 
280  if (nal->type == LCEVC_IDR_NUT) {
281  nb_idr++;
282 
283  ret = write_nalu(&lvcc, idr_pb, nal);
284  if (ret < 0)
285  goto fail;
286  } else if (nal->type == LCEVC_NON_IDR_NUT) {
287  nb_nidr++;
288 
289  ret = write_nalu(&lvcc, nidr_pb, nal);
290  if (ret < 0)
291  goto fail;
292  }
293  }
294  idr_size = avio_get_dyn_buf(idr_pb, &idr);
295  nidr_size = avio_get_dyn_buf(nidr_pb, &nidr);
296 
297  if (!idr_size && !nidr_size) {
299  goto fail;
300  }
301 
302  avio_w8(pb, 1); /* version */
303  avio_w8(pb, lvcc.profile_idc);
304  avio_w8(pb, lvcc.level_idc);
305  avio_w8(pb, (lvcc.chroma_format_idc << 6) |
306  (lvcc.bit_depth_luma_minus8 << 3) |
308  avio_w8(pb, 0xff); /* 2 bits nal size length - 1 (11) + 6 bits reserved (111111)*/
311  avio_w8(pb, 0xff);
312 
313  int nb_arrays = !!nb_idr + !!nb_nidr;
314  avio_w8(pb, nb_arrays);
315 
316  if (nb_idr) {
317  avio_w8(pb, LCEVC_IDR_NUT);
318  avio_wb16(pb, nb_idr);
319  avio_write(pb, idr, idr_size);
320  }
321  if (nb_nidr) {
323  avio_wb16(pb, nb_nidr);
324  avio_write(pb, nidr, nidr_size);
325  }
326 
327  ret = 0;
328 fail:
329  ffio_free_dyn_buf(&idr_pb);
330  ffio_free_dyn_buf(&nidr_pb);
331  ff_h2645_packet_uninit(&h2645_pkt);
332 
333  return ret;
334 }
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
get_bits_long
static unsigned int get_bits_long(GetBitContext *s, int n)
Read 0-32 bits.
Definition: get_bits.h:424
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:246
ff_lcvec_parse_config_record
int ff_lcvec_parse_config_record(LCEVCDecoderConfigurationRecord *lvcc, const uint8_t *buf, int size)
Definition: lcevc.c:180
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.h:30
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:221
ffio_open_null_buf
int ffio_open_null_buf(AVIOContext **s)
Open a write-only fake memory stream.
Definition: aviobuf.c:1462
GetBitContext
Definition: get_bits.h:109
LCEVCDecoderConfigurationRecord::bit_depth_luma_minus8
uint8_t bit_depth_luma_minus8
Definition: lcevc.h:31
avio_tell
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:494
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:39
NULL
#define NULL
Definition: coverity.c:32
AVERROR_PATCHWELCOME
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:64
ffio_close_null_buf
int ffio_close_null_buf(AVIOContext *s)
Close a null buffer.
Definition: aviobuf.c:1472
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.h:33
size
int size
Definition: twinvq_data.h:10344
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.h:34
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.h:32
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.h:27
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.h:29
mem.h
LCEVCDecoderConfigurationRecord::profile_idc
uint8_t profile_idc
Definition: lcevc.h:28
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