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