FFmpeg
extract_extradata_bsf.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/common.h"
22 #include "libavutil/intreadwrite.h"
23 #include "libavutil/log.h"
24 #include "libavutil/opt.h"
25 
26 #include "avcodec.h"
27 #include "av1.h"
28 #include "av1_parse.h"
29 #include "bsf.h"
30 #include "bytestream.h"
31 #include "h2645_parse.h"
32 #include "h264.h"
33 #include "hevc.h"
34 #include "vc1_common.h"
35 
36 typedef struct ExtractExtradataContext {
37  const AVClass *class;
38 
40  uint8_t **data, int *size);
41 
42  /* AV1 specific fields */
44 
45  /* H264/HEVC specific fields */
47 
48  /* AVOptions */
49  int remove;
51 
52 static int val_in_array(const int *arr, int len, int val)
53 {
54  int i;
55  for (i = 0; i < len; i++)
56  if (arr[i] == val)
57  return 1;
58  return 0;
59 }
60 
62  uint8_t **data, int *size)
63 {
64  static const int extradata_obu_types[] = {
66  };
68 
69  int extradata_size = 0, filtered_size = 0;
70  int nb_extradata_obu_types = FF_ARRAY_ELEMS(extradata_obu_types);
71  int i, has_seq = 0, ret = 0;
72 
73  ret = ff_av1_packet_split(&s->av1_pkt, pkt->data, pkt->size, ctx);
74  if (ret < 0)
75  return ret;
76 
77  for (i = 0; i < s->av1_pkt.nb_obus; i++) {
78  AV1OBU *obu = &s->av1_pkt.obus[i];
79  if (val_in_array(extradata_obu_types, nb_extradata_obu_types, obu->type)) {
80  extradata_size += obu->raw_size;
81  if (obu->type == AV1_OBU_SEQUENCE_HEADER)
82  has_seq = 1;
83  } else if (s->remove) {
84  filtered_size += obu->raw_size;
85  }
86  }
87 
88  if (extradata_size && has_seq) {
89  AVBufferRef *filtered_buf = NULL;
90  PutByteContext pb_filtered_data, pb_extradata;
91  uint8_t *extradata;
92 
93  if (s->remove) {
94  filtered_buf = av_buffer_alloc(filtered_size + AV_INPUT_BUFFER_PADDING_SIZE);
95  if (!filtered_buf) {
96  return AVERROR(ENOMEM);
97  }
98  memset(filtered_buf->data + filtered_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
99  }
100 
101  extradata = av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
102  if (!extradata) {
103  av_buffer_unref(&filtered_buf);
104  return AVERROR(ENOMEM);
105  }
106  memset(extradata + extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
107 
108  *data = extradata;
109  *size = extradata_size;
110 
111  bytestream2_init_writer(&pb_extradata, extradata, extradata_size);
112  if (s->remove)
113  bytestream2_init_writer(&pb_filtered_data, filtered_buf->data, filtered_size);
114 
115  for (i = 0; i < s->av1_pkt.nb_obus; i++) {
116  AV1OBU *obu = &s->av1_pkt.obus[i];
117  if (val_in_array(extradata_obu_types, nb_extradata_obu_types,
118  obu->type)) {
119  bytestream2_put_bufferu(&pb_extradata, obu->raw_data, obu->raw_size);
120  } else if (s->remove) {
121  bytestream2_put_bufferu(&pb_filtered_data, obu->raw_data, obu->raw_size);
122  }
123  }
124 
125  if (s->remove) {
126  av_buffer_unref(&pkt->buf);
127  pkt->buf = filtered_buf;
128  pkt->data = filtered_buf->data;
129  pkt->size = filtered_size;
130  }
131  }
132 
133  return 0;
134 }
135 
137  uint8_t **data, int *size)
138 {
139  static const int extradata_nal_types_hevc[] = {
141  };
142  static const int extradata_nal_types_h264[] = {
144  };
145 
147 
148  int extradata_size = 0, filtered_size = 0;
149  const int *extradata_nal_types;
150  int nb_extradata_nal_types;
151  int i, has_sps = 0, has_vps = 0, ret = 0;
152 
153  if (ctx->par_in->codec_id == AV_CODEC_ID_HEVC) {
154  extradata_nal_types = extradata_nal_types_hevc;
155  nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types_hevc);
156  } else {
157  extradata_nal_types = extradata_nal_types_h264;
158  nb_extradata_nal_types = FF_ARRAY_ELEMS(extradata_nal_types_h264);
159  }
160 
161  ret = ff_h2645_packet_split(&s->h2645_pkt, pkt->data, pkt->size,
162  ctx, 0, 0, ctx->par_in->codec_id, 1, 0);
163  if (ret < 0)
164  return ret;
165 
166  for (i = 0; i < s->h2645_pkt.nb_nals; i++) {
167  H2645NAL *nal = &s->h2645_pkt.nals[i];
168  if (val_in_array(extradata_nal_types, nb_extradata_nal_types, nal->type)) {
169  extradata_size += nal->raw_size + 3;
170  if (ctx->par_in->codec_id == AV_CODEC_ID_HEVC) {
171  if (nal->type == HEVC_NAL_SPS) has_sps = 1;
172  if (nal->type == HEVC_NAL_VPS) has_vps = 1;
173  } else {
174  if (nal->type == H264_NAL_SPS) has_sps = 1;
175  }
176  } else if (s->remove) {
177  filtered_size += nal->raw_size + 3;
178  }
179  }
180 
181  if (extradata_size &&
182  ((ctx->par_in->codec_id == AV_CODEC_ID_HEVC && has_sps && has_vps) ||
183  (ctx->par_in->codec_id == AV_CODEC_ID_H264 && has_sps))) {
184  AVBufferRef *filtered_buf = NULL;
185  PutByteContext pb_filtered_data, pb_extradata;
186  uint8_t *extradata;
187 
188  if (s->remove) {
189  filtered_buf = av_buffer_alloc(filtered_size + AV_INPUT_BUFFER_PADDING_SIZE);
190  if (!filtered_buf) {
191  return AVERROR(ENOMEM);
192  }
193  memset(filtered_buf->data + filtered_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
194  }
195 
196  extradata = av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
197  if (!extradata) {
198  av_buffer_unref(&filtered_buf);
199  return AVERROR(ENOMEM);
200  }
201  memset(extradata + extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
202 
203  *data = extradata;
204  *size = extradata_size;
205 
206  bytestream2_init_writer(&pb_extradata, extradata, extradata_size);
207  if (s->remove)
208  bytestream2_init_writer(&pb_filtered_data, filtered_buf->data, filtered_size);
209 
210  for (i = 0; i < s->h2645_pkt.nb_nals; i++) {
211  H2645NAL *nal = &s->h2645_pkt.nals[i];
212  if (val_in_array(extradata_nal_types, nb_extradata_nal_types,
213  nal->type)) {
214  bytestream2_put_be24u(&pb_extradata, 1); //startcode
215  bytestream2_put_bufferu(&pb_extradata, nal->raw_data, nal->raw_size);
216  } else if (s->remove) {
217  bytestream2_put_be24u(&pb_filtered_data, 1); // startcode
218  bytestream2_put_bufferu(&pb_filtered_data, nal->raw_data, nal->raw_size);
219  }
220  }
221 
222  if (s->remove) {
223  av_buffer_unref(&pkt->buf);
224  pkt->buf = filtered_buf;
225  pkt->data = filtered_buf->data;
226  pkt->size = filtered_size;
227  }
228  }
229 
230  return 0;
231 }
232 
234  uint8_t **data, int *size)
235 {
237  const uint8_t *ptr = pkt->data, *end = pkt->data + pkt->size;
238  uint32_t state = UINT32_MAX;
239  int has_extradata = 0, extradata_size = 0;
240 
241  while (ptr < end) {
242  ptr = avpriv_find_start_code(ptr, end, &state);
243  if (state == VC1_CODE_SEQHDR || state == VC1_CODE_ENTRYPOINT) {
244  has_extradata = 1;
245  } else if (has_extradata && IS_MARKER(state)) {
246  extradata_size = ptr - 4 - pkt->data;
247  break;
248  }
249  }
250 
251  if (extradata_size) {
252  *data = av_malloc(extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
253  if (!*data)
254  return AVERROR(ENOMEM);
255 
256  memcpy(*data, pkt->data, extradata_size);
257  memset(*data + extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
258  *size = extradata_size;
259 
260  if (s->remove) {
261  pkt->data += extradata_size;
262  pkt->size -= extradata_size;
263  }
264  }
265 
266  return 0;
267 }
268 
270  uint8_t **data, int *size)
271 {
273  uint32_t state = UINT32_MAX;
274  int i, found = 0;
275 
276  for (i = 0; i < pkt->size; i++) {
277  state = (state << 8) | pkt->data[i];
278  if (state == 0x1B3)
279  found = 1;
280  else if (found && state != 0x1B5 && state < 0x200 && state >= 0x100) {
281  if (i > 3) {
282  *size = i - 3;
283  *data = av_malloc(*size + AV_INPUT_BUFFER_PADDING_SIZE);
284  if (!*data)
285  return AVERROR(ENOMEM);
286 
287  memcpy(*data, pkt->data, *size);
288  memset(*data + *size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
289 
290  if (s->remove) {
291  pkt->data += *size;
292  pkt->size -= *size;
293  }
294  }
295  break;
296  }
297  }
298  return 0;
299 }
300 
302  uint8_t **data, int *size)
303 {
305  const uint8_t *ptr = pkt->data, *end = pkt->data + pkt->size;
306  uint32_t state = UINT32_MAX;
307 
308  while (ptr < end) {
309  ptr = avpriv_find_start_code(ptr, end, &state);
310  if (state == 0x1B3 || state == 0x1B6) {
311  if (ptr - pkt->data > 4) {
312  *size = ptr - 4 - pkt->data;
313  *data = av_malloc(*size + AV_INPUT_BUFFER_PADDING_SIZE);
314  if (!*data)
315  return AVERROR(ENOMEM);
316 
317  memcpy(*data, pkt->data, *size);
318  memset(*data + *size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
319 
320  if (s->remove) {
321  pkt->data += *size;
322  pkt->size -= *size;
323  }
324  }
325  break;
326  }
327  }
328  return 0;
329 }
330 
331 static const struct {
332  enum AVCodecID id;
334  uint8_t **data, int *size);
335 } extract_tab[] = {
338  { AV_CODEC_ID_CAVS, extract_extradata_mpeg4 },
340  { AV_CODEC_ID_HEVC, extract_extradata_h2645 },
342  { AV_CODEC_ID_MPEG2VIDEO, extract_extradata_mpeg12 },
343  { AV_CODEC_ID_MPEG4, extract_extradata_mpeg4 },
345 };
346 
348 {
350  int i;
351 
352  for (i = 0; i < FF_ARRAY_ELEMS(extract_tab); i++) {
353  if (extract_tab[i].id == ctx->par_in->codec_id) {
354  s->extract = extract_tab[i].extract;
355  break;
356  }
357  }
358  if (!s->extract)
359  return AVERROR_BUG;
360 
361  return 0;
362 }
363 
365 {
367  uint8_t *extradata = NULL;
368  int extradata_size;
369  int ret = 0;
370 
371  ret = ff_bsf_get_packet_ref(ctx, pkt);
372  if (ret < 0)
373  return ret;
374 
375  ret = s->extract(ctx, pkt, &extradata, &extradata_size);
376  if (ret < 0)
377  goto fail;
378 
379  if (extradata) {
381  extradata, extradata_size);
382  if (ret < 0) {
383  av_freep(&extradata);
384  goto fail;
385  }
386  }
387 
388  return 0;
389 
390 fail:
391  av_packet_unref(pkt);
392  return ret;
393 }
394 
396 {
400 }
401 
402 static const enum AVCodecID codec_ids[] = {
413 };
414 
415 #define OFFSET(x) offsetof(ExtractExtradataContext, x)
416 #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM)
417 static const AVOption options[] = {
418  { "remove", "remove the extradata from the bitstream", OFFSET(remove), AV_OPT_TYPE_INT,
419  { .i64 = 0 }, 0, 1, FLAGS },
420  { NULL },
421 };
422 
424  .class_name = "extract_extradata",
425  .item_name = av_default_item_name,
426  .option = options,
427  .version = LIBAVUTIL_VERSION_INT,
428 };
429 
431  .name = "extract_extradata",
432  .codec_ids = codec_ids,
433  .priv_data_size = sizeof(ExtractExtradataContext),
434  .priv_class = &extract_extradata_class,
437  .close = extract_extradata_close,
438 };
#define NULL
Definition: coverity.c:32
const char const char void * val
Definition: avisynth_c.h:863
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it...
Definition: buffer.c:125
int(* extract)(AVBSFContext *ctx, AVPacket *pkt, uint8_t **data, int *size)
AVOption.
Definition: opt.h:246
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
static int extract_extradata_filter(AVBSFContext *ctx, AVPacket *pkt)
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: avcodec.h:3970
The bitstream filter state.
Definition: avcodec.h:5776
int size
Definition: avcodec.h:1483
const uint8_t * raw_data
Definition: av1_parse.h:43
static av_always_inline void bytestream2_init_writer(PutByteContext *p, uint8_t *buf, int buf_size)
Definition: bytestream.h:143
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:191
static AVPacket pkt
void * priv_data
Opaque filter-specific private data.
Definition: avcodec.h:5797
static int extract_extradata_mpeg4(AVBSFContext *ctx, AVPacket *pkt, uint8_t **data, int *size)
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:72
static int extract_extradata_init(AVBSFContext *ctx)
uint8_t
#define av_malloc(s)
AVOptions.
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
static int val_in_array(const int *arr, int len, int val)
static void extract_extradata_close(AVBSFContext *ctx)
int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, void *logctx, int is_nalff, int nal_length_size, enum AVCodecID codec_id, int small_padding, int use_ref)
Split an input packet into NAL units.
Definition: h2645_parse.c:393
static const AVClass extract_extradata_class
void ff_h2645_packet_uninit(H2645Packet *pkt)
Free all the allocated memory in the packet.
Definition: h2645_parse.c:520
const char * name
Definition: avcodec.h:5826
static int extract_extradata_av1(AVBSFContext *ctx, AVPacket *pkt, uint8_t **data, int *size)
uint8_t * data
Definition: avcodec.h:1482
ptrdiff_t size
Definition: opengl_enc.c:100
static struct @321 state
const uint8_t * avpriv_find_start_code(const uint8_t *p, const uint8_t *end, uint32_t *state)
H.264 common definitions.
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: avcodec.h:215
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce then the filter should push the output frames on the output link immediately As an exception to the previous rule if the input frame is enough to produce several output frames then the filter needs output only at least one per link The additional frames can be left buffered in the filter
#define IS_MARKER(state)
Definition: dca_parser.c:51
AVBufferRef * buf
A reference to the reference-counted buffer where the packet data is stored.
Definition: avcodec.h:1465
#define fail()
Definition: checkasm.h:122
int raw_size
Definition: h2645_parse.h:44
AVFormatContext * ctx
Definition: movenc.c:48
const AVBitStreamFilter ff_extract_extradata_bsf
#define s(width, name)
Definition: cbs_vp9.c:257
int nb_obus
Definition: av1_parse.h:57
preferred ID for MPEG-1/2 video decoding
Definition: avcodec.h:220
int type
NAL unit type.
Definition: h2645_parse.h:52
AV1OBU * obus
Definition: av1_parse.h:56
#define FF_ARRAY_ELEMS(a)
if(ret)
#define OFFSET(x)
The AV_PKT_DATA_NEW_EXTRADATA is used to notify the codec or the format that the extradata buffer was...
Definition: avcodec.h:1204
Libavcodec external API header.
AVBufferRef * av_buffer_alloc(int size)
Allocate an AVBuffer of the given size using av_malloc().
Definition: buffer.c:67
int ff_av1_packet_split(AV1Packet *pkt, const uint8_t *buf, int length, void *logctx)
Split an input packet into OBUs.
Definition: av1_parse.c:56
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:599
uint8_t * data
The data buffer.
Definition: buffer.h:89
static int extract_extradata_h2645(AVBSFContext *ctx, AVPacket *pkt, uint8_t **data, int *size)
static av_always_inline unsigned int bytestream2_put_bufferu(PutByteContext *p, const uint8_t *src, unsigned int size)
Definition: bytestream.h:297
AV1 common definitions.
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:50
Describe the class of an AVClass context structure.
Definition: log.h:67
static const struct @79 extract_tab[]
int type
Definition: av1_parse.h:48
void ff_av1_packet_uninit(AV1Packet *pkt)
Free all the allocated memory in the packet.
Definition: av1_parse.c:106
int av_packet_add_side_data(AVPacket *pkt, enum AVPacketSideDataType type, uint8_t *data, size_t size)
Wrap an existing array as a packet side data.
Definition: avpacket.c:295
An input packet split into OBUs.
Definition: av1_parse.h:55
int raw_size
Size of entire OBU, including header.
Definition: av1_parse.h:42
A reference to a data buffer.
Definition: buffer.h:81
int
common internal and external API header
#define FLAGS
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
Definition: avcodec.h:795
const uint8_t * raw_data
Definition: h2645_parse.h:45
int len
H2645NAL * nals
Definition: h2645_parse.h:77
static int extract_extradata_vc1(AVBSFContext *ctx, AVPacket *pkt, uint8_t **data, int *size)
static int extract_extradata_mpeg12(AVBSFContext *ctx, AVPacket *pkt, uint8_t **data, int *size)
#define av_freep(p)
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
static enum AVCodecID codec_ids[]
enum AVCodecID id
This structure stores compressed data.
Definition: avcodec.h:1459
AVCodecParameters * par_in
Parameters of the input stream.
Definition: avcodec.h:5804
int ff_bsf_get_packet_ref(AVBSFContext *ctx, AVPacket *pkt)
Called by bitstream filters to get packet for filtering.
Definition: bsf.c:239
static const AVOption options[]