FFmpeg  4.4.5
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 "bsf_internal.h"
30 #include "bytestream.h"
31 #include "hevc.h"
32 
33 #define MIN_HEVCC_LENGTH 23
34 
35 typedef struct HEVCBSFContext {
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);
63  ret = AVERROR_INVALIDDATA;
64  goto fail;
65  }
66 
67  for (j = 0; j < cnt; j++) {
68  int nalu_len = bytestream2_get_be16(&gb);
69 
70  if (4 + AV_INPUT_BUFFER_PADDING_SIZE + nalu_len > SIZE_MAX - new_extradata_size) {
71  ret = AVERROR_INVALIDDATA;
72  goto fail;
73  }
74  ret = av_reallocp(&new_extradata, new_extradata_size + nalu_len + 4 + AV_INPUT_BUFFER_PADDING_SIZE);
75  if (ret < 0)
76  goto fail;
77 
78  AV_WB32(new_extradata + new_extradata_size, 1); // add the startcode
79  bytestream2_get_buffer(&gb, new_extradata + new_extradata_size + 4, nalu_len);
80  new_extradata_size += 4 + nalu_len;
81  memset(new_extradata + new_extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
82  }
83  }
84 
85  av_freep(&ctx->par_out->extradata);
86  ctx->par_out->extradata = new_extradata;
87  ctx->par_out->extradata_size = new_extradata_size;
88 
89  if (!new_extradata_size)
90  av_log(ctx, AV_LOG_WARNING, "No parameter sets in the extradata\n");
91 
92  return length_size;
93 fail:
94  av_freep(&new_extradata);
95  return ret;
96 }
97 
99 {
101  int ret;
102 
103  if (ctx->par_in->extradata_size < MIN_HEVCC_LENGTH ||
104  AV_RB24(ctx->par_in->extradata) == 1 ||
105  AV_RB32(ctx->par_in->extradata) == 1) {
107  "The input looks like it is Annex B already\n");
108  } else {
110  if (ret < 0)
111  return ret;
112  s->length_size = ret;
113  s->extradata_parsed = 1;
114  }
115 
116  return 0;
117 }
118 
120 {
122  AVPacket *in;
123  GetByteContext gb;
124 
125  int got_irap = 0;
126  int i, ret = 0;
127 
128  ret = ff_bsf_get_packet(ctx, &in);
129  if (ret < 0)
130  return ret;
131 
132  if (!s->extradata_parsed) {
134  av_packet_free(&in);
135  return 0;
136  }
137 
138  bytestream2_init(&gb, in->data, in->size);
139 
140  while (bytestream2_get_bytes_left(&gb)) {
141  uint32_t nalu_size = 0;
142  int nalu_type;
143  int is_irap, add_extradata, extra_size, prev_size;
144 
145  if (bytestream2_get_bytes_left(&gb) < s->length_size) {
146  ret = AVERROR_INVALIDDATA;
147  goto fail;
148  }
149  for (i = 0; i < s->length_size; i++)
150  nalu_size = (nalu_size << 8) | bytestream2_get_byte(&gb);
151 
152  if (nalu_size < 2 || nalu_size > bytestream2_get_bytes_left(&gb)) {
153  ret = AVERROR_INVALIDDATA;
154  goto fail;
155  }
156 
157  nalu_type = (bytestream2_peek_byte(&gb) >> 1) & 0x3f;
158 
159  /* prepend extradata to IRAP frames */
160  is_irap = nalu_type >= 16 && nalu_type <= 23;
161  add_extradata = is_irap && !got_irap;
162  extra_size = add_extradata * ctx->par_out->extradata_size;
163  got_irap |= is_irap;
164 
165  if (FFMIN(INT_MAX, SIZE_MAX) < 4ULL + nalu_size + extra_size) {
166  ret = AVERROR_INVALIDDATA;
167  goto fail;
168  }
169 
170  prev_size = out->size;
171 
172  ret = av_grow_packet(out, 4 + nalu_size + extra_size);
173  if (ret < 0)
174  goto fail;
175 
176  if (extra_size)
177  memcpy(out->data + prev_size, ctx->par_out->extradata, extra_size);
178  AV_WB32(out->data + prev_size + extra_size, 1);
179  bytestream2_get_buffer(&gb, out->data + prev_size + 4 + extra_size, nalu_size);
180  }
181 
182  ret = av_packet_copy_props(out, in);
183  if (ret < 0)
184  goto fail;
185 
186 fail:
187  if (ret < 0)
189  av_packet_free(&in);
190 
191  return ret;
192 }
193 
194 static const enum AVCodecID codec_ids[] = {
196 };
197 
199  .name = "hevc_mp4toannexb",
200  .priv_data_size = sizeof(HEVCBSFContext),
203  .codec_ids = codec_ids,
204 };
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)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> in
uint8_t
Libavcodec external API header.
#define AV_RB24
Definition: intreadwrite.h:64
#define AV_RB32
Definition: intreadwrite.h:130
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:31
int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt)
Called by the bitstream filters to get the next packet for filtering.
Definition: bsf.c:232
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:267
static av_always_inline int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:158
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:137
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:168
#define s(width, name)
Definition: cbs_vp9.c:257
static av_always_inline void filter(int16_t *output, ptrdiff_t out_stride, const int16_t *low, ptrdiff_t low_stride, const int16_t *high, ptrdiff_t high_stride, int len, int clip)
Definition: cfhddsp.c:27
#define fail()
Definition: checkasm.h:133
#define FFMIN(a, b)
Definition: common.h:105
#define NULL
Definition: coverity.c:32
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: codec_id.h:46
@ AV_CODEC_ID_NONE
Definition: codec_id.h:47
@ AV_CODEC_ID_HEVC
Definition: codec_id.h:223
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding.
Definition: avcodec.h:215
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition: avpacket.c:75
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:634
int av_grow_packet(AVPacket *pkt, int grow_by)
Increase packet size, correctly zeroing padding.
Definition: avpacket.c:122
void av_packet_move_ref(AVPacket *dst, AVPacket *src)
Move every field in src to dst and reset src.
Definition: avpacket.c:690
int av_packet_copy_props(AVPacket *dst, const AVPacket *src)
Copy only "properties" fields from src to dst.
Definition: avpacket.c:600
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:200
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:210
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
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:161
static int hevc_mp4toannexb_init(AVBSFContext *ctx)
static enum AVCodecID codec_ids[]
const AVBitStreamFilter ff_hevc_mp4toannexb_bsf
static int hevc_extradata_to_annexb(AVBSFContext *ctx)
static int hevc_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out)
#define MIN_HEVCC_LENGTH
cl_device_type type
int i
Definition: input.c:407
#define AV_WB32(p, v)
Definition: intreadwrite.h:419
@ HEVC_NAL_SEI_SUFFIX
Definition: hevc.h:69
@ HEVC_NAL_SEI_PREFIX
Definition: hevc.h:68
@ HEVC_NAL_PPS
Definition: hevc.h:63
@ HEVC_NAL_VPS
Definition: hevc.h:61
@ HEVC_NAL_SPS
Definition: hevc.h:62
internal header for HEVC (de)muxer utilities
Memory handling functions.
The bitstream filter state.
Definition: bsf.h:49
const char * name
Definition: bsf.h:99
void * priv_data
Format private data.
Definition: avformat.h:1260
This structure stores compressed data.
Definition: packet.h:346
#define av_freep(p)
#define av_log(a,...)
FILE * out
Definition: movenc.c:54
AVFormatContext * ctx
Definition: movenc.c:48