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 "bsf.h"
28 #include "bsf_internal.h"
29 #include "bytestream.h"
30 #include "defs.h"
31 #include "hevc.h"
32 
33 #define MIN_HEVCC_LENGTH 23
34 
35 typedef struct HEVCBSFContext {
36  uint8_t length_size;
39 
41 {
42  GetByteContext gb;
43  int length_size, num_arrays, i, j;
44  int ret = 0;
45 
46  uint8_t *new_extradata = NULL;
47  size_t new_extradata_size = 0;
48 
49  bytestream2_init(&gb, ctx->par_in->extradata, ctx->par_in->extradata_size);
50 
51  bytestream2_skip(&gb, 21);
52  length_size = (bytestream2_get_byte(&gb) & 3) + 1;
53  num_arrays = bytestream2_get_byte(&gb);
54 
55  for (i = 0; i < num_arrays; i++) {
56  int type = bytestream2_get_byte(&gb) & 0x3f;
57  int cnt = bytestream2_get_be16(&gb);
58 
59  if (!(type == HEVC_NAL_VPS || type == HEVC_NAL_SPS || type == HEVC_NAL_PPS ||
61  av_log(ctx, AV_LOG_ERROR, "Invalid NAL unit type in extradata: %d\n",
62  type);
64  goto fail;
65  }
66 
67  for (j = 0; j < cnt; j++) {
68  const int nalu_len = bytestream2_get_be16(&gb);
69 
70  if (!nalu_len ||
71  nalu_len > bytestream2_get_bytes_left(&gb) ||
72  4 + AV_INPUT_BUFFER_PADDING_SIZE + nalu_len > SIZE_MAX - new_extradata_size) {
74  goto fail;
75  }
76  ret = av_reallocp(&new_extradata, new_extradata_size + nalu_len + 4 + AV_INPUT_BUFFER_PADDING_SIZE);
77  if (ret < 0)
78  goto fail;
79 
80  AV_WB32(new_extradata + new_extradata_size, 1); // add the startcode
81  bytestream2_get_buffer(&gb, new_extradata + new_extradata_size + 4, nalu_len);
82  new_extradata_size += 4 + nalu_len;
83  memset(new_extradata + new_extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
84  }
85  }
86 
87  av_freep(&ctx->par_out->extradata);
88  ctx->par_out->extradata = new_extradata;
89  ctx->par_out->extradata_size = new_extradata_size;
90 
91  if (!new_extradata_size)
92  av_log(ctx, AV_LOG_WARNING, "No parameter sets in the extradata\n");
93 
94  return length_size;
95 fail:
96  av_freep(&new_extradata);
97  return ret;
98 }
99 
101 {
103  int ret;
104 
105  if (ctx->par_in->extradata_size < MIN_HEVCC_LENGTH ||
106  AV_RB24(ctx->par_in->extradata) == 1 ||
107  AV_RB32(ctx->par_in->extradata) == 1) {
109  "The input looks like it is Annex B already\n");
110  } else {
112  if (ret < 0)
113  return ret;
114  s->length_size = ret;
115  s->extradata_parsed = 1;
116  }
117 
118  return 0;
119 }
120 
122 {
124  AVPacket *in;
125  GetByteContext gb;
126 
127  int got_irap = 0;
128  int i, ret = 0;
129 
130  ret = ff_bsf_get_packet(ctx, &in);
131  if (ret < 0)
132  return ret;
133 
134  if (!s->extradata_parsed) {
135  av_packet_move_ref(out, in);
136  av_packet_free(&in);
137  return 0;
138  }
139 
140  bytestream2_init(&gb, in->data, in->size);
141 
142  while (bytestream2_get_bytes_left(&gb)) {
143  uint32_t nalu_size = 0;
144  int nalu_type;
145  int is_irap, add_extradata, extra_size, prev_size;
146 
147  if (bytestream2_get_bytes_left(&gb) < s->length_size) {
149  goto fail;
150  }
151  for (i = 0; i < s->length_size; i++)
152  nalu_size = (nalu_size << 8) | bytestream2_get_byte(&gb);
153 
154  if (nalu_size < 2 || nalu_size > bytestream2_get_bytes_left(&gb)) {
156  goto fail;
157  }
158 
159  nalu_type = (bytestream2_peek_byte(&gb) >> 1) & 0x3f;
160 
161  /* prepend extradata to IRAP frames */
162  is_irap = nalu_type >= HEVC_NAL_BLA_W_LP &&
163  nalu_type <= HEVC_NAL_RSV_IRAP_VCL23;
164  add_extradata = is_irap && !got_irap;
165  extra_size = add_extradata * ctx->par_out->extradata_size;
166  got_irap |= is_irap;
167 
168  if (FFMIN(INT_MAX, SIZE_MAX) < 4ULL + nalu_size + extra_size) {
170  goto fail;
171  }
172 
173  prev_size = out->size;
174 
175  ret = av_grow_packet(out, 4 + nalu_size + extra_size);
176  if (ret < 0)
177  goto fail;
178 
179  if (extra_size)
180  memcpy(out->data + prev_size, ctx->par_out->extradata, extra_size);
181  AV_WB32(out->data + prev_size + extra_size, 1);
182  bytestream2_get_buffer(&gb, out->data + prev_size + 4 + extra_size, nalu_size);
183  }
184 
186  if (ret < 0)
187  goto fail;
188 
189 fail:
190  if (ret < 0)
192  av_packet_free(&in);
193 
194  return ret;
195 }
196 
197 static const enum AVCodecID codec_ids[] = {
199 };
200 
202  .p.name = "hevc_mp4toannexb",
203  .p.codec_ids = codec_ids,
204  .priv_data_size = sizeof(HEVCBSFContext),
207 };
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: packet.c:427
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
bsf_internal.h
out
FILE * out
Definition: movenc.c:55
GetByteContext
Definition: bytestream.h:33
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:524
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
HEVCBSFContext::length_size
uint8_t length_size
Definition: hevc_mp4toannexb.c:36
filter
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
Definition: filter_design.txt:228
ff_hevc_mp4toannexb_bsf
const FFBitStreamFilter ff_hevc_mp4toannexb_bsf
Definition: hevc_mp4toannexb.c:201
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:235
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
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:100
bsf.h
hevc_mp4toannexb_filter
static int hevc_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out)
Definition: hevc_mp4toannexb.c:121
fail
#define fail()
Definition: checkasm.h:179
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
HEVCBSFContext
Definition: hevc_mp4toannexb.c:35
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
intreadwrite.h
s
#define s(width, name)
Definition: cbs_vp9.c:198
ctx
AVFormatContext * ctx
Definition: movenc.c:49
NULL
#define NULL
Definition: coverity.c:32
FFBitStreamFilter
Definition: bsf_internal.h:27
HEVC_NAL_PPS
@ HEVC_NAL_PPS
Definition: hevc.h:63
HEVC_NAL_SEI_SUFFIX
@ HEVC_NAL_SEI_SUFFIX
Definition: hevc.h:69
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:484
bytestream2_get_bytes_left
static av_always_inline int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:158
AVCodecID
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: codec_id.h:49
AV_WB32
#define AV_WB32(p, v)
Definition: intreadwrite.h:417
FFBitStreamFilter::p
AVBitStreamFilter p
The public AVBitStreamFilter.
Definition: bsf_internal.h:31
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:366
AVPacket::size
int size
Definition: packet.h:525
HEVC_NAL_BLA_W_LP
@ HEVC_NAL_BLA_W_LP
Definition: hevc.h:45
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
codec_ids
static enum AVCodecID codec_ids[]
Definition: hevc_mp4toannexb.c:197
HEVC_NAL_RSV_IRAP_VCL23
@ HEVC_NAL_RSV_IRAP_VCL23
Definition: hevc.h:52
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:390
AV_CODEC_ID_NONE
@ AV_CODEC_ID_NONE
Definition: codec_id.h:50
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
AV_CODEC_ID_HEVC
@ AV_CODEC_ID_HEVC
Definition: codec_id.h:226
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
MIN_HEVCC_LENGTH
#define MIN_HEVCC_LENGTH
Definition: hevc_mp4toannexb.c:33
HEVC_NAL_VPS
@ HEVC_NAL_VPS
Definition: hevc.h:61
ret
ret
Definition: filter_design.txt:187
AV_INPUT_BUFFER_PADDING_SIZE
#define AV_INPUT_BUFFER_PADDING_SIZE
Definition: defs.h:40
defs.h
HEVC_NAL_SPS
@ HEVC_NAL_SPS
Definition: hevc.h:62
mem.h
AVPacket
This structure stores compressed data.
Definition: packet.h:501
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h: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
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
hevc_extradata_to_annexb
static int hevc_extradata_to_annexb(AVBSFContext *ctx)
Definition: hevc_mp4toannexb.c:40
HEVC_NAL_SEI_PREFIX
@ HEVC_NAL_SEI_PREFIX
Definition: hevc.h:68
HEVCBSFContext::extradata_parsed
int extradata_parsed
Definition: hevc_mp4toannexb.c:37
AVFormatContext::priv_data
void * priv_data
Format private data.
Definition: avformat.h:1283