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