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/intreadwrite.h"
25 #include "libavutil/mem.h"
26 #include "avcodec.h"
27 
28 typedef struct H264BSFContext {
33 
34 static int alloc_and_copy(uint8_t **poutbuf, int *poutbuf_size,
35  const uint8_t *sps_pps, uint32_t sps_pps_size,
36  const uint8_t *in, uint32_t in_size) {
37  uint32_t offset = *poutbuf_size;
38  uint8_t nal_header_size = offset ? 3 : 4;
39  void *tmp;
40 
41  *poutbuf_size += sps_pps_size+in_size+nal_header_size;
42  tmp = av_realloc(*poutbuf, *poutbuf_size);
43  if (!tmp)
44  return AVERROR(ENOMEM);
45  *poutbuf = tmp;
46  if (sps_pps)
47  memcpy(*poutbuf+offset, sps_pps, sps_pps_size);
48  memcpy(*poutbuf+sps_pps_size+nal_header_size+offset, in, in_size);
49  if (!offset) {
50  AV_WB32(*poutbuf+sps_pps_size, 1);
51  } else {
52  (*poutbuf+offset+sps_pps_size)[0] = (*poutbuf+offset+sps_pps_size)[1] = 0;
53  (*poutbuf+offset+sps_pps_size)[2] = 1;
54  }
55 
56  return 0;
57 }
58 
60  AVCodecContext *avctx, const char *args,
61  uint8_t **poutbuf, int *poutbuf_size,
62  const uint8_t *buf, int buf_size,
63  int keyframe) {
64  H264BSFContext *ctx = bsfc->priv_data;
65  int i;
66  uint8_t unit_type;
67  int32_t nal_size;
68  uint32_t cumul_size = 0;
69  const uint8_t *buf_end = buf + buf_size;
70  int ret = AVERROR(EINVAL);
71 
72  /* nothing to filter */
73  if (!avctx->extradata || avctx->extradata_size < 6) {
74  *poutbuf = (uint8_t*) buf;
75  *poutbuf_size = buf_size;
76  return 0;
77  }
78 
79  /* retrieve sps and pps NAL units from extradata */
80  if (!ctx->extradata_parsed) {
81  uint16_t unit_size;
82  uint64_t total_size = 0;
83  uint8_t *out = NULL, unit_nb, sps_done = 0, sps_seen = 0, pps_seen = 0;
84  const uint8_t *extradata = avctx->extradata+4;
85  static const uint8_t nalu_header[4] = {0, 0, 0, 1};
86 
87  /* retrieve length coded size */
88  ctx->length_size = (*extradata++ & 0x3) + 1;
89 
90  /* retrieve sps and pps unit(s) */
91  unit_nb = *extradata++ & 0x1f; /* number of sps unit(s) */
92  if (!unit_nb) {
93  goto pps;
94  } else {
95  sps_seen = 1;
96  }
97 
98  while (unit_nb--) {
99  void *tmp;
100 
101  unit_size = AV_RB16(extradata);
102  total_size += unit_size+4;
103  if (total_size > INT_MAX - FF_INPUT_BUFFER_PADDING_SIZE ||
104  extradata+2+unit_size > avctx->extradata+avctx->extradata_size) {
105  av_free(out);
106  return AVERROR(EINVAL);
107  }
108  tmp = av_realloc(out, total_size + FF_INPUT_BUFFER_PADDING_SIZE);
109  if (!tmp) {
110  av_free(out);
111  return AVERROR(ENOMEM);
112  }
113  out = tmp;
114  memcpy(out+total_size-unit_size-4, nalu_header, 4);
115  memcpy(out+total_size-unit_size, extradata+2, unit_size);
116  extradata += 2+unit_size;
117 pps:
118  if (!unit_nb && !sps_done++) {
119  unit_nb = *extradata++; /* number of pps unit(s) */
120  if (unit_nb)
121  pps_seen = 1;
122  }
123  }
124 
125  if(out)
126  memset(out + total_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
127 
128  if (!sps_seen)
129  av_log(avctx, AV_LOG_WARNING, "Warning: SPS NALU missing or invalid. The resulting stream may not play.\n");
130  if (!pps_seen)
131  av_log(avctx, AV_LOG_WARNING, "Warning: PPS NALU missing or invalid. The resulting stream may not play.\n");
132 
133  av_free(avctx->extradata);
134  avctx->extradata = out;
135  avctx->extradata_size = total_size;
136  ctx->first_idr = 1;
137  ctx->extradata_parsed = 1;
138  }
139 
140  *poutbuf_size = 0;
141  *poutbuf = NULL;
142  do {
143  ret= AVERROR(EINVAL);
144  if (buf + ctx->length_size > buf_end)
145  goto fail;
146 
147  for (nal_size = 0, i = 0; i<ctx->length_size; i++)
148  nal_size = (nal_size << 8) | buf[i];
149 
150  buf += ctx->length_size;
151  unit_type = *buf & 0x1f;
152 
153  if (buf + nal_size > buf_end || nal_size < 0)
154  goto fail;
155 
156  /* prepend only to the first type 5 NAL unit of an IDR picture */
157  if (ctx->first_idr && unit_type == 5) {
158  if ((ret=alloc_and_copy(poutbuf, poutbuf_size,
159  avctx->extradata, avctx->extradata_size,
160  buf, nal_size)) < 0)
161  goto fail;
162  ctx->first_idr = 0;
163  } else {
164  if ((ret=alloc_and_copy(poutbuf, poutbuf_size,
165  NULL, 0,
166  buf, nal_size)) < 0)
167  goto fail;
168  if (!ctx->first_idr && unit_type == 1)
169  ctx->first_idr = 1;
170  }
171 
172  buf += nal_size;
173  cumul_size += nal_size + ctx->length_size;
174  } while (cumul_size < buf_size);
175 
176  return 1;
177 
178 fail:
179  av_freep(poutbuf);
180  *poutbuf_size = 0;
181  return ret;
182 }
183 
185  "h264_mp4toannexb",
186  sizeof(H264BSFContext),
188 };
struct H264BSFContext H264BSFContext
memory handling functions
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:154
About Git write you should know how to use GIT properly Luckily Git comes with excellent documentation git help man git shows you the available git< command > help man git< command > shows information about the subcommand< command > The most comprehensive manual is the website Git Reference visit they are quite exhaustive You do not need a special username or password All you need is to provide a ssh public key to the Git server admin What follows now is a basic introduction to Git and some FFmpeg specific guidelines Read it at least if you are granted commit privileges to the FFmpeg project you are expected to be familiar with these rules I if not You can get git from etc no matter how small Every one of them has been saved from looking like a fool by this many times It s very easy for stray debug output or cosmetic modifications to slip in
Definition: git-howto.txt:5
void * av_realloc(void *ptr, size_t size)
Allocate or reallocate a block of memory.
Definition: mem.c:141
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:198
#define AV_WB32(p, darg)
Definition: intreadwrite.h:265
uint8_t
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:183
static int h264_mp4toannexb_filter(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args, uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size, int keyframe)
#define AV_RB16
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
static const uint8_t offset[127][2]
Definition: vf_spp.c:70
external API header
#define FF_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
ret
Definition: avfilter.c:821
int32_t
NULL
Definition: eval.c:55
main external API structure.
void * buf
Definition: avisynth_c.h:594
synthesis window for stochastic i
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
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=av_sample_fmt_is_planar(in_fmt);out_planar=av_sample_fmt_is_planar(out_fmt);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_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_dlog(ac->avr,"%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-> out
static int alloc_and_copy(uint8_t **poutbuf, int *poutbuf_size, const uint8_t *sps_pps, uint32_t sps_pps_size, const uint8_t *in, uint32_t in_size)
AVBitStreamFilter ff_h264_mp4toannexb_bsf