FFmpeg  4.3.7
h264_mp4toannexb_bsf.c
Go to the documentation of this file.
1 /*
2  * H.264 MP4 to Annex B byte stream format filter
3  * Copyright (c) 2007 Benoit Fouet <benoit.fouet@free.fr>
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/avassert.h"
25 #include "libavutil/intreadwrite.h"
26 #include "libavutil/mem.h"
27 
28 #include "avcodec.h"
29 #include "bsf.h"
30 #include "bsf_internal.h"
31 #include "bytestream.h"
32 #include "h264.h"
33 
34 typedef struct H264BSFContext {
37  int sps_size;
38  int pps_size;
45 
46 static void count_or_copy(uint8_t **out, uint64_t *out_size,
47  const uint8_t *in, int in_size, int ps, int copy)
48 {
49  uint8_t start_code_size = ps < 0 ? 0 : *out_size == 0 || ps ? 4 : 3;
50 
51  if (copy) {
52  memcpy(*out + start_code_size, in, in_size);
53  if (start_code_size == 4) {
54  AV_WB32(*out, 1);
55  } else if (start_code_size) {
56  (*out)[0] =
57  (*out)[1] = 0;
58  (*out)[2] = 1;
59  }
60  *out += start_code_size + in_size;
61  }
62  *out_size += start_code_size + in_size;
63 }
64 
65 static int h264_extradata_to_annexb(AVBSFContext *ctx, const int padding)
66 {
67  H264BSFContext *s = ctx->priv_data;
68  GetByteContext ogb, *gb = &ogb;
69  uint16_t unit_size;
70  uint32_t total_size = 0;
71  uint8_t *out = NULL, unit_nb, sps_done = 0;
72  static const uint8_t nalu_header[4] = { 0, 0, 0, 1 };
73  int length_size, pps_offset = 0;
74 
76 
77  bytestream2_skipu(gb, 4);
78 
79  /* retrieve length coded size */
80  length_size = (bytestream2_get_byteu(gb) & 0x3) + 1;
81 
82  /* retrieve sps and pps unit(s) */
83  unit_nb = bytestream2_get_byteu(gb) & 0x1f; /* number of sps unit(s) */
84  if (!unit_nb) {
85  goto pps;
86  }
87 
88  while (unit_nb--) {
89  int err;
90 
91  /* possible overread ok due to padding */
92  unit_size = bytestream2_get_be16u(gb);
93  total_size += unit_size + 4;
94  av_assert1(total_size <= INT_MAX - padding);
95  if (bytestream2_get_bytes_left(gb) < unit_size + !sps_done) {
96  av_log(ctx, AV_LOG_ERROR, "Global extradata truncated, "
97  "corrupted stream or invalid MP4/AVCC bitstream\n");
98  av_free(out);
99  return AVERROR_INVALIDDATA;
100  }
101  if ((err = av_reallocp(&out, total_size + padding)) < 0)
102  return err;
103  memcpy(out + total_size - unit_size - 4, nalu_header, 4);
104  bytestream2_get_bufferu(gb, out + total_size - unit_size, unit_size);
105 pps:
106  if (!unit_nb && !sps_done++) {
107  unit_nb = bytestream2_get_byteu(gb); /* number of pps unit(s) */
108  pps_offset = total_size;
109  }
110  }
111 
112  if (out)
113  memset(out + total_size, 0, padding);
114 
115  if (pps_offset) {
116  s->sps = out;
117  s->sps_size = pps_offset;
118  } else {
119  av_log(ctx, AV_LOG_WARNING,
120  "Warning: SPS NALU missing or invalid. "
121  "The resulting stream may not play.\n");
122  }
123  if (pps_offset < total_size) {
124  s->pps = out + pps_offset;
125  s->pps_size = total_size - pps_offset;
126  } else {
127  av_log(ctx, AV_LOG_WARNING,
128  "Warning: PPS NALU missing or invalid. "
129  "The resulting stream may not play.\n");
130  }
131 
132  av_freep(&ctx->par_out->extradata);
133  ctx->par_out->extradata = out;
134  ctx->par_out->extradata_size = total_size;
135 
136  return length_size;
137 }
138 
140 {
141  H264BSFContext *s = ctx->priv_data;
142  int extra_size = ctx->par_in->extradata_size;
143  int ret;
144 
145  /* retrieve sps and pps NAL units from extradata */
146  if (!extra_size ||
147  (extra_size >= 3 && AV_RB24(ctx->par_in->extradata) == 1) ||
148  (extra_size >= 4 && AV_RB32(ctx->par_in->extradata) == 1)) {
149  av_log(ctx, AV_LOG_VERBOSE,
150  "The input looks like it is Annex B already\n");
151  } else if (extra_size >= 7) {
153  if (ret < 0)
154  return ret;
155 
156  s->length_size = ret;
157  s->new_idr = 1;
158  s->idr_sps_seen = 0;
159  s->idr_pps_seen = 0;
160  s->extradata_parsed = 1;
161  } else {
162  av_log(ctx, AV_LOG_ERROR, "Invalid extradata size: %d\n", extra_size);
163  return AVERROR_INVALIDDATA;
164  }
165 
166  return 0;
167 }
168 
170 {
171  H264BSFContext *s = ctx->priv_data;
172  AVPacket *in;
173  uint8_t unit_type, new_idr, sps_seen, pps_seen;
174  const uint8_t *buf;
175  const uint8_t *buf_end;
176  uint8_t *out;
177  uint64_t out_size;
178  int ret;
179 
180  ret = ff_bsf_get_packet(ctx, &in);
181  if (ret < 0)
182  return ret;
183 
184  /* nothing to filter */
185  if (!s->extradata_parsed) {
186  av_packet_move_ref(opkt, in);
187  av_packet_free(&in);
188  return 0;
189  }
190 
191  buf_end = in->data + in->size;
192 
193 #define LOG_ONCE(...) \
194  if (j) \
195  av_log(__VA_ARGS__)
196  for (int j = 0; j < 2; j++) {
197  buf = in->data;
198  new_idr = s->new_idr;
199  sps_seen = s->idr_sps_seen;
200  pps_seen = s->idr_pps_seen;
201  out_size = 0;
202 
203  do {
204  uint32_t nal_size = 0;
205 
206  /* possible overread ok due to padding */
207  for (int i = 0; i < s->length_size; i++)
208  nal_size = (nal_size << 8) | buf[i];
209 
210  buf += s->length_size;
211 
212  /* This check requires the cast as the right side might
213  * otherwise be promoted to an unsigned value. */
214  if ((int64_t)nal_size > buf_end - buf) {
215  ret = AVERROR_INVALIDDATA;
216  goto fail;
217  }
218 
219  if (!nal_size)
220  continue;
221 
222  unit_type = *buf & 0x1f;
223 
224  if (unit_type == H264_NAL_SPS) {
225  sps_seen = new_idr = 1;
226  } else if (unit_type == H264_NAL_PPS) {
227  pps_seen = new_idr = 1;
228  /* if SPS has not been seen yet, prepend the AVCC one to PPS */
229  if (!sps_seen) {
230  if (!s->sps_size) {
231  LOG_ONCE(ctx, AV_LOG_WARNING, "SPS not present in the stream, nor in AVCC, stream may be unreadable\n");
232  } else {
233  count_or_copy(&out, &out_size, s->sps, s->sps_size, -1, j);
234  sps_seen = 1;
235  }
236  }
237  }
238 
239  /* If this is a new IDR picture following an IDR picture, reset the idr flag.
240  * Just check first_mb_in_slice to be 0 as this is the simplest solution.
241  * This could be checking idr_pic_id instead, but would complexify the parsing. */
242  if (!new_idr && unit_type == H264_NAL_IDR_SLICE && (buf[1] & 0x80))
243  new_idr = 1;
244 
245  /* prepend only to the first type 5 NAL unit of an IDR picture, if no sps/pps are already present */
246  if (new_idr && unit_type == H264_NAL_IDR_SLICE && !sps_seen && !pps_seen) {
247  if (ctx->par_out->extradata)
248  count_or_copy(&out, &out_size, ctx->par_out->extradata,
249  ctx->par_out->extradata_size, -1, j);
250  new_idr = 0;
251  /* if only SPS has been seen, also insert PPS */
252  } else if (new_idr && unit_type == H264_NAL_IDR_SLICE && sps_seen && !pps_seen) {
253  if (!s->pps_size) {
254  LOG_ONCE(ctx, AV_LOG_WARNING, "PPS not present in the stream, nor in AVCC, stream may be unreadable\n");
255  } else {
256  count_or_copy(&out, &out_size, s->pps, s->pps_size, -1, j);
257  }
258  }
259 
260  count_or_copy(&out, &out_size, buf, nal_size,
261  unit_type == H264_NAL_SPS || unit_type == H264_NAL_PPS, j);
262  if (!new_idr && unit_type == H264_NAL_SLICE) {
263  new_idr = 1;
264  sps_seen = 0;
265  pps_seen = 0;
266  }
267 
268  buf += nal_size;
269  } while (buf < buf_end);
270 
271  if (!j) {
272  if (out_size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) {
273  ret = AVERROR_INVALIDDATA;
274  goto fail;
275  }
276  ret = av_new_packet(opkt, out_size);
277  if (ret < 0)
278  goto fail;
279  out = opkt->data;
280  }
281  }
282 #undef LOG_ONCE
283 
284  av_assert1(out_size == opkt->size);
285 
286  s->new_idr = new_idr;
287  s->idr_sps_seen = sps_seen;
288  s->idr_pps_seen = pps_seen;
289 
290  ret = av_packet_copy_props(opkt, in);
291  if (ret < 0)
292  goto fail;
293 
294 fail:
295  if (ret < 0)
296  av_packet_unref(opkt);
297  av_packet_free(&in);
298 
299  return ret;
300 }
301 
303 {
304  H264BSFContext *s = ctx->priv_data;
305 
306  s->idr_sps_seen = 0;
307  s->idr_pps_seen = 0;
308  s->new_idr = s->extradata_parsed;
309 }
310 
311 static const enum AVCodecID codec_ids[] = {
313 };
314 
316  .name = "h264_mp4toannexb",
317  .priv_data_size = sizeof(H264BSFContext),
321  .codec_ids = codec_ids,
322 };
#define NULL
Definition: coverity.c:32
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
AVCodecParameters * par_out
Parameters of the output stream.
Definition: bsf.h:83
static void copy(const float *p1, float *p2, const int length)
static void flush(AVCodecContext *avctx)
#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: bsf.h:49
int size
Definition: packet.h:356
#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
int out_size
Definition: movenc.c:55
static int h264_mp4toannexb_init(AVBSFContext *ctx)
void * priv_data
Opaque filter-specific private data.
Definition: bsf.h:70
static av_always_inline unsigned int bytestream2_get_bufferu(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:273
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:196
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition: avpacket.c:64
uint8_t
#define AV_RB32
Definition: intreadwrite.h:130
const char * name
Definition: bsf.h:99
uint8_t * data
Definition: packet.h:355
void av_packet_move_ref(AVPacket *dst, AVPacket *src)
Move every field in src to dst and reset src.
Definition: avpacket.c:663
static int h264_extradata_to_annexb(AVBSFContext *ctx, const int padding)
static av_always_inline void bytestream2_skipu(GetByteContext *g, unsigned int size)
Definition: bytestream.h:170
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
#define av_log(a,...)
static av_always_inline int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:154
H.264 common definitions.
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:88
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: codec_id.h:46
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
static void h264_mp4toannexb_flush(AVBSFContext *ctx)
simple assert() macros that are a bit more flexible than ISO C assert().
#define fail()
Definition: checkasm.h:123
int extradata_size
Size of the extradata content in bytes.
Definition: codec_par.h:78
int av_packet_copy_props(AVPacket *dst, const AVPacket *src)
Copy only "properties" fields from src to dst.
Definition: avpacket.c:571
static void count_or_copy(uint8_t **out, uint64_t *out_size, const uint8_t *in, int in_size, int ps, int copy)
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition: avassert.h:53
AVFormatContext * ctx
Definition: movenc.c:48
#define s(width, name)
Definition: cbs_vp9.c:257
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
Libavcodec external API header.
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:605
#define LOG_ONCE(...)
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
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:228
#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
const AVBitStreamFilter ff_h264_mp4toannexb_bsf
#define av_free(p)
static int h264_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *opkt)
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: codec_par.h:74
FILE * out
Definition: movenc.c:54
#define av_freep(p)
This structure stores compressed data.
Definition: packet.h:332
AVCodecParameters * par_in
Parameters of the input stream.
Definition: bsf.h:77