FFmpeg  4.0
hevc_mp4toannexb_bsf.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 "avcodec.h"
28 #include "bsf.h"
29 #include "bytestream.h"
30 #include "hevc.h"
31 
32 #define MIN_HEVCC_LENGTH 23
33 
34 typedef struct HEVCBSFContext {
38 
40 {
41  GetByteContext gb;
42  int length_size, num_arrays, i, j;
43  int ret = 0;
44 
45  uint8_t *new_extradata = NULL;
46  size_t new_extradata_size = 0;
47 
49 
50  bytestream2_skip(&gb, 21);
51  length_size = (bytestream2_get_byte(&gb) & 3) + 1;
52  num_arrays = bytestream2_get_byte(&gb);
53 
54  for (i = 0; i < num_arrays; i++) {
55  int type = bytestream2_get_byte(&gb) & 0x3f;
56  int cnt = bytestream2_get_be16(&gb);
57 
58  if (!(type == HEVC_NAL_VPS || type == HEVC_NAL_SPS || type == HEVC_NAL_PPS ||
59  type == HEVC_NAL_SEI_PREFIX || type == HEVC_NAL_SEI_SUFFIX)) {
60  av_log(ctx, AV_LOG_ERROR, "Invalid NAL unit type in extradata: %d\n",
61  type);
62  ret = AVERROR_INVALIDDATA;
63  goto fail;
64  }
65 
66  for (j = 0; j < cnt; j++) {
67  int nalu_len = bytestream2_get_be16(&gb);
68 
69  if (4 + AV_INPUT_BUFFER_PADDING_SIZE + nalu_len > SIZE_MAX - new_extradata_size) {
70  ret = AVERROR_INVALIDDATA;
71  goto fail;
72  }
73  ret = av_reallocp(&new_extradata, new_extradata_size + nalu_len + 4 + AV_INPUT_BUFFER_PADDING_SIZE);
74  if (ret < 0)
75  goto fail;
76 
77  AV_WB32(new_extradata + new_extradata_size, 1); // add the startcode
78  bytestream2_get_buffer(&gb, new_extradata + new_extradata_size + 4, nalu_len);
79  new_extradata_size += 4 + nalu_len;
80  memset(new_extradata + new_extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
81  }
82  }
83 
84  av_freep(&ctx->par_out->extradata);
85  ctx->par_out->extradata = new_extradata;
86  ctx->par_out->extradata_size = new_extradata_size;
87 
88  if (!new_extradata_size)
89  av_log(ctx, AV_LOG_WARNING, "No parameter sets in the extradata\n");
90 
91  return length_size;
92 fail:
93  av_freep(&new_extradata);
94  return ret;
95 }
96 
98 {
99  HEVCBSFContext *s = ctx->priv_data;
100  int ret;
101 
102  if (ctx->par_in->extradata_size < MIN_HEVCC_LENGTH ||
103  AV_RB24(ctx->par_in->extradata) == 1 ||
104  AV_RB32(ctx->par_in->extradata) == 1) {
105  av_log(ctx, AV_LOG_VERBOSE,
106  "The input looks like it is Annex B already\n");
107  } else {
108  ret = hevc_extradata_to_annexb(ctx);
109  if (ret < 0)
110  return ret;
111  s->length_size = ret;
112  s->extradata_parsed = 1;
113  }
114 
115  return 0;
116 }
117 
119 {
120  HEVCBSFContext *s = ctx->priv_data;
121  AVPacket *in;
122  GetByteContext gb;
123 
124  int got_irap = 0;
125  int i, ret = 0;
126 
127  ret = ff_bsf_get_packet(ctx, &in);
128  if (ret < 0)
129  return ret;
130 
131  if (!s->extradata_parsed) {
132  av_packet_move_ref(out, in);
133  av_packet_free(&in);
134  return 0;
135  }
136 
137  bytestream2_init(&gb, in->data, in->size);
138 
139  while (bytestream2_get_bytes_left(&gb)) {
140  uint32_t nalu_size = 0;
141  int nalu_type;
142  int is_irap, add_extradata, extra_size, prev_size;
143 
144  for (i = 0; i < s->length_size; i++)
145  nalu_size = (nalu_size << 8) | bytestream2_get_byte(&gb);
146 
147  nalu_type = (bytestream2_peek_byte(&gb) >> 1) & 0x3f;
148 
149  /* prepend extradata to IRAP frames */
150  is_irap = nalu_type >= 16 && nalu_type <= 23;
151  add_extradata = is_irap && !got_irap;
152  extra_size = add_extradata * ctx->par_out->extradata_size;
153  got_irap |= is_irap;
154 
155  if (SIZE_MAX - nalu_size < 4 ||
156  SIZE_MAX - 4 - nalu_size < extra_size) {
157  ret = AVERROR_INVALIDDATA;
158  goto fail;
159  }
160 
161  prev_size = out->size;
162 
163  ret = av_grow_packet(out, 4 + nalu_size + extra_size);
164  if (ret < 0)
165  goto fail;
166 
167  if (add_extradata)
168  memcpy(out->data + prev_size, ctx->par_out->extradata, extra_size);
169  AV_WB32(out->data + prev_size + extra_size, 1);
170  bytestream2_get_buffer(&gb, out->data + prev_size + 4 + extra_size, nalu_size);
171  }
172 
173  ret = av_packet_copy_props(out, in);
174  if (ret < 0)
175  goto fail;
176 
177 fail:
178  if (ret < 0)
179  av_packet_unref(out);
180  av_packet_free(&in);
181 
182  return ret;
183 }
184 
185 static const enum AVCodecID codec_ids[] = {
187 };
188 
190  .name = "hevc_mp4toannexb",
191  .priv_data_size = sizeof(HEVCBSFContext),
194  .codec_ids = codec_ids,
195 };
#define NULL
Definition: coverity.c:32
const char * s
Definition: avisynth_c.h:768
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
AVCodecParameters * par_out
Parameters of the output stream.
Definition: avcodec.h:5721
static int hevc_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out)
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
Memory handling functions.
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
The bitstream filter state.
Definition: avcodec.h:5687
int size
Definition: avcodec.h:1431
#define AV_RB24
Definition: intreadwrite.h:64
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:133
void * priv_data
Opaque filter-specific private data.
Definition: avcodec.h:5708
static void filter(int16_t *output, ptrdiff_t out_stride, int16_t *low, ptrdiff_t low_stride, int16_t *high, ptrdiff_t high_stride, int len, int clip)
Definition: cfhd.c:114
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition: avpacket.c:62
uint8_t
#define AV_RB32
Definition: intreadwrite.h:130
const char * name
Definition: avcodec.h:5737
uint8_t * data
Definition: avcodec.h:1430
void av_packet_move_ref(AVPacket *dst, AVPacket *src)
Move every field in src to dst and reset src.
Definition: avpacket.c:647
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
#define av_log(a,...)
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: avcodec.h:215
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:164
#define MIN_HEVCC_LENGTH
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:263
static av_always_inline unsigned int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:154
#define fail()
Definition: checkasm.h:116
int extradata_size
Size of the extradata content in bytes.
Definition: avcodec.h:3902
int av_packet_copy_props(AVPacket *dst, const AVPacket *src)
Copy only "properties" fields from src to dst.
Definition: avpacket.c:558
AVFormatContext * ctx
Definition: movenc.c:48
static int hevc_mp4toannexb_init(AVBSFContext *ctx)
const AVBitStreamFilter ff_hevc_mp4toannexb_bsf
static int hevc_extradata_to_annexb(AVBSFContext *ctx)
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:163
Libavcodec external API header.
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:592
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi - 0x80) *(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t, *(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t, *(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) #define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac) { } void ff_audio_convert_free(AudioConvert **ac) { if(! *ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);} AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map) { AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method !=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2) { ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc) { av_free(ac);return NULL;} return ac;} in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar) { ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar ? ac->channels :1;} else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;} int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in) { int use_generic=1;int len=in->nb_samples;int p;if(ac->dc) { av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (dithered)\", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> in
#define AV_WB32(p, v)
Definition: intreadwrite.h:419
cl_device_type type
static enum AVCodecID codec_ids[]
int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt)
Called by the bitstream filters to get the next packet for filtering.
Definition: bsf.c:206
int av_grow_packet(AVPacket *pkt, int grow_by)
Increase packet size, correctly zeroing padding.
Definition: avpacket.c:109
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
Definition: avcodec.h:773
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: avcodec.h:3898
FILE * out
Definition: movenc.c:54
#define av_freep(p)
This structure stores compressed data.
Definition: avcodec.h:1407
AVCodecParameters * par_in
Parameters of the input stream.
Definition: avcodec.h:5715