FFmpeg
hevc_mp4toannexb.c
Go to the documentation of this file.
1 /*
2  * HEVC MP4 to Annex B byte stream format filter
3  * copyright (c) 2015 Anton Khirnov
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include <string.h>
23 
24 #include "libavutil/intreadwrite.h"
25 #include "libavutil/mem.h"
26 
27 #include "libavcodec/bsf.h"
29 #include "libavcodec/bytestream.h"
30 #include "libavcodec/defs.h"
31 
32 #include "libavcodec/hevc/hevc.h"
33 
34 #define MIN_HEVCC_LENGTH 23
35 
36 typedef struct HEVCBSFContext {
37  uint8_t *extradata;
39  uint8_t length_size;
42 
44  const uint8_t *extradata, int extradata_size,
45  uint8_t **out_extradata, int *out_extradata_size)
46 {
48  GetByteContext gb;
49  int length_size, num_arrays, i, j;
50  int ret = 0;
51 
52  uint8_t *new_extradata = NULL;
53  size_t new_extradata_size = 0;
54 
55  bytestream2_init(&gb, extradata, extradata_size);
56 
57  bytestream2_skip(&gb, 21);
58  length_size = (bytestream2_get_byte(&gb) & 3) + 1;
59  num_arrays = bytestream2_get_byte(&gb);
60 
61  for (i = 0; i < num_arrays; i++) {
62  int type = bytestream2_get_byte(&gb) & 0x3f;
63  int cnt = bytestream2_get_be16(&gb);
64 
65  if (!(type == HEVC_NAL_VPS || type == HEVC_NAL_SPS || type == HEVC_NAL_PPS ||
67  av_log(ctx, AV_LOG_ERROR, "Invalid NAL unit type in extradata: %d\n",
68  type);
70  goto fail;
71  }
72 
73  for (j = 0; j < cnt; j++) {
74  const int nalu_len = bytestream2_get_be16(&gb);
75 
76  if (!nalu_len ||
77  nalu_len > bytestream2_get_bytes_left(&gb) ||
78  4 + AV_INPUT_BUFFER_PADDING_SIZE + nalu_len > SIZE_MAX - new_extradata_size) {
80  goto fail;
81  }
82  ret = av_reallocp(&new_extradata, new_extradata_size + nalu_len + 4 + AV_INPUT_BUFFER_PADDING_SIZE);
83  if (ret < 0)
84  goto fail;
85 
86  AV_WB32(new_extradata + new_extradata_size, 1); // add the startcode
87  bytestream2_get_buffer(&gb, new_extradata + new_extradata_size + 4, nalu_len);
88  new_extradata_size += 4 + nalu_len;
89  memset(new_extradata + new_extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
90  }
91  }
92 
93  if (!new_extradata_size)
94  av_log(ctx, AV_LOG_WARNING, "No parameter sets in the extradata\n");
95 
96  if (out_extradata && out_extradata_size) {
97  av_freep(out_extradata);
98  *out_extradata =
99  av_malloc(new_extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
100  if (!(*out_extradata)) {
101  ret = AVERROR(ENOMEM);
102  goto fail;
103  }
104  *out_extradata_size = new_extradata_size;
105  memcpy(*out_extradata, new_extradata, new_extradata_size);
106  memset(*out_extradata + new_extradata_size, 0,
108  }
109 
110  av_freep(&s->extradata);
111  s->extradata = new_extradata;
112  s->extradata_size = new_extradata_size;
113 
114  s->length_size = length_size;
115  s->extradata_parsed = 1;
116  return 0;
117 fail:
118  av_freep(&new_extradata);
119  return ret;
120 }
121 
123 {
124  int ret;
125 
126  if (ctx->par_in->extradata_size < MIN_HEVCC_LENGTH ||
127  AV_RB24(ctx->par_in->extradata) == 1 ||
128  AV_RB32(ctx->par_in->extradata) == 1) {
130  "The input looks like it is Annex B already\n");
131  } else {
133  ctx->par_in->extradata,
134  ctx->par_in->extradata_size,
135  &ctx->par_out->extradata,
136  &ctx->par_out->extradata_size);
137  if (ret < 0)
138  return ret;
139  }
140 
141  return 0;
142 }
143 
145 {
147  AVPacket *in;
148  GetByteContext gb;
149 
150  int got_irap = 0;
151  int got_ps = 0, seen_irap_ps = 0;
152  int i, ret = 0;
153  size_t extradata_size = 0;
154  uint8_t *extradata = NULL;
155 
156  ret = ff_bsf_get_packet(ctx, &in);
157  if (ret < 0)
158  return ret;
159 
160  extradata =
162  if (extradata && extradata_size >= MIN_HEVCC_LENGTH &&
163  ((extradata[0] == 1) ||
164  (extradata[0] == 0 && (extradata[1] || extradata[2] > 1)))) {
165  ret = hevc_extradata_to_annexb(ctx, extradata, extradata_size,
166  NULL, NULL);
167  if (ret < 0)
168  goto fail;
171  }
172 
173  if (!s->extradata_parsed) {
174  av_packet_move_ref(out, in);
175  av_packet_free(&in);
176  return 0;
177  }
178 
179  bytestream2_init(&gb, in->data, in->size);
180 
181  while (!got_irap && bytestream2_get_bytes_left(&gb)) {
182  uint32_t nalu_size = 0;
183  int nalu_type;
184 
185  if (bytestream2_get_bytes_left(&gb) < s->length_size) {
187  goto fail;
188  }
189  for (i = 0; i < s->length_size; i++)
190  nalu_size = (nalu_size << 8) | bytestream2_get_byte(&gb);
191 
192  if (nalu_size < 2 || nalu_size > bytestream2_get_bytes_left(&gb)) {
194  goto fail;
195  }
196 
197  nalu_type = (bytestream2_peek_byte(&gb) >> 1) & 0x3f;
198  bytestream2_skip(&gb, nalu_size);
199  got_irap |= nalu_type >= HEVC_NAL_BLA_W_LP &&
200  nalu_type <= HEVC_NAL_RSV_IRAP_VCL23;
201  got_ps |= nalu_type >= HEVC_NAL_VPS && nalu_type <= HEVC_NAL_PPS;
202  }
203  seen_irap_ps = got_irap && got_ps;
204  got_irap = got_ps = 0;
205 
206  bytestream2_init(&gb, in->data, in->size);
207 
208  while (bytestream2_get_bytes_left(&gb)) {
209  uint32_t nalu_size = 0;
210  int nalu_type;
211  int is_irap, is_ps, add_extradata, extra_size, prev_size;
212 
213  if (bytestream2_get_bytes_left(&gb) < s->length_size) {
215  goto fail;
216  }
217  for (i = 0; i < s->length_size; i++)
218  nalu_size = (nalu_size << 8) | bytestream2_get_byte(&gb);
219 
220  if (nalu_size < 2 || nalu_size > bytestream2_get_bytes_left(&gb)) {
222  goto fail;
223  }
224 
225  nalu_type = (bytestream2_peek_byte(&gb) >> 1) & 0x3f;
226 
227  /* prepend extradata to IRAP frames */
228  is_irap = nalu_type >= HEVC_NAL_BLA_W_LP &&
229  nalu_type <= HEVC_NAL_RSV_IRAP_VCL23;
230  is_ps = nalu_type >= HEVC_NAL_VPS && nalu_type <= HEVC_NAL_PPS && seen_irap_ps;
231  add_extradata = (is_ps || is_irap) && !got_ps && !got_irap;
232  extra_size = add_extradata * s->extradata_size;
233  got_irap |= is_irap;
234  got_ps |= is_ps;
235 
236  if (FFMIN(INT_MAX, SIZE_MAX) < 4ULL + nalu_size + extra_size) {
238  goto fail;
239  }
240 
241  prev_size = out->size;
242 
243  ret = av_grow_packet(out, 4 + nalu_size + extra_size);
244  if (ret < 0)
245  goto fail;
246 
247  if (extra_size)
248  memcpy(out->data + prev_size, s->extradata, extra_size);
249  AV_WB32(out->data + prev_size + extra_size, 1);
250  bytestream2_get_buffer(&gb, out->data + prev_size + 4 + extra_size, nalu_size);
251  }
252 
254  if (ret < 0)
255  goto fail;
256 
257 fail:
258  if (ret < 0)
260  av_packet_free(&in);
261 
262  return ret;
263 }
264 
266 {
268  av_freep(&s->extradata);
269 }
270 
271 static const enum AVCodecID codec_ids[] = {
273 };
274 
276  .p.name = "hevc_mp4toannexb",
277  .p.codec_ids = codec_ids,
278  .priv_data_size = sizeof(HEVCBSFContext),
282 };
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: packet.c:434
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:216
hevc_extradata_to_annexb
static int hevc_extradata_to_annexb(AVBSFContext *ctx, const uint8_t *extradata, int extradata_size, uint8_t **out_extradata, int *out_extradata_size)
Definition: hevc_mp4toannexb.c:43
AVERROR
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
bsf_internal.h
bytestream2_get_bytes_left
static av_always_inline int bytestream2_get_bytes_left(const GetByteContext *g)
Definition: bytestream.h:158
hevc_mp4toannexb_close
static void hevc_mp4toannexb_close(AVBSFContext *ctx)
Definition: hevc_mp4toannexb.c:265
out
static FILE * out
Definition: movenc.c:55
GetByteContext
Definition: bytestream.h:33
AV_PKT_DATA_NEW_EXTRADATA
@ AV_PKT_DATA_NEW_EXTRADATA
The AV_PKT_DATA_NEW_EXTRADATA is used to notify the codec or the format that the extradata buffer was...
Definition: packet.h:56
AVBitStreamFilter::name
const char * name
Definition: bsf.h:112
av_grow_packet
int av_grow_packet(AVPacket *pkt, int grow_by)
Increase packet size, correctly zeroing padding.
Definition: packet.c:121
AVPacket::data
uint8_t * data
Definition: packet.h:603
av_packet_side_data_remove
void av_packet_side_data_remove(AVPacketSideData *sd, int *pnb_sd, enum AVPacketSideDataType type)
Remove side data of the given type from a side data array.
Definition: packet.c:642
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:226
HEVCBSFContext::length_size
uint8_t length_size
Definition: hevc_mp4toannexb.c:39
ff_hevc_mp4toannexb_bsf
const FFBitStreamFilter ff_hevc_mp4toannexb_bsf
Definition: hevc_mp4toannexb.c:275
ff_bsf_get_packet
int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt)
Called by the bitstream filters to get the next packet for filtering.
Definition: bsf.c:233
av_packet_free
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition: packet.c:74
AVBSFContext
The bitstream filter state.
Definition: bsf.h:68
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
hevc_mp4toannexb_init
static int hevc_mp4toannexb_init(AVBSFContext *ctx)
Definition: hevc_mp4toannexb.c:122
bsf.h
hevc_mp4toannexb_filter
static int hevc_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out)
Definition: hevc_mp4toannexb.c:144
HEVC_NAL_SEI_SUFFIX
@ HEVC_NAL_SEI_SUFFIX
Definition: hevc.h:69
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
HEVC_NAL_SEI_PREFIX
@ HEVC_NAL_SEI_PREFIX
Definition: hevc.h:68
HEVCBSFContext::extradata_size
size_t extradata_size
Definition: hevc_mp4toannexb.c:38
HEVCBSFContext
Definition: hevc_mp4toannexb.c:36
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
intreadwrite.h
HEVC_NAL_VPS
@ HEVC_NAL_VPS
Definition: hevc.h:61
ctx
static AVFormatContext * ctx
Definition: movenc.c:49
hevc.h
fail
#define fail
Definition: test.h:479
NULL
#define NULL
Definition: coverity.c:32
FFBitStreamFilter
Definition: bsf_internal.h:29
bytestream2_get_buffer
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:267
av_packet_move_ref
void av_packet_move_ref(AVPacket *dst, AVPacket *src)
Move every field in src to dst and reset src.
Definition: packet.c:491
AVCodecID
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: codec_id.h:47
AV_WB32
#define AV_WB32(p, v)
Definition: intreadwrite.h:415
HEVC_NAL_RSV_IRAP_VCL23
@ HEVC_NAL_RSV_IRAP_VCL23
Definition: hevc.h:52
FFBitStreamFilter::p
AVBitStreamFilter p
The public AVBitStreamFilter.
Definition: bsf_internal.h:33
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:608
AVPacket::size
int size
Definition: packet.h:604
filter
void(* filter)(uint8_t *src, ptrdiff_t stride, int qscale)
Definition: h263dsp.c:29
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
HEVC_NAL_SPS
@ HEVC_NAL_SPS
Definition: hevc.h:62
av_reallocp
int av_reallocp(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory through a pointer to a pointer.
Definition: mem.c:188
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
av_malloc
#define av_malloc(s)
Definition: ops_static.c:52
HEVC_NAL_PPS
@ HEVC_NAL_PPS
Definition: hevc.h:63
codec_ids
static enum AVCodecID codec_ids[]
Definition: hevc_mp4toannexb.c:271
av_packet_copy_props
int av_packet_copy_props(AVPacket *dst, const AVPacket *src)
Copy only "properties" fields from src to dst.
Definition: packet.c:397
AV_CODEC_ID_NONE
@ AV_CODEC_ID_NONE
Definition: codec_id.h:48
av_packet_get_side_data
uint8_t * av_packet_get_side_data(const AVPacket *pkt, enum AVPacketSideDataType type, size_t *size)
Get side information from packet.
Definition: packet.c:252
s
uint8_t s
Definition: llvidencdsp.c:39
AV_CODEC_ID_HEVC
@ AV_CODEC_ID_HEVC
Definition: codec_id.h:223
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
MIN_HEVCC_LENGTH
#define MIN_HEVCC_LENGTH
Definition: hevc_mp4toannexb.c:34
ret
ret
Definition: filter_design.txt:187
AVPacket::side_data
AVPacketSideData * side_data
Additional packet data that can be provided by the container.
Definition: packet.h:614
AV_INPUT_BUFFER_PADDING_SIZE
#define AV_INPUT_BUFFER_PADDING_SIZE
Definition: defs.h:40
defs.h
mem.h
HEVCBSFContext::extradata
uint8_t * extradata
Definition: hevc_mp4toannexb.c:37
AVPacket
This structure stores compressed data.
Definition: packet.h:580
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
bytestream.h
bytestream2_init
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:137
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
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
HEVCBSFContext::extradata_parsed
int extradata_parsed
Definition: hevc_mp4toannexb.c:40
AVFormatContext::priv_data
void * priv_data
Format private data.
Definition: avformat.h:1361
AVPacket::side_data_elems
int side_data_elems
Definition: packet.h:615
HEVC_NAL_BLA_W_LP
@ HEVC_NAL_BLA_W_LP
Definition: hevc.h:45