2 * H.264 MP4 to Annex B byte stream format filter
3 * Copyright (c) 2007 Benoit Fouet <benoit.fouet@free.fr>
5 * This file is part of Libav.
7 * Libav 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.
12 * Libav 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.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 #include "libavutil/intreadwrite.h"
25 #include "libavutil/mem.h"
28 typedef struct H264BSFContext
{
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;
41 *poutbuf_size
+= sps_pps_size
+in_size
+nal_header_size
;
42 tmp
= av_realloc(*poutbuf
, *poutbuf_size
);
44 return AVERROR(ENOMEM
);
47 memcpy(*poutbuf
+offset
, sps_pps
, sps_pps_size
);
48 memcpy(*poutbuf
+sps_pps_size
+nal_header_size
+offset
, in
, in_size
);
50 AV_WB32(*poutbuf
+sps_pps_size
, 1);
52 (*poutbuf
+offset
+sps_pps_size
)[0] = (*poutbuf
+offset
+sps_pps_size
)[1] = 0;
53 (*poutbuf
+offset
+sps_pps_size
)[2] = 1;
59 static int h264_mp4toannexb_filter(AVBitStreamFilterContext
*bsfc
,
60 AVCodecContext
*avctx
, const char *args
,
61 uint8_t **poutbuf
, int *poutbuf_size
,
62 const uint8_t *buf
, int buf_size
,
64 H264BSFContext
*ctx
= bsfc
->priv_data
;
67 uint32_t cumul_size
= 0;
68 const uint8_t *buf_end
= buf
+ buf_size
;
70 /* nothing to filter */
71 if (!avctx
->extradata
|| avctx
->extradata_size
< 6) {
72 *poutbuf
= (uint8_t*) buf
;
73 *poutbuf_size
= buf_size
;
77 /* retrieve sps and pps NAL units from extradata */
78 if (!ctx
->extradata_parsed
) {
80 uint64_t total_size
= 0;
81 uint8_t *out
= NULL
, unit_nb
, sps_done
= 0, sps_seen
= 0, pps_seen
= 0;
82 const uint8_t *extradata
= avctx
->extradata
+4;
83 static const uint8_t nalu_header
[4] = {0, 0, 0, 1};
85 /* retrieve length coded size */
86 ctx
->length_size
= (*extradata
++ & 0x3) + 1;
87 if (ctx
->length_size
== 3)
88 return AVERROR(EINVAL
);
90 /* retrieve sps and pps unit(s) */
91 unit_nb
= *extradata
++ & 0x1f; /* number of sps unit(s) */
93 unit_nb
= *extradata
++; /* number of pps unit(s) */
105 unit_size
= AV_RB16(extradata
);
106 total_size
+= unit_size
+4;
107 if (total_size
> INT_MAX
- FF_INPUT_BUFFER_PADDING_SIZE
||
108 extradata
+2+unit_size
> avctx
->extradata
+avctx
->extradata_size
) {
110 return AVERROR(EINVAL
);
112 tmp
= av_realloc(out
, total_size
+ FF_INPUT_BUFFER_PADDING_SIZE
);
115 return AVERROR(ENOMEM
);
118 memcpy(out
+total_size
-unit_size
-4, nalu_header
, 4);
119 memcpy(out
+total_size
-unit_size
, extradata
+2, unit_size
);
120 extradata
+= 2+unit_size
;
122 if (!unit_nb
&& !sps_done
++) {
123 unit_nb
= *extradata
++; /* number of pps unit(s) */
130 memset(out
+ total_size
, 0, FF_INPUT_BUFFER_PADDING_SIZE
);
133 av_log(avctx
, AV_LOG_WARNING
, "Warning: SPS NALU missing or invalid. The resulting stream may not play.\n");
135 av_log(avctx
, AV_LOG_WARNING
, "Warning: PPS NALU missing or invalid. The resulting stream may not play.\n");
137 av_free(avctx
->extradata
);
138 avctx
->extradata
= out
;
139 avctx
->extradata_size
= total_size
;
141 ctx
->extradata_parsed
= 1;
147 if (buf
+ ctx
->length_size
> buf_end
)
150 if (ctx
->length_size
== 1) {
152 } else if (ctx
->length_size
== 2) {
153 nal_size
= AV_RB16(buf
);
155 nal_size
= AV_RB32(buf
);
157 buf
+= ctx
->length_size
;
158 unit_type
= *buf
& 0x1f;
160 if (buf
+ nal_size
> buf_end
|| nal_size
< 0)
163 /* prepend only to the first type 5 NAL unit of an IDR picture */
164 if (ctx
->first_idr
&& unit_type
== 5) {
165 if (alloc_and_copy(poutbuf
, poutbuf_size
,
166 avctx
->extradata
, avctx
->extradata_size
,
171 if (alloc_and_copy(poutbuf
, poutbuf_size
,
175 if (!ctx
->first_idr
&& unit_type
== 1)
180 cumul_size
+= nal_size
+ ctx
->length_size
;
181 } while (cumul_size
< buf_size
);
188 return AVERROR(EINVAL
);
191 AVBitStreamFilter ff_h264_mp4toannexb_bsf
= {
193 sizeof(H264BSFContext
),
194 h264_mp4toannexb_filter
,