Line | Branch | Exec | Source |
---|---|---|---|
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 "bsf.h" | ||
29 | #include "bsf_internal.h" | ||
30 | #include "bytestream.h" | ||
31 | #include "defs.h" | ||
32 | #include "h264.h" | ||
33 | |||
34 | typedef struct H264BSFContext { | ||
35 | uint8_t *sps; | ||
36 | uint8_t *pps; | ||
37 | int sps_size; | ||
38 | int pps_size; | ||
39 | unsigned sps_buf_size; | ||
40 | unsigned pps_buf_size; | ||
41 | uint8_t length_size; | ||
42 | uint8_t new_idr; | ||
43 | uint8_t idr_sps_seen; | ||
44 | uint8_t idr_pps_seen; | ||
45 | int extradata_parsed; | ||
46 | } H264BSFContext; | ||
47 | |||
48 | enum PsSource { | ||
49 | PS_OUT_OF_BAND = -1, | ||
50 | PS_NONE = 0, | ||
51 | PS_IN_BAND = 1, | ||
52 | }; | ||
53 | |||
54 | 3578 | static void count_or_copy(uint8_t **out, uint64_t *out_size, | |
55 | const uint8_t *in, int in_size, enum PsSource ps, int copy) | ||
56 | { | ||
57 | uint8_t start_code_size; | ||
58 | |||
59 |
2/2✓ Branch 0 taken 68 times.
✓ Branch 1 taken 3510 times.
|
3578 | if (ps == PS_OUT_OF_BAND) |
60 | /* start code already present in out-of-band ps data, so don't need to | ||
61 | * add it manually again | ||
62 | */ | ||
63 | 68 | start_code_size = 0; | |
64 |
4/4✓ Branch 0 taken 3506 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 820 times.
✓ Branch 3 taken 2686 times.
|
3510 | else if (ps == PS_IN_BAND || *out_size == 0) |
65 | 824 | start_code_size = 4; | |
66 | else | ||
67 | 2686 | start_code_size = 3; | |
68 | |||
69 |
2/2✓ Branch 0 taken 1789 times.
✓ Branch 1 taken 1789 times.
|
3578 | if (copy) { |
70 | 1789 | memcpy(*out + start_code_size, in, in_size); | |
71 |
2/2✓ Branch 0 taken 412 times.
✓ Branch 1 taken 1377 times.
|
1789 | if (start_code_size == 4) { |
72 | 412 | AV_WB32(*out, 1); | |
73 |
2/2✓ Branch 0 taken 1343 times.
✓ Branch 1 taken 34 times.
|
1377 | } else if (start_code_size) { |
74 | 1343 | (*out)[0] = | |
75 | 1343 | (*out)[1] = 0; | |
76 | 1343 | (*out)[2] = 1; | |
77 | } | ||
78 | 1789 | *out += start_code_size + in_size; | |
79 | } | ||
80 | 3578 | *out_size += start_code_size + in_size; | |
81 | 3578 | } | |
82 | |||
83 | 10 | static int h264_extradata_to_annexb(AVBSFContext *ctx, | |
84 | uint8_t *extradata, int extradata_size) | ||
85 | { | ||
86 | 10 | H264BSFContext *s = ctx->priv_data; | |
87 | 10 | GetByteContext ogb, *gb = &ogb; | |
88 | uint16_t unit_size; | ||
89 | 10 | uint32_t total_size = 0; | |
90 | 10 | uint8_t *out = NULL, unit_nb, sps_done = 0; | |
91 | static const uint8_t nalu_header[4] = { 0, 0, 0, 1 }; | ||
92 | 10 | const int padding = AV_INPUT_BUFFER_PADDING_SIZE; | |
93 | 10 | int length_size, pps_offset = 0; | |
94 | |||
95 | 10 | bytestream2_init(gb, extradata, extradata_size); | |
96 | |||
97 | 10 | bytestream2_skipu(gb, 4); | |
98 | |||
99 | /* retrieve length coded size */ | ||
100 | 10 | length_size = (bytestream2_get_byteu(gb) & 0x3) + 1; | |
101 | |||
102 | /* retrieve sps and pps unit(s) */ | ||
103 | 10 | unit_nb = bytestream2_get_byteu(gb) & 0x1f; /* number of sps unit(s) */ | |
104 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (!unit_nb) { |
105 | ✗ | goto pps; | |
106 | } | ||
107 | |||
108 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 10 times.
|
30 | while (unit_nb--) { |
109 | int err; | ||
110 | |||
111 | /* possible overread ok due to padding */ | ||
112 | 20 | unit_size = bytestream2_get_be16u(gb); | |
113 | 20 | total_size += unit_size + 4; | |
114 | av_assert1(total_size <= INT_MAX - padding); | ||
115 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
|
20 | if (bytestream2_get_bytes_left(gb) < unit_size + !sps_done) { |
116 | ✗ | av_log(ctx, AV_LOG_ERROR, "Global extradata truncated, " | |
117 | "corrupted stream or invalid MP4/AVCC bitstream\n"); | ||
118 | ✗ | av_free(out); | |
119 | ✗ | return AVERROR_INVALIDDATA; | |
120 | } | ||
121 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
|
20 | if ((err = av_reallocp(&out, total_size + padding)) < 0) |
122 | ✗ | return err; | |
123 | 20 | memcpy(out + total_size - unit_size - 4, nalu_header, 4); | |
124 | 20 | bytestream2_get_bufferu(gb, out + total_size - unit_size, unit_size); | |
125 | 20 | pps: | |
126 |
3/4✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 10 times.
|
20 | if (!unit_nb && !sps_done++) { |
127 | 10 | unit_nb = bytestream2_get_byteu(gb); /* number of pps unit(s) */ | |
128 | 10 | pps_offset = total_size; | |
129 | } | ||
130 | } | ||
131 | |||
132 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | if (out) |
133 | 10 | memset(out + total_size, 0, padding); | |
134 | |||
135 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | if (pps_offset) { |
136 | uint8_t *sps; | ||
137 | |||
138 | 10 | s->sps_size = pps_offset; | |
139 | 10 | sps = av_fast_realloc(s->sps, &s->sps_buf_size, s->sps_size); | |
140 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (!sps) { |
141 | ✗ | av_free(out); | |
142 | ✗ | return AVERROR(ENOMEM); | |
143 | } | ||
144 | 10 | s->sps = sps; | |
145 | 10 | memcpy(s->sps, out, s->sps_size); | |
146 | } else { | ||
147 | ✗ | av_log(ctx, AV_LOG_WARNING, | |
148 | "Warning: SPS NALU missing or invalid. " | ||
149 | "The resulting stream may not play.\n"); | ||
150 | } | ||
151 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | if (pps_offset < total_size) { |
152 | uint8_t *pps; | ||
153 | |||
154 | 10 | s->pps_size = total_size - pps_offset; | |
155 | 10 | pps = av_fast_realloc(s->pps, &s->pps_buf_size, s->pps_size); | |
156 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (!pps) { |
157 | ✗ | av_freep(&s->sps); | |
158 | ✗ | av_free(out); | |
159 | ✗ | return AVERROR(ENOMEM); | |
160 | } | ||
161 | 10 | s->pps = pps; | |
162 | 10 | memcpy(s->pps, out + pps_offset, s->pps_size); | |
163 | } else { | ||
164 | ✗ | av_log(ctx, AV_LOG_WARNING, | |
165 | "Warning: PPS NALU missing or invalid. " | ||
166 | "The resulting stream may not play.\n"); | ||
167 | } | ||
168 | |||
169 | 10 | av_freep(&ctx->par_out->extradata); | |
170 | 10 | ctx->par_out->extradata = out; | |
171 | 10 | ctx->par_out->extradata_size = total_size; | |
172 | |||
173 | 10 | s->length_size = length_size; | |
174 | 10 | s->new_idr = 1; | |
175 | 10 | s->idr_sps_seen = 0; | |
176 | 10 | s->idr_pps_seen = 0; | |
177 | 10 | s->extradata_parsed = 1; | |
178 | |||
179 | 10 | return 0; | |
180 | } | ||
181 | |||
182 | 2 | static int h264_mp4toannexb_save_ps(uint8_t **dst, int *dst_size, | |
183 | unsigned *dst_buf_size, | ||
184 | const uint8_t *nal, uint32_t nal_size, | ||
185 | int first) | ||
186 | { | ||
187 | static const uint8_t nalu_header[4] = { 0, 0, 0, 1 }; | ||
188 | 2 | const int start_code_size = sizeof(nalu_header); | |
189 | uint8_t *ptr; | ||
190 | uint32_t size; | ||
191 | |||
192 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (first) |
193 | 2 | size = 0; | |
194 | else | ||
195 | ✗ | size = *dst_size; | |
196 | |||
197 | 2 | ptr = av_fast_realloc(*dst, dst_buf_size, size + nal_size + start_code_size); | |
198 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (!ptr) |
199 | ✗ | return AVERROR(ENOMEM); | |
200 | |||
201 | 2 | memcpy(ptr + size, nalu_header, start_code_size); | |
202 | 2 | size += start_code_size; | |
203 | 2 | memcpy(ptr + size, nal, nal_size); | |
204 | 2 | size += nal_size; | |
205 | |||
206 | 2 | *dst = ptr; | |
207 | 2 | *dst_size = size; | |
208 | 2 | return 0; | |
209 | } | ||
210 | |||
211 | 412 | static int h264_mp4toannexb_filter_ps(H264BSFContext *s, | |
212 | const uint8_t *buf, | ||
213 | const uint8_t *buf_end) | ||
214 | { | ||
215 | 412 | int sps_count = 0; | |
216 | 412 | int pps_count = 0; | |
217 | uint8_t unit_type; | ||
218 | |||
219 | do { | ||
220 | 1760 | uint32_t nal_size = 0; | |
221 | |||
222 | /* possible overread ok due to padding */ | ||
223 |
2/2✓ Branch 0 taken 7040 times.
✓ Branch 1 taken 1760 times.
|
8800 | for (int i = 0; i < s->length_size; i++) |
224 | 7040 | nal_size = (nal_size << 8) | buf[i]; | |
225 | |||
226 | 1760 | buf += s->length_size; | |
227 | |||
228 | /* This check requires the cast as the right side might | ||
229 | * otherwise be promoted to an unsigned value. */ | ||
230 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1759 times.
|
1760 | if ((int64_t)nal_size > buf_end - buf) |
231 | 1 | return AVERROR_INVALIDDATA; | |
232 | |||
233 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1759 times.
|
1759 | if (!nal_size) |
234 | ✗ | continue; | |
235 | |||
236 | 1759 | unit_type = *buf & 0x1f; | |
237 | |||
238 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1758 times.
|
1759 | if (unit_type == H264_NAL_SPS) { |
239 | 1 | h264_mp4toannexb_save_ps(&s->sps, &s->sps_size, &s->sps_buf_size, buf, | |
240 | nal_size, !sps_count); | ||
241 | 1 | sps_count++; | |
242 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1757 times.
|
1758 | } else if (unit_type == H264_NAL_PPS) { |
243 | 1 | h264_mp4toannexb_save_ps(&s->pps, &s->pps_size, &s->pps_buf_size, buf, | |
244 | nal_size, !pps_count); | ||
245 | 1 | pps_count++; | |
246 | } | ||
247 | |||
248 | 1759 | buf += nal_size; | |
249 |
2/2✓ Branch 0 taken 1348 times.
✓ Branch 1 taken 411 times.
|
1759 | } while (buf < buf_end); |
250 | |||
251 | 411 | return 0; | |
252 | } | ||
253 | |||
254 | 7 | static int h264_mp4toannexb_init(AVBSFContext *ctx) | |
255 | { | ||
256 | 7 | int extra_size = ctx->par_in->extradata_size; | |
257 | |||
258 | /* retrieve sps and pps NAL units from extradata */ | ||
259 |
2/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | if (!extra_size || |
260 |
2/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | (extra_size >= 3 && AV_RB24(ctx->par_in->extradata) == 1) || |
261 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | (extra_size >= 4 && AV_RB32(ctx->par_in->extradata) == 1)) { |
262 | ✗ | av_log(ctx, AV_LOG_VERBOSE, | |
263 | "The input looks like it is Annex B already\n"); | ||
264 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | } else if (extra_size >= 7) { |
265 | 7 | return h264_extradata_to_annexb(ctx, | |
266 | 7 | ctx->par_in->extradata, | |
267 | 7 | ctx->par_in->extradata_size); | |
268 | } else { | ||
269 | ✗ | av_log(ctx, AV_LOG_ERROR, "Invalid extradata size: %d\n", extra_size); | |
270 | ✗ | return AVERROR_INVALIDDATA; | |
271 | } | ||
272 | |||
273 | ✗ | return 0; | |
274 | } | ||
275 | |||
276 | 831 | static int h264_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *opkt) | |
277 | { | ||
278 | 831 | H264BSFContext *s = ctx->priv_data; | |
279 | AVPacket *in; | ||
280 | uint8_t unit_type, new_idr, sps_seen, pps_seen; | ||
281 | const uint8_t *buf; | ||
282 | const uint8_t *buf_end; | ||
283 | uint8_t *out; | ||
284 | uint64_t out_size; | ||
285 | int ret; | ||
286 | size_t extradata_size; | ||
287 | uint8_t *extradata; | ||
288 | |||
289 | 831 | ret = ff_bsf_get_packet(ctx, &in); | |
290 |
2/2✓ Branch 0 taken 419 times.
✓ Branch 1 taken 412 times.
|
831 | if (ret < 0) |
291 | 419 | return ret; | |
292 | |||
293 | 412 | extradata = av_packet_get_side_data(in, AV_PKT_DATA_NEW_EXTRADATA, | |
294 | &extradata_size); | ||
295 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 409 times.
|
412 | if (extradata) { |
296 | 3 | ret = h264_extradata_to_annexb(ctx, extradata, extradata_size); | |
297 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (ret < 0) |
298 | ✗ | goto fail; | |
299 | } | ||
300 | |||
301 | /* nothing to filter */ | ||
302 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 412 times.
|
412 | if (!s->extradata_parsed) { |
303 | ✗ | av_packet_move_ref(opkt, in); | |
304 | ✗ | av_packet_free(&in); | |
305 | ✗ | return 0; | |
306 | } | ||
307 | |||
308 | 412 | buf_end = in->data + in->size; | |
309 | 412 | ret = h264_mp4toannexb_filter_ps(s, in->data, buf_end); | |
310 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 411 times.
|
412 | if (ret < 0) |
311 | 1 | goto fail; | |
312 | |||
313 | #define LOG_ONCE(...) \ | ||
314 | if (j) \ | ||
315 | av_log(__VA_ARGS__) | ||
316 |
2/2✓ Branch 0 taken 822 times.
✓ Branch 1 taken 411 times.
|
1233 | for (int j = 0; j < 2; j++) { |
317 | 822 | buf = in->data; | |
318 | 822 | new_idr = s->new_idr; | |
319 | 822 | sps_seen = s->idr_sps_seen; | |
320 | 822 | pps_seen = s->idr_pps_seen; | |
321 | 822 | out_size = 0; | |
322 | |||
323 | do { | ||
324 | 3510 | uint32_t nal_size = 0; | |
325 | enum PsSource ps; | ||
326 | |||
327 | /* possible overread ok due to padding */ | ||
328 |
2/2✓ Branch 0 taken 14040 times.
✓ Branch 1 taken 3510 times.
|
17550 | for (int i = 0; i < s->length_size; i++) |
329 | 14040 | nal_size = (nal_size << 8) | buf[i]; | |
330 | |||
331 | 3510 | buf += s->length_size; | |
332 | |||
333 | /* This check requires the cast as the right side might | ||
334 | * otherwise be promoted to an unsigned value. */ | ||
335 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3510 times.
|
3510 | if ((int64_t)nal_size > buf_end - buf) { |
336 | ✗ | ret = AVERROR_INVALIDDATA; | |
337 | ✗ | goto fail; | |
338 | } | ||
339 | |||
340 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3510 times.
|
3510 | if (!nal_size) |
341 | ✗ | continue; | |
342 | |||
343 | 3510 | unit_type = *buf & 0x1f; | |
344 | |||
345 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3508 times.
|
3510 | if (unit_type == H264_NAL_SPS) { |
346 | 2 | sps_seen = new_idr = 1; | |
347 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3506 times.
|
3508 | } else if (unit_type == H264_NAL_PPS) { |
348 | 2 | pps_seen = new_idr = 1; | |
349 | /* if SPS has not been seen yet, prepend the AVCC one to PPS */ | ||
350 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (!sps_seen) { |
351 | ✗ | if (!s->sps_size) { | |
352 | ✗ | LOG_ONCE(ctx, AV_LOG_WARNING, "SPS not present in the stream, nor in AVCC, stream may be unreadable\n"); | |
353 | } else { | ||
354 | ✗ | count_or_copy(&out, &out_size, s->sps, s->sps_size, PS_OUT_OF_BAND, j); | |
355 | ✗ | sps_seen = 1; | |
356 | } | ||
357 | } | ||
358 | } | ||
359 | |||
360 | /* If this is a new IDR picture following an IDR picture, reset the idr flag. | ||
361 | * Just check first_mb_in_slice to be 0 as this is the simplest solution. | ||
362 | * This could be checking idr_pic_id instead, but would complexify the parsing. */ | ||
363 |
5/6✓ Branch 0 taken 178 times.
✓ Branch 1 taken 3332 times.
✓ Branch 2 taken 104 times.
✓ Branch 3 taken 74 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 104 times.
|
3510 | if (!new_idr && unit_type == H264_NAL_IDR_SLICE && (buf[1] & 0x80)) |
364 | ✗ | new_idr = 1; | |
365 | |||
366 | /* prepend only to the first type 5 NAL unit of an IDR picture, if no sps/pps are already present */ | ||
367 |
7/8✓ Branch 0 taken 3332 times.
✓ Branch 1 taken 178 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 3296 times.
✓ Branch 4 taken 34 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 34 times.
✗ Branch 7 not taken.
|
3510 | if (new_idr && unit_type == H264_NAL_IDR_SLICE && !sps_seen && !pps_seen) { |
368 |
1/2✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
|
34 | if (s->sps_size) |
369 | 34 | count_or_copy(&out, &out_size, s->sps, s->sps_size, PS_OUT_OF_BAND, j); | |
370 |
1/2✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
|
34 | if (s->pps_size) |
371 | 34 | count_or_copy(&out, &out_size, s->pps, s->pps_size, PS_OUT_OF_BAND, j); | |
372 | 34 | new_idr = 0; | |
373 | /* if only SPS has been seen, also insert PPS */ | ||
374 |
6/8✓ Branch 0 taken 3298 times.
✓ Branch 1 taken 178 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3296 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
|
3476 | } else if (new_idr && unit_type == H264_NAL_IDR_SLICE && sps_seen && !pps_seen) { |
375 | ✗ | if (!s->pps_size) { | |
376 | ✗ | LOG_ONCE(ctx, AV_LOG_WARNING, "PPS not present in the stream, nor in AVCC, stream may be unreadable\n"); | |
377 | } else { | ||
378 | ✗ | count_or_copy(&out, &out_size, s->pps, s->pps_size, PS_OUT_OF_BAND, j); | |
379 | } | ||
380 | } | ||
381 | |||
382 |
4/4✓ Branch 0 taken 3508 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3506 times.
|
3510 | if (unit_type == H264_NAL_SPS || unit_type == H264_NAL_PPS) |
383 | 4 | ps = PS_IN_BAND; | |
384 | else | ||
385 | 3506 | ps = PS_NONE; | |
386 | 3510 | count_or_copy(&out, &out_size, buf, nal_size, ps, j); | |
387 |
2/2✓ Branch 0 taken 1760 times.
✓ Branch 1 taken 1750 times.
|
3510 | if (unit_type == H264_NAL_SLICE) { |
388 | 1760 | new_idr = 1; | |
389 | 1760 | sps_seen = 0; | |
390 | 1760 | pps_seen = 0; | |
391 | } | ||
392 | |||
393 | 3510 | buf += nal_size; | |
394 |
2/2✓ Branch 0 taken 2688 times.
✓ Branch 1 taken 822 times.
|
3510 | } while (buf < buf_end); |
395 | |||
396 |
2/2✓ Branch 0 taken 411 times.
✓ Branch 1 taken 411 times.
|
822 | if (!j) { |
397 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 411 times.
|
411 | if (out_size > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE) { |
398 | ✗ | ret = AVERROR_INVALIDDATA; | |
399 | ✗ | goto fail; | |
400 | } | ||
401 | 411 | ret = av_new_packet(opkt, out_size); | |
402 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 411 times.
|
411 | if (ret < 0) |
403 | ✗ | goto fail; | |
404 | 411 | out = opkt->data; | |
405 | } | ||
406 | } | ||
407 | #undef LOG_ONCE | ||
408 | |||
409 | av_assert1(out_size == opkt->size); | ||
410 | |||
411 | 411 | s->new_idr = new_idr; | |
412 | 411 | s->idr_sps_seen = sps_seen; | |
413 | 411 | s->idr_pps_seen = pps_seen; | |
414 | |||
415 | 411 | ret = av_packet_copy_props(opkt, in); | |
416 |
1/2✓ Branch 0 taken 411 times.
✗ Branch 1 not taken.
|
411 | if (ret < 0) |
417 | ✗ | goto fail; | |
418 | |||
419 | 411 | fail: | |
420 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 411 times.
|
412 | if (ret < 0) |
421 | 1 | av_packet_unref(opkt); | |
422 | 412 | av_packet_free(&in); | |
423 | |||
424 | 412 | return ret; | |
425 | } | ||
426 | |||
427 | 7 | static void h264_mp4toannexb_close(AVBSFContext *ctx) | |
428 | { | ||
429 | 7 | H264BSFContext *s = ctx->priv_data; | |
430 | |||
431 | 7 | av_freep(&s->sps); | |
432 | 7 | av_freep(&s->pps); | |
433 | 7 | } | |
434 | |||
435 | ✗ | static void h264_mp4toannexb_flush(AVBSFContext *ctx) | |
436 | { | ||
437 | ✗ | H264BSFContext *s = ctx->priv_data; | |
438 | |||
439 | ✗ | s->idr_sps_seen = 0; | |
440 | ✗ | s->idr_pps_seen = 0; | |
441 | ✗ | s->new_idr = s->extradata_parsed; | |
442 | ✗ | } | |
443 | |||
444 | static const enum AVCodecID codec_ids[] = { | ||
445 | AV_CODEC_ID_H264, AV_CODEC_ID_NONE, | ||
446 | }; | ||
447 | |||
448 | const FFBitStreamFilter ff_h264_mp4toannexb_bsf = { | ||
449 | .p.name = "h264_mp4toannexb", | ||
450 | .p.codec_ids = codec_ids, | ||
451 | .priv_data_size = sizeof(H264BSFContext), | ||
452 | .init = h264_mp4toannexb_init, | ||
453 | .filter = h264_mp4toannexb_filter, | ||
454 | .close = h264_mp4toannexb_close, | ||
455 | .flush = h264_mp4toannexb_flush, | ||
456 | }; | ||
457 |