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 FFmpeg.
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.
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.
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
24 #include "libavutil/intreadwrite.h"
25 #include "libavutil/mem.h"
28 typedef struct H264BSFContext
{
31 uint8_t idr_sps_pps_seen
;
35 static int alloc_and_copy(uint8_t **poutbuf
, int *poutbuf_size
,
36 const uint8_t *sps_pps
, uint32_t sps_pps_size
,
37 const uint8_t *in
, uint32_t in_size
)
39 uint32_t offset
= *poutbuf_size
;
40 uint8_t nal_header_size
= offset
? 3 : 4;
43 *poutbuf_size
+= sps_pps_size
+ in_size
+ nal_header_size
;
44 if ((err
= av_reallocp(poutbuf
,
45 *poutbuf_size
+ FF_INPUT_BUFFER_PADDING_SIZE
)) < 0) {
50 memcpy(*poutbuf
+ offset
, sps_pps
, sps_pps_size
);
51 memcpy(*poutbuf
+ sps_pps_size
+ nal_header_size
+ offset
, in
, in_size
);
53 AV_WB32(*poutbuf
+ sps_pps_size
, 1);
55 (*poutbuf
+ offset
+ sps_pps_size
)[0] =
56 (*poutbuf
+ offset
+ sps_pps_size
)[1] = 0;
57 (*poutbuf
+ offset
+ sps_pps_size
)[2] = 1;
63 static int h264_extradata_to_annexb(AVCodecContext
*avctx
, const int padding
)
66 uint64_t total_size
= 0;
67 uint8_t *out
= NULL
, unit_nb
, sps_done
= 0,
68 sps_seen
= 0, pps_seen
= 0;
69 const uint8_t *extradata
= avctx
->extradata
+ 4;
70 static const uint8_t nalu_header
[4] = { 0, 0, 0, 1 };
71 int length_size
= (*extradata
++ & 0x3) + 1; // retrieve length coded size
73 /* retrieve sps and pps unit(s) */
74 unit_nb
= *extradata
++ & 0x1f; /* number of sps unit(s) */
84 unit_size
= AV_RB16(extradata
);
85 total_size
+= unit_size
+ 4;
86 if (total_size
> INT_MAX
- padding
) {
87 av_log(avctx
, AV_LOG_ERROR
,
88 "Too big extradata size, corrupted stream or invalid MP4/AVCC bitstream\n");
90 return AVERROR(EINVAL
);
92 if (extradata
+ 2 + unit_size
> avctx
->extradata
+ avctx
->extradata_size
) {
93 av_log(avctx
, AV_LOG_ERROR
, "Packet header is not contained in global extradata, "
94 "corrupted stream or invalid MP4/AVCC bitstream\n");
96 return AVERROR(EINVAL
);
98 if ((err
= av_reallocp(&out
, total_size
+ padding
)) < 0)
100 memcpy(out
+ total_size
- unit_size
- 4, nalu_header
, 4);
101 memcpy(out
+ total_size
- unit_size
, extradata
+ 2, unit_size
);
102 extradata
+= 2 + unit_size
;
104 if (!unit_nb
&& !sps_done
++) {
105 unit_nb
= *extradata
++; /* number of pps unit(s) */
112 memset(out
+ total_size
, 0, FF_INPUT_BUFFER_PADDING_SIZE
);
115 av_log(avctx
, AV_LOG_WARNING
,
116 "Warning: SPS NALU missing or invalid. "
117 "The resulting stream may not play.\n");
120 av_log(avctx
, AV_LOG_WARNING
,
121 "Warning: PPS NALU missing or invalid. "
122 "The resulting stream may not play.\n");
124 av_free(avctx
->extradata
);
125 avctx
->extradata
= out
;
126 avctx
->extradata_size
= total_size
;
131 static int h264_mp4toannexb_filter(AVBitStreamFilterContext
*bsfc
,
132 AVCodecContext
*avctx
, const char *args
,
133 uint8_t **poutbuf
, int *poutbuf_size
,
134 const uint8_t *buf
, int buf_size
,
137 H264BSFContext
*ctx
= bsfc
->priv_data
;
141 uint32_t cumul_size
= 0;
142 const uint8_t *buf_end
= buf
+ buf_size
;
145 /* nothing to filter */
146 if (!avctx
->extradata
|| avctx
->extradata_size
< 6) {
147 *poutbuf
= (uint8_t *)buf
;
148 *poutbuf_size
= buf_size
;
152 /* retrieve sps and pps NAL units from extradata */
153 if (!ctx
->extradata_parsed
) {
154 ret
= h264_extradata_to_annexb(avctx
, FF_INPUT_BUFFER_PADDING_SIZE
);
157 ctx
->length_size
= ret
;
159 ctx
->idr_sps_pps_seen
= 0;
160 ctx
->extradata_parsed
= 1;
166 ret
= AVERROR(EINVAL
);
167 if (buf
+ ctx
->length_size
> buf_end
)
170 for (nal_size
= 0, i
= 0; i
<ctx
->length_size
; i
++)
171 nal_size
= (nal_size
<< 8) | buf
[i
];
173 buf
+= ctx
->length_size
;
174 unit_type
= *buf
& 0x1f;
176 if (buf
+ nal_size
> buf_end
|| nal_size
< 0)
179 if (unit_type
== 7 || unit_type
== 8)
180 ctx
->idr_sps_pps_seen
= 1;
182 /* if this is a new IDR picture following an IDR picture, reset the idr flag.
183 * Just check first_mb_in_slice to be 0 as this is the simplest solution.
184 * This could be checking idr_pic_id instead, but would complexify the parsing. */
185 if (!ctx
->new_idr
&& unit_type
== 5 && (buf
[1] & 0x80))
188 /* prepend only to the first type 5 NAL unit of an IDR picture, if no sps/pps are already present */
189 if (ctx
->new_idr
&& unit_type
== 5 && !ctx
->idr_sps_pps_seen
) {
190 if ((ret
=alloc_and_copy(poutbuf
, poutbuf_size
,
191 avctx
->extradata
, avctx
->extradata_size
,
196 if ((ret
=alloc_and_copy(poutbuf
, poutbuf_size
,
197 NULL
, 0, buf
, nal_size
)) < 0)
199 if (!ctx
->new_idr
&& unit_type
== 1) {
201 ctx
->idr_sps_pps_seen
= 0;
206 cumul_size
+= nal_size
+ ctx
->length_size
;
207 } while (cumul_size
< buf_size
);
217 AVBitStreamFilter ff_h264_mp4toannexb_bsf
= {
218 .name
= "h264_mp4toannexb",
219 .priv_data_size
= sizeof(H264BSFContext
),
220 .filter
= h264_mp4toannexb_filter
,