1 /*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include <string.h>
20
21 #include "config.h"
22
23 #include "libavutil/avassert.h"
24 #include "libavutil/buffer.h"
25 #include "libavutil/common.h"
26
27 #include "cbs.h"
28 #include "cbs_internal.h"
29
30
31 static const CodedBitstreamType *cbs_type_table[] = {
32 #if CONFIG_CBS_AV1
33 &ff_cbs_type_av1,
34 #endif
35 #if CONFIG_CBS_H264
36 &ff_cbs_type_h264,
37 #endif
38 #if CONFIG_CBS_H265
39 &ff_cbs_type_h265,
40 #endif
41 #if CONFIG_CBS_JPEG
42 &ff_cbs_type_jpeg,
43 #endif
44 #if CONFIG_CBS_MPEG2
45 &ff_cbs_type_mpeg2,
46 #endif
47 #if CONFIG_CBS_VP9
48 &ff_cbs_type_vp9,
49 #endif
50 };
51
52 const enum AVCodecID ff_cbs_all_codec_ids[] = {
53 #if CONFIG_CBS_AV1
54 AV_CODEC_ID_AV1,
55 #endif
56 #if CONFIG_CBS_H264
57 AV_CODEC_ID_H264,
58 #endif
59 #if CONFIG_CBS_H265
60 AV_CODEC_ID_H265,
61 #endif
62 #if CONFIG_CBS_JPEG
63 AV_CODEC_ID_MJPEG,
64 #endif
65 #if CONFIG_CBS_MPEG2
66 AV_CODEC_ID_MPEG2VIDEO,
67 #endif
68 #if CONFIG_CBS_VP9
69 AV_CODEC_ID_VP9,
70 #endif
71 AV_CODEC_ID_NONE
72 };
73
ff_cbs_init(CodedBitstreamContext ** ctx_ptr,enum AVCodecID codec_id,void * log_ctx)74 int ff_cbs_init(CodedBitstreamContext **ctx_ptr,
75 enum AVCodecID codec_id, void *log_ctx)
76 {
77 CodedBitstreamContext *ctx;
78 const CodedBitstreamType *type;
79 int i;
80
81 type = NULL;
82 for (i = 0; i < FF_ARRAY_ELEMS(cbs_type_table); i++) {
83 if (cbs_type_table[i]->codec_id == codec_id) {
84 type = cbs_type_table[i];
85 break;
86 }
87 }
88 if (!type)
89 return AVERROR(EINVAL);
90
91 ctx = av_mallocz(sizeof(*ctx));
92 if (!ctx)
93 return AVERROR(ENOMEM);
94
95 ctx->log_ctx = log_ctx;
96 ctx->codec = type;
97
98 if (type->priv_data_size) {
99 ctx->priv_data = av_mallocz(ctx->codec->priv_data_size);
100 if (!ctx->priv_data) {
101 av_freep(&ctx);
102 return AVERROR(ENOMEM);
103 }
104 }
105
106 ctx->decompose_unit_types = NULL;
107
108 ctx->trace_enable = 0;
109 ctx->trace_level = AV_LOG_TRACE;
110
111 *ctx_ptr = ctx;
112 return 0;
113 }
114
ff_cbs_close(CodedBitstreamContext ** ctx_ptr)115 void ff_cbs_close(CodedBitstreamContext **ctx_ptr)
116 {
117 CodedBitstreamContext *ctx = *ctx_ptr;
118
119 if (!ctx)
120 return;
121
122 if (ctx->codec && ctx->codec->close)
123 ctx->codec->close(ctx);
124
125 av_freep(&ctx->write_buffer);
126 av_freep(&ctx->priv_data);
127 av_freep(ctx_ptr);
128 }
129
cbs_unit_uninit(CodedBitstreamContext * ctx,CodedBitstreamUnit * unit)130 static void cbs_unit_uninit(CodedBitstreamContext *ctx,
131 CodedBitstreamUnit *unit)
132 {
133 av_buffer_unref(&unit->content_ref);
134 unit->content = NULL;
135
136 av_buffer_unref(&unit->data_ref);
137 unit->data = NULL;
138 unit->data_size = 0;
139 unit->data_bit_padding = 0;
140 }
141
ff_cbs_fragment_reset(CodedBitstreamContext * ctx,CodedBitstreamFragment * frag)142 void ff_cbs_fragment_reset(CodedBitstreamContext *ctx,
143 CodedBitstreamFragment *frag)
144 {
145 int i;
146
147 for (i = 0; i < frag->nb_units; i++)
148 cbs_unit_uninit(ctx, &frag->units[i]);
149 frag->nb_units = 0;
150
151 av_buffer_unref(&frag->data_ref);
152 frag->data = NULL;
153 frag->data_size = 0;
154 frag->data_bit_padding = 0;
155 }
156
ff_cbs_fragment_free(CodedBitstreamContext * ctx,CodedBitstreamFragment * frag)157 void ff_cbs_fragment_free(CodedBitstreamContext *ctx,
158 CodedBitstreamFragment *frag)
159 {
160 ff_cbs_fragment_reset(ctx, frag);
161
162 av_freep(&frag->units);
163 frag->nb_units_allocated = 0;
164 }
165
cbs_read_fragment_content(CodedBitstreamContext * ctx,CodedBitstreamFragment * frag)166 static int cbs_read_fragment_content(CodedBitstreamContext *ctx,
167 CodedBitstreamFragment *frag)
168 {
169 int err, i, j;
170
171 for (i = 0; i < frag->nb_units; i++) {
172 CodedBitstreamUnit *unit = &frag->units[i];
173
174 if (ctx->decompose_unit_types) {
175 for (j = 0; j < ctx->nb_decompose_unit_types; j++) {
176 if (ctx->decompose_unit_types[j] == unit->type)
177 break;
178 }
179 if (j >= ctx->nb_decompose_unit_types)
180 continue;
181 }
182
183 av_buffer_unref(&unit->content_ref);
184 unit->content = NULL;
185
186 av_assert0(unit->data && unit->data_ref);
187
188 err = ctx->codec->read_unit(ctx, unit);
189 if (err == AVERROR(ENOSYS)) {
190 av_log(ctx->log_ctx, AV_LOG_VERBOSE,
191 "Decomposition unimplemented for unit %d "
192 "(type %"PRIu32").\n", i, unit->type);
193 } else if (err < 0) {
194 av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to read unit %d "
195 "(type %"PRIu32").\n", i, unit->type);
196 return err;
197 }
198 }
199
200 return 0;
201 }
202
cbs_fill_fragment_data(CodedBitstreamContext * ctx,CodedBitstreamFragment * frag,const uint8_t * data,size_t size)203 static int cbs_fill_fragment_data(CodedBitstreamContext *ctx,
204 CodedBitstreamFragment *frag,
205 const uint8_t *data, size_t size)
206 {
207 av_assert0(!frag->data && !frag->data_ref);
208
209 frag->data_ref =
210 av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
211 if (!frag->data_ref)
212 return AVERROR(ENOMEM);
213
214 frag->data = frag->data_ref->data;
215 frag->data_size = size;
216
217 memcpy(frag->data, data, size);
218 memset(frag->data + size, 0,
219 AV_INPUT_BUFFER_PADDING_SIZE);
220
221 return 0;
222 }
223
ff_cbs_read_extradata(CodedBitstreamContext * ctx,CodedBitstreamFragment * frag,const AVCodecParameters * par)224 int ff_cbs_read_extradata(CodedBitstreamContext *ctx,
225 CodedBitstreamFragment *frag,
226 const AVCodecParameters *par)
227 {
228 int err;
229
230 err = cbs_fill_fragment_data(ctx, frag, par->extradata,
231 par->extradata_size);
232 if (err < 0)
233 return err;
234
235 err = ctx->codec->split_fragment(ctx, frag, 1);
236 if (err < 0)
237 return err;
238
239 return cbs_read_fragment_content(ctx, frag);
240 }
241
ff_cbs_read_packet(CodedBitstreamContext * ctx,CodedBitstreamFragment * frag,const AVPacket * pkt)242 int ff_cbs_read_packet(CodedBitstreamContext *ctx,
243 CodedBitstreamFragment *frag,
244 const AVPacket *pkt)
245 {
246 int err;
247
248 if (pkt->buf) {
249 frag->data_ref = av_buffer_ref(pkt->buf);
250 if (!frag->data_ref)
251 return AVERROR(ENOMEM);
252
253 frag->data = pkt->data;
254 frag->data_size = pkt->size;
255
256 } else {
257 err = cbs_fill_fragment_data(ctx, frag, pkt->data, pkt->size);
258 if (err < 0)
259 return err;
260 }
261
262 err = ctx->codec->split_fragment(ctx, frag, 0);
263 if (err < 0)
264 return err;
265
266 return cbs_read_fragment_content(ctx, frag);
267 }
268
ff_cbs_read(CodedBitstreamContext * ctx,CodedBitstreamFragment * frag,const uint8_t * data,size_t size)269 int ff_cbs_read(CodedBitstreamContext *ctx,
270 CodedBitstreamFragment *frag,
271 const uint8_t *data, size_t size)
272 {
273 int err;
274
275 err = cbs_fill_fragment_data(ctx, frag, data, size);
276 if (err < 0)
277 return err;
278
279 err = ctx->codec->split_fragment(ctx, frag, 0);
280 if (err < 0)
281 return err;
282
283 return cbs_read_fragment_content(ctx, frag);
284 }
285
cbs_write_unit_data(CodedBitstreamContext * ctx,CodedBitstreamUnit * unit)286 static int cbs_write_unit_data(CodedBitstreamContext *ctx,
287 CodedBitstreamUnit *unit)
288 {
289 PutBitContext pbc;
290 int ret;
291
292 if (!ctx->write_buffer) {
293 // Initial write buffer size is 1MB.
294 ctx->write_buffer_size = 1024 * 1024;
295
296 reallocate_and_try_again:
297 ret = av_reallocp(&ctx->write_buffer, ctx->write_buffer_size);
298 if (ret < 0) {
299 av_log(ctx->log_ctx, AV_LOG_ERROR, "Unable to allocate a "
300 "sufficiently large write buffer (last attempt "
301 "%"SIZE_SPECIFIER" bytes).\n", ctx->write_buffer_size);
302 return ret;
303 }
304 }
305
306 init_put_bits(&pbc, ctx->write_buffer, ctx->write_buffer_size);
307
308 ret = ctx->codec->write_unit(ctx, unit, &pbc);
309 if (ret < 0) {
310 if (ret == AVERROR(ENOSPC)) {
311 // Overflow.
312 if (ctx->write_buffer_size == INT_MAX / 8)
313 return AVERROR(ENOMEM);
314 ctx->write_buffer_size = FFMIN(2 * ctx->write_buffer_size, INT_MAX / 8);
315 goto reallocate_and_try_again;
316 }
317 // Write failed for some other reason.
318 return ret;
319 }
320
321 // Overflow but we didn't notice.
322 av_assert0(put_bits_count(&pbc) <= 8 * ctx->write_buffer_size);
323
324 if (put_bits_count(&pbc) % 8)
325 unit->data_bit_padding = 8 - put_bits_count(&pbc) % 8;
326 else
327 unit->data_bit_padding = 0;
328
329 flush_put_bits(&pbc);
330
331 ret = ff_cbs_alloc_unit_data(ctx, unit, put_bits_count(&pbc) / 8);
332 if (ret < 0)
333 return ret;
334
335 memcpy(unit->data, ctx->write_buffer, unit->data_size);
336
337 return 0;
338 }
339
ff_cbs_write_fragment_data(CodedBitstreamContext * ctx,CodedBitstreamFragment * frag)340 int ff_cbs_write_fragment_data(CodedBitstreamContext *ctx,
341 CodedBitstreamFragment *frag)
342 {
343 int err, i;
344
345 for (i = 0; i < frag->nb_units; i++) {
346 CodedBitstreamUnit *unit = &frag->units[i];
347
348 if (!unit->content)
349 continue;
350
351 av_buffer_unref(&unit->data_ref);
352 unit->data = NULL;
353
354 err = cbs_write_unit_data(ctx, unit);
355 if (err < 0) {
356 av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to write unit %d "
357 "(type %"PRIu32").\n", i, unit->type);
358 return err;
359 }
360 av_assert0(unit->data && unit->data_ref);
361 }
362
363 av_buffer_unref(&frag->data_ref);
364 frag->data = NULL;
365
366 err = ctx->codec->assemble_fragment(ctx, frag);
367 if (err < 0) {
368 av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to assemble fragment.\n");
369 return err;
370 }
371 av_assert0(frag->data && frag->data_ref);
372
373 return 0;
374 }
375
ff_cbs_write_extradata(CodedBitstreamContext * ctx,AVCodecParameters * par,CodedBitstreamFragment * frag)376 int ff_cbs_write_extradata(CodedBitstreamContext *ctx,
377 AVCodecParameters *par,
378 CodedBitstreamFragment *frag)
379 {
380 int err;
381
382 err = ff_cbs_write_fragment_data(ctx, frag);
383 if (err < 0)
384 return err;
385
386 av_freep(&par->extradata);
387
388 par->extradata = av_malloc(frag->data_size +
389 AV_INPUT_BUFFER_PADDING_SIZE);
390 if (!par->extradata)
391 return AVERROR(ENOMEM);
392
393 memcpy(par->extradata, frag->data, frag->data_size);
394 memset(par->extradata + frag->data_size, 0,
395 AV_INPUT_BUFFER_PADDING_SIZE);
396 par->extradata_size = frag->data_size;
397
398 return 0;
399 }
400
ff_cbs_write_packet(CodedBitstreamContext * ctx,AVPacket * pkt,CodedBitstreamFragment * frag)401 int ff_cbs_write_packet(CodedBitstreamContext *ctx,
402 AVPacket *pkt,
403 CodedBitstreamFragment *frag)
404 {
405 AVBufferRef *buf;
406 int err;
407
408 err = ff_cbs_write_fragment_data(ctx, frag);
409 if (err < 0)
410 return err;
411
412 buf = av_buffer_ref(frag->data_ref);
413 if (!buf)
414 return AVERROR(ENOMEM);
415
416 av_buffer_unref(&pkt->buf);
417
418 pkt->buf = buf;
419 pkt->data = frag->data;
420 pkt->size = frag->data_size;
421
422 return 0;
423 }
424
425
ff_cbs_trace_header(CodedBitstreamContext * ctx,const char * name)426 void ff_cbs_trace_header(CodedBitstreamContext *ctx,
427 const char *name)
428 {
429 if (!ctx->trace_enable)
430 return;
431
432 av_log(ctx->log_ctx, ctx->trace_level, "%s\n", name);
433 }
434
ff_cbs_trace_syntax_element(CodedBitstreamContext * ctx,int position,const char * str,const int * subscripts,const char * bits,int64_t value)435 void ff_cbs_trace_syntax_element(CodedBitstreamContext *ctx, int position,
436 const char *str, const int *subscripts,
437 const char *bits, int64_t value)
438 {
439 char name[256];
440 size_t name_len, bits_len;
441 int pad, subs, i, j, k, n;
442
443 if (!ctx->trace_enable)
444 return;
445
446 av_assert0(value >= INT_MIN && value <= UINT32_MAX);
447
448 subs = subscripts ? subscripts[0] : 0;
449 n = 0;
450 for (i = j = 0; str[i];) {
451 if (str[i] == '[') {
452 if (n < subs) {
453 ++n;
454 k = snprintf(name + j, sizeof(name) - j, "[%d", subscripts[n]);
455 av_assert0(k > 0 && j + k < sizeof(name));
456 j += k;
457 for (++i; str[i] && str[i] != ']'; i++);
458 av_assert0(str[i] == ']');
459 } else {
460 while (str[i] && str[i] != ']')
461 name[j++] = str[i++];
462 av_assert0(str[i] == ']');
463 }
464 } else {
465 av_assert0(j + 1 < sizeof(name));
466 name[j++] = str[i++];
467 }
468 }
469 av_assert0(j + 1 < sizeof(name));
470 name[j] = 0;
471 av_assert0(n == subs);
472
473 name_len = strlen(name);
474 bits_len = strlen(bits);
475
476 if (name_len + bits_len > 60)
477 pad = bits_len + 2;
478 else
479 pad = 61 - name_len;
480
481 av_log(ctx->log_ctx, ctx->trace_level, "%-10d %s%*s = %"PRId64"\n",
482 position, name, pad, bits, value);
483 }
484
ff_cbs_read_unsigned(CodedBitstreamContext * ctx,GetBitContext * gbc,int width,const char * name,const int * subscripts,uint32_t * write_to,uint32_t range_min,uint32_t range_max)485 int ff_cbs_read_unsigned(CodedBitstreamContext *ctx, GetBitContext *gbc,
486 int width, const char *name,
487 const int *subscripts, uint32_t *write_to,
488 uint32_t range_min, uint32_t range_max)
489 {
490 uint32_t value;
491 int position;
492
493 av_assert0(width > 0 && width <= 32);
494
495 if (get_bits_left(gbc) < width) {
496 av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid value at "
497 "%s: bitstream ended.\n", name);
498 return AVERROR_INVALIDDATA;
499 }
500
501 if (ctx->trace_enable)
502 position = get_bits_count(gbc);
503
504 value = get_bits_long(gbc, width);
505
506 if (ctx->trace_enable) {
507 char bits[33];
508 int i;
509 for (i = 0; i < width; i++)
510 bits[i] = value >> (width - i - 1) & 1 ? '1' : '0';
511 bits[i] = 0;
512
513 ff_cbs_trace_syntax_element(ctx, position, name, subscripts,
514 bits, value);
515 }
516
517 if (value < range_min || value > range_max) {
518 av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
519 "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n",
520 name, value, range_min, range_max);
521 return AVERROR_INVALIDDATA;
522 }
523
524 *write_to = value;
525 return 0;
526 }
527
ff_cbs_write_unsigned(CodedBitstreamContext * ctx,PutBitContext * pbc,int width,const char * name,const int * subscripts,uint32_t value,uint32_t range_min,uint32_t range_max)528 int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc,
529 int width, const char *name,
530 const int *subscripts, uint32_t value,
531 uint32_t range_min, uint32_t range_max)
532 {
533 av_assert0(width > 0 && width <= 32);
534
535 if (value < range_min || value > range_max) {
536 av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
537 "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n",
538 name, value, range_min, range_max);
539 return AVERROR_INVALIDDATA;
540 }
541
542 if (put_bits_left(pbc) < width)
543 return AVERROR(ENOSPC);
544
545 if (ctx->trace_enable) {
546 char bits[33];
547 int i;
548 for (i = 0; i < width; i++)
549 bits[i] = value >> (width - i - 1) & 1 ? '1' : '0';
550 bits[i] = 0;
551
552 ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc),
553 name, subscripts, bits, value);
554 }
555
556 if (width < 32)
557 put_bits(pbc, width, value);
558 else
559 put_bits32(pbc, value);
560
561 return 0;
562 }
563
ff_cbs_read_signed(CodedBitstreamContext * ctx,GetBitContext * gbc,int width,const char * name,const int * subscripts,int32_t * write_to,int32_t range_min,int32_t range_max)564 int ff_cbs_read_signed(CodedBitstreamContext *ctx, GetBitContext *gbc,
565 int width, const char *name,
566 const int *subscripts, int32_t *write_to,
567 int32_t range_min, int32_t range_max)
568 {
569 int32_t value;
570 int position;
571
572 av_assert0(width > 0 && width <= 32);
573
574 if (get_bits_left(gbc) < width) {
575 av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid value at "
576 "%s: bitstream ended.\n", name);
577 return AVERROR_INVALIDDATA;
578 }
579
580 if (ctx->trace_enable)
581 position = get_bits_count(gbc);
582
583 value = get_sbits_long(gbc, width);
584
585 if (ctx->trace_enable) {
586 char bits[33];
587 int i;
588 for (i = 0; i < width; i++)
589 bits[i] = value & (1U << (width - i - 1)) ? '1' : '0';
590 bits[i] = 0;
591
592 ff_cbs_trace_syntax_element(ctx, position, name, subscripts,
593 bits, value);
594 }
595
596 if (value < range_min || value > range_max) {
597 av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
598 "%"PRId32", but must be in [%"PRId32",%"PRId32"].\n",
599 name, value, range_min, range_max);
600 return AVERROR_INVALIDDATA;
601 }
602
603 *write_to = value;
604 return 0;
605 }
606
ff_cbs_write_signed(CodedBitstreamContext * ctx,PutBitContext * pbc,int width,const char * name,const int * subscripts,int32_t value,int32_t range_min,int32_t range_max)607 int ff_cbs_write_signed(CodedBitstreamContext *ctx, PutBitContext *pbc,
608 int width, const char *name,
609 const int *subscripts, int32_t value,
610 int32_t range_min, int32_t range_max)
611 {
612 av_assert0(width > 0 && width <= 32);
613
614 if (value < range_min || value > range_max) {
615 av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
616 "%"PRId32", but must be in [%"PRId32",%"PRId32"].\n",
617 name, value, range_min, range_max);
618 return AVERROR_INVALIDDATA;
619 }
620
621 if (put_bits_left(pbc) < width)
622 return AVERROR(ENOSPC);
623
624 if (ctx->trace_enable) {
625 char bits[33];
626 int i;
627 for (i = 0; i < width; i++)
628 bits[i] = value & (1U << (width - i - 1)) ? '1' : '0';
629 bits[i] = 0;
630
631 ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc),
632 name, subscripts, bits, value);
633 }
634
635 if (width < 32)
636 put_sbits(pbc, width, value);
637 else
638 put_bits32(pbc, value);
639
640 return 0;
641 }
642
643
ff_cbs_alloc_unit_content(CodedBitstreamContext * ctx,CodedBitstreamUnit * unit,size_t size,void (* free)(void * opaque,uint8_t * data))644 int ff_cbs_alloc_unit_content(CodedBitstreamContext *ctx,
645 CodedBitstreamUnit *unit,
646 size_t size,
647 void (*free)(void *opaque, uint8_t *data))
648 {
649 av_assert0(!unit->content && !unit->content_ref);
650
651 unit->content = av_mallocz(size);
652 if (!unit->content)
653 return AVERROR(ENOMEM);
654
655 unit->content_ref = av_buffer_create(unit->content, size,
656 free, NULL, 0);
657 if (!unit->content_ref) {
658 av_freep(&unit->content);
659 return AVERROR(ENOMEM);
660 }
661
662 return 0;
663 }
664
ff_cbs_alloc_unit_data(CodedBitstreamContext * ctx,CodedBitstreamUnit * unit,size_t size)665 int ff_cbs_alloc_unit_data(CodedBitstreamContext *ctx,
666 CodedBitstreamUnit *unit,
667 size_t size)
668 {
669 av_assert0(!unit->data && !unit->data_ref);
670
671 unit->data_ref = av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
672 if (!unit->data_ref)
673 return AVERROR(ENOMEM);
674
675 unit->data = unit->data_ref->data;
676 unit->data_size = size;
677
678 memset(unit->data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
679
680 return 0;
681 }
682
cbs_insert_unit(CodedBitstreamContext * ctx,CodedBitstreamFragment * frag,int position)683 static int cbs_insert_unit(CodedBitstreamContext *ctx,
684 CodedBitstreamFragment *frag,
685 int position)
686 {
687 CodedBitstreamUnit *units;
688
689 if (frag->nb_units < frag->nb_units_allocated) {
690 units = frag->units;
691
692 if (position < frag->nb_units)
693 memmove(units + position + 1, units + position,
694 (frag->nb_units - position) * sizeof(*units));
695 } else {
696 units = av_malloc_array(frag->nb_units*2 + 1, sizeof(*units));
697 if (!units)
698 return AVERROR(ENOMEM);
699
700 frag->nb_units_allocated = 2*frag->nb_units_allocated + 1;
701
702 if (position > 0)
703 memcpy(units, frag->units, position * sizeof(*units));
704
705 if (position < frag->nb_units)
706 memcpy(units + position + 1, frag->units + position,
707 (frag->nb_units - position) * sizeof(*units));
708 }
709
710 memset(units + position, 0, sizeof(*units));
711
712 if (units != frag->units) {
713 av_free(frag->units);
714 frag->units = units;
715 }
716
717 ++frag->nb_units;
718
719 return 0;
720 }
721
ff_cbs_insert_unit_content(CodedBitstreamContext * ctx,CodedBitstreamFragment * frag,int position,CodedBitstreamUnitType type,void * content,AVBufferRef * content_buf)722 int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx,
723 CodedBitstreamFragment *frag,
724 int position,
725 CodedBitstreamUnitType type,
726 void *content,
727 AVBufferRef *content_buf)
728 {
729 CodedBitstreamUnit *unit;
730 AVBufferRef *content_ref;
731 int err;
732
733 if (position == -1)
734 position = frag->nb_units;
735 av_assert0(position >= 0 && position <= frag->nb_units);
736
737 if (content_buf) {
738 content_ref = av_buffer_ref(content_buf);
739 if (!content_ref)
740 return AVERROR(ENOMEM);
741 } else {
742 content_ref = NULL;
743 }
744
745 err = cbs_insert_unit(ctx, frag, position);
746 if (err < 0) {
747 av_buffer_unref(&content_ref);
748 return err;
749 }
750
751 unit = &frag->units[position];
752 unit->type = type;
753 unit->content = content;
754 unit->content_ref = content_ref;
755
756 return 0;
757 }
758
ff_cbs_insert_unit_data(CodedBitstreamContext * ctx,CodedBitstreamFragment * frag,int position,CodedBitstreamUnitType type,uint8_t * data,size_t data_size,AVBufferRef * data_buf)759 int ff_cbs_insert_unit_data(CodedBitstreamContext *ctx,
760 CodedBitstreamFragment *frag,
761 int position,
762 CodedBitstreamUnitType type,
763 uint8_t *data, size_t data_size,
764 AVBufferRef *data_buf)
765 {
766 CodedBitstreamUnit *unit;
767 AVBufferRef *data_ref;
768 int err;
769
770 if (position == -1)
771 position = frag->nb_units;
772 av_assert0(position >= 0 && position <= frag->nb_units);
773
774 if (data_buf)
775 data_ref = av_buffer_ref(data_buf);
776 else
777 data_ref = av_buffer_create(data, data_size, NULL, NULL, 0);
778 if (!data_ref) {
779 if (!data_buf)
780 av_free(data);
781 return AVERROR(ENOMEM);
782 }
783
784 err = cbs_insert_unit(ctx, frag, position);
785 if (err < 0) {
786 av_buffer_unref(&data_ref);
787 return err;
788 }
789
790 unit = &frag->units[position];
791 unit->type = type;
792 unit->data = data;
793 unit->data_size = data_size;
794 unit->data_ref = data_ref;
795
796 return 0;
797 }
798
ff_cbs_delete_unit(CodedBitstreamContext * ctx,CodedBitstreamFragment * frag,int position)799 void ff_cbs_delete_unit(CodedBitstreamContext *ctx,
800 CodedBitstreamFragment *frag,
801 int position)
802 {
803 av_assert0(0 <= position && position < frag->nb_units
804 && "Unit to be deleted not in fragment.");
805
806 cbs_unit_uninit(ctx, &frag->units[position]);
807
808 --frag->nb_units;
809
810 if (frag->nb_units > 0)
811 memmove(frag->units + position,
812 frag->units + position + 1,
813 (frag->nb_units - position) * sizeof(*frag->units));
814 }
815