FFmpeg
lcevc_parser.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include <stdint.h>
20 
21 #include "libavutil/mem.h"
22 
23 #include "avcodec.h"
24 #include "bytestream.h"
25 #include "get_bits.h"
26 #include "h2645_parse.h"
27 #include "lcevc.h"
28 #include "lcevc_parse.h"
29 #include "lcevctab.h"
30 #include "parser.h"
31 #include "parser_internal.h"
32 
33 #define START_CODE 0x000001 ///< start_code_prefix_one_3bytes
34 
35 typedef struct LCEVCParserContext {
37 
39 
41  int is_lvcc;
44 
45 static int lcevc_find_frame_end(AVCodecParserContext *s, const uint8_t *buf,
46  int buf_size)
47 {
48  LCEVCParserContext *ctx = s->priv_data;
49  ParseContext *pc = &ctx->pc;
50 
51  for (int i = 0; i < buf_size; i++) {
52  int nut;
53 
54  pc->state = (pc->state << 8) | buf[i];
55 
56  if (((pc->state >> 8) & 0xFFFFFF) != START_CODE)
57  continue;
58 
59  nut = (pc->state >> 1) & 0x1F;
60 
61  // Beginning of access unit
62  if (nut == LCEVC_IDR_NUT || nut == LCEVC_NON_IDR_NUT) {
63  if (!pc->frame_start_found)
64  pc->frame_start_found = 1;
65  else {
66  pc->frame_start_found = 0;
67  return i - 3;
68  }
69  }
70  }
71 
72  return END_NOT_FOUND;
73 }
74 
76  const H2645NAL *nal)
77 {
78  GetByteContext gbc;
79  bytestream2_init(&gbc, nal->data, nal->size);
80  bytestream2_skip(&gbc, 2);
81 
82  while (bytestream2_get_bytes_left(&gbc) > 1) {
83  GetBitContext gb;
84  uint64_t payload_size;
85  int payload_size_type, payload_type;
86  int block_size;
87 
88  int ret = init_get_bits8(&gb, gbc.buffer, bytestream2_get_bytes_left(&gbc));
89  if (ret < 0)
90  return ret;
91 
92  payload_size_type = get_bits(&gb, 3);
93  payload_type = get_bits(&gb, 5);
94  payload_size = payload_size_type;
95  if (payload_size_type == 6)
96  return AVERROR_PATCHWELCOME;
97  if (payload_size_type == 7)
98  payload_size = get_mb(&gb);
99 
100  if (payload_size > INT_MAX - (get_bits_count(&gb) >> 3))
101  return AVERROR_INVALIDDATA;
102 
103  block_size = payload_size + (get_bits_count(&gb) >> 3);
104  if (block_size >= bytestream2_get_bytes_left(&gbc))
105  return AVERROR_INVALIDDATA;
106 
107  switch (payload_type) {
109  avctx->profile = get_bits(&gb, 4);
110  avctx->level = get_bits(&gb, 4);
111  break;
113  int resolution_type, chroma_format_idc, bit_depth;
114  int processed_planes_type_flag;
115 
116  processed_planes_type_flag = get_bits1(&gb);
117  resolution_type = get_bits(&gb, 6);
118  skip_bits1(&gb);
119  chroma_format_idc = get_bits(&gb, 2);
120  skip_bits(&gb, 2);
121  bit_depth = get_bits(&gb, 2); // enhancement_depth_type
122 
123  s->format = ff_lcevc_depth_type[bit_depth][chroma_format_idc];
124 
125  if (resolution_type < 63) {
126  s->width = ff_lcevc_resolution_type[resolution_type].width;
127  s->height = ff_lcevc_resolution_type[resolution_type].height;
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  s->width = get_bits(&gb, 16);
154  s->height = get_bits(&gb, 16);
155  }
156  break;
157  }
158  default:
159  break;
160  }
161 
162  bytestream2_skip(&gbc, block_size);
163  }
164 
165  return 0;
166 }
167 
168 static int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf,
169  int buf_size, AVCodecContext *avctx)
170 {
171  LCEVCParserContext *ctx = s->priv_data;
172  int flags = (H2645_FLAG_IS_NALFF * !!ctx->is_lvcc) | H2645_FLAG_SMALL_PADDING;
173  int ret, i;
174 
175  /* set some sane default values */
176  s->pict_type = AV_PICTURE_TYPE_NONE;
177  s->key_frame = 0;
178  s->picture_structure = AV_PICTURE_STRUCTURE_UNKNOWN;
179 
180  ret = ff_h2645_packet_split(&ctx->pkt, buf, buf_size, avctx,
181  ctx->nal_length_size, AV_CODEC_ID_LCEVC, flags);
182  if (ret < 0)
183  return ret;
184 
185  for (i = 0; i < ctx->pkt.nb_nals; i++) {
186  H2645NAL *nal = &ctx->pkt.nals[i];
187 
188  switch (nal->type) {
189  case LCEVC_IDR_NUT:
190  s->key_frame = 1;
191  // fall-through
192  case LCEVC_NON_IDR_NUT:
193  parse_nal_unit(s, avctx, nal);
194  break;
195  default:
196  break;
197  }
198  }
199 
200  return 0;
201 }
202 
204  AVCodecContext *avctx,
205  const uint8_t **poutbuf, int *poutbuf_size,
206  const uint8_t *buf, int buf_size)
207 {
208  LCEVCParserContext *ctx = s->priv_data;
209  ParseContext *pc = &ctx->pc;
210  int next;
211 
212  if (!ctx->parsed_extradata && avctx->extradata_size > 4) {
213  ctx->parsed_extradata = 1;
214  ctx->is_lvcc = !!avctx->extradata[0];
215 
216  if (ctx->is_lvcc)
217  ctx->nal_length_size = (avctx->extradata[4] >> 6) + 1;
218  }
219 
220  if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
221  next = buf_size;
222  } else {
223  next = lcevc_find_frame_end(s, buf, buf_size);
224  if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
225  *poutbuf = NULL;
226  *poutbuf_size = 0;
227  return buf_size;
228  }
229  }
230 
231  parse_nal_units(s, buf, buf_size, avctx);
232 
233  *poutbuf = buf;
234  *poutbuf_size = buf_size;
235  return next;
236 }
237 
239 {
240  LCEVCParserContext *ctx = s->priv_data;
241 
243 
244  av_freep(&ctx->pc.buffer);
245 }
246 
249  .priv_data_size = sizeof(LCEVCParserContext),
250  .parse = lcevc_parse,
252 };
flags
const SwsFlags flags[]
Definition: swscale.c:72
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
GetByteContext
Definition: bytestream.h:33
AV_PICTURE_STRUCTURE_UNKNOWN
@ AV_PICTURE_STRUCTURE_UNKNOWN
unknown
Definition: avcodec.h:2587
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
parse_nal_unit
static int parse_nal_unit(AVCodecParserContext *s, AVCodecContext *avctx, const H2645NAL *nal)
Definition: lcevc_parser.c:75
get_bits_count
static int get_bits_count(const GetBitContext *s)
Definition: get_bits.h:254
parser_internal.h
lcevc_parse.h
ff_lcevc_resolution_type
const struct FFLCEVCDim ff_lcevc_resolution_type[63]
Definition: lcevctab.c:22
LCEVCParserContext
Definition: lcevc_parser.c:35
bit_depth
static void bit_depth(AudioStatsContext *s, const uint64_t *const mask, uint8_t *depth)
Definition: af_astats.c:246
ParseContext::state
uint32_t state
contains the last few bytes in MSB order
Definition: parser.h:33
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
close
static av_cold void close(AVCodecParserContext *s)
Definition: apv_parser.c:197
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
ParseContext
Definition: parser.h:28
GetBitContext
Definition: get_bits.h:109
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
LCEVCParserContext::pkt
H2645Packet pkt
Definition: lcevc_parser.c:38
init_get_bits8
static int init_get_bits8(GetBitContext *s, const uint8_t *buffer, int byte_size)
Initialize GetBitContext.
Definition: get_bits.h:544
AVCodecContext::extradata_size
int extradata_size
Definition: avcodec.h:523
s
#define s(width, name)
Definition: cbs_vp9.c:198
GetByteContext::buffer
const uint8_t * buffer
Definition: bytestream.h:34
LCEVCParserContext::is_lvcc
int is_lvcc
Definition: lcevc_parser.c:41
ctx
static AVFormatContext * ctx
Definition: movenc.c:49
get_bits.h
ff_lcevc_depth_type
enum AVPixelFormat ff_lcevc_depth_type[4][4]
Definition: lcevctab.c:38
parse_nal_units
static int parse_nal_units(AVCodecParserContext *s, const uint8_t *buf, int buf_size, AVCodecContext *avctx)
Definition: lcevc_parser.c:168
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
ParseContext::frame_start_found
int frame_start_found
Definition: parser.h:34
parse
static int parse(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size)
Definition: apv_parser.c:92
AVCodecContext::level
int level
Encoding level descriptor.
Definition: avcodec.h:1640
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
H2645NAL
Definition: h2645_parse.h:34
AV_PICTURE_TYPE_NONE
@ AV_PICTURE_TYPE_NONE
Undefined.
Definition: avutil.h:277
START_CODE
#define START_CODE
start_code_prefix_one_3bytes
Definition: lcevc_parser.c:33
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
FFLCEVCDim::height
uint16_t height
Definition: lcevctab.h:29
ff_combine_frame
int ff_combine_frame(ParseContext *pc, int next, const uint8_t **buf, int *buf_size)
Combine the (truncated) bitstream to a complete frame.
Definition: parser.c:217
FFCodecParser
Definition: parser_internal.h:29
H2645_FLAG_SMALL_PADDING
@ H2645_FLAG_SMALL_PADDING
Definition: h2645_parse.h:98
PARSER_FLAG_COMPLETE_FRAMES
#define PARSER_FLAG_COMPLETE_FRAMES
Definition: avcodec.h:2627
nal
static int FUNC() nal(CodedBitstreamContext *ctx, RWContext *rw, LCEVCRawNAL *current, int nal_unit_type)
Definition: cbs_lcevc_syntax_template.c:657
AVCodecContext::extradata
uint8_t * extradata
Out-of-band global headers that may be used by some codecs.
Definition: avcodec.h:522
lcevc_parse
static int lcevc_parse(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size)
Definition: lcevc_parser.c:203
ff_lcevc_parser
const FFCodecParser ff_lcevc_parser
Definition: lcevc_parser.c:247
LCEVCParserContext::nal_length_size
int nal_length_size
Definition: lcevc_parser.c:42
parser.h
PARSER_CODEC_LIST
#define PARSER_CODEC_LIST(...)
Definition: parser_internal.h:76
FFLCEVCDim::width
uint16_t width
Definition: lcevctab.h:28
avcodec.h
AVCodecParserContext
Definition: avcodec.h:2593
lcevc_find_frame_end
static int lcevc_find_frame_end(AVCodecParserContext *s, const uint8_t *buf, int buf_size)
Definition: lcevc_parser.c:45
ret
ret
Definition: filter_design.txt:187
lcevctab.h
lcevc_parser_close
static void lcevc_parser_close(AVCodecParserContext *s)
Definition: lcevc_parser.c:238
AVCodecContext
main external API structure.
Definition: avcodec.h:439
LCEVC_PAYLOAD_TYPE_SEQUENCE_CONFIG
@ LCEVC_PAYLOAD_TYPE_SEQUENCE_CONFIG
Definition: lcevc.h:70
AVCodecContext::profile
int profile
profile
Definition: avcodec.h:1630
mem.h
END_NOT_FOUND
#define END_NOT_FOUND
Definition: parser.h:40
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
LCEVC_PAYLOAD_TYPE_GLOBAL_CONFIG
@ LCEVC_PAYLOAD_TYPE_GLOBAL_CONFIG
Definition: lcevc.h:71
LCEVCParserContext::pc
ParseContext pc
Definition: lcevc_parser.c:36
bytestream.h
bytestream2_init
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:137
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
H2645_FLAG_IS_NALFF
@ H2645_FLAG_IS_NALFF
Definition: h2645_parse.h:97
LCEVC_IDR_NUT
@ LCEVC_IDR_NUT
Definition: lcevc.h:61
H2645Packet
Definition: h2645_parse.h:82
LCEVCParserContext::parsed_extradata
int parsed_extradata
Definition: lcevc_parser.c:40