2 * This file is part of FFmpeg.
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.
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.
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
23 #include "libavutil/avassert.h"
24 #include "libavutil/buffer.h"
25 #include "libavutil/common.h"
26 #include "libavutil/mem.h"
27 #include "libavutil/opt.h"
31 #include "cbs_internal.h"
32 #include "libavutil/refstruct.h"
35 static const CodedBitstreamType
*const cbs_type_table
[] = {
62 const enum AVCodecID ff_cbs_all_codec_ids
[] = {
79 AV_CODEC_ID_MPEG2VIDEO
,
90 av_cold
int ff_cbs_init(CodedBitstreamContext
**ctx_ptr
,
91 enum AVCodecID codec_id
, void *log_ctx
)
93 CodedBitstreamContext
*ctx
;
94 const CodedBitstreamType
*type
;
98 for (i
= 0; i
< FF_ARRAY_ELEMS(cbs_type_table
); i
++) {
99 if (cbs_type_table
[i
]->codec_id
== codec_id
) {
100 type
= cbs_type_table
[i
];
105 return AVERROR(EINVAL
);
107 ctx
= av_mallocz(sizeof(*ctx
));
109 return AVERROR(ENOMEM
);
111 ctx
->log_ctx
= log_ctx
;
112 ctx
->codec
= type
; /* Must be before any error */
114 if (type
->priv_data_size
) {
115 ctx
->priv_data
= av_mallocz(ctx
->codec
->priv_data_size
);
116 if (!ctx
->priv_data
) {
118 return AVERROR(ENOMEM
);
120 if (type
->priv_class
) {
121 *(const AVClass
**)ctx
->priv_data
= type
->priv_class
;
122 av_opt_set_defaults(ctx
->priv_data
);
126 ctx
->decompose_unit_types
= NULL
;
128 ctx
->trace_enable
= 0;
129 ctx
->trace_level
= AV_LOG_TRACE
;
130 ctx
->trace_context
= ctx
;
136 av_cold
void ff_cbs_flush(CodedBitstreamContext
*ctx
)
138 if (ctx
->codec
->flush
)
139 ctx
->codec
->flush(ctx
);
142 av_cold
void ff_cbs_close(CodedBitstreamContext
**ctx_ptr
)
144 CodedBitstreamContext
*ctx
= *ctx_ptr
;
149 if (ctx
->codec
->close
)
150 ctx
->codec
->close(ctx
);
152 av_freep(&ctx
->write_buffer
);
154 if (ctx
->codec
->priv_class
&& ctx
->priv_data
)
155 av_opt_free(ctx
->priv_data
);
157 av_freep(&ctx
->priv_data
);
161 static void cbs_unit_uninit(CodedBitstreamUnit
*unit
)
163 av_refstruct_unref(&unit
->content_ref
);
164 unit
->content
= NULL
;
166 av_buffer_unref(&unit
->data_ref
);
169 unit
->data_bit_padding
= 0;
172 void ff_cbs_fragment_reset(CodedBitstreamFragment
*frag
)
176 for (i
= 0; i
< frag
->nb_units
; i
++)
177 cbs_unit_uninit(&frag
->units
[i
]);
180 av_buffer_unref(&frag
->data_ref
);
183 frag
->data_bit_padding
= 0;
186 av_cold
void ff_cbs_fragment_free(CodedBitstreamFragment
*frag
)
188 ff_cbs_fragment_reset(frag
);
190 av_freep(&frag
->units
);
191 frag
->nb_units_allocated
= 0;
194 static int cbs_read_fragment_content(CodedBitstreamContext
*ctx
,
195 CodedBitstreamFragment
*frag
)
199 for (i
= 0; i
< frag
->nb_units
; i
++) {
200 CodedBitstreamUnit
*unit
= &frag
->units
[i
];
202 if (ctx
->decompose_unit_types
) {
203 for (j
= 0; j
< ctx
->nb_decompose_unit_types
; j
++) {
204 if (ctx
->decompose_unit_types
[j
] == unit
->type
)
207 if (j
>= ctx
->nb_decompose_unit_types
)
211 av_refstruct_unref(&unit
->content_ref
);
212 unit
->content
= NULL
;
214 av_assert0(unit
->data
&& unit
->data_ref
);
216 err
= ctx
->codec
->read_unit(ctx
, unit
);
217 if (err
== AVERROR(ENOSYS
)) {
218 av_log(ctx
->log_ctx
, AV_LOG_VERBOSE
,
219 "Decomposition unimplemented for unit %d "
220 "(type %"PRIu32
").\n", i
, unit
->type
);
221 } else if (err
== AVERROR(EAGAIN
)) {
222 av_log(ctx
->log_ctx
, AV_LOG_VERBOSE
,
223 "Skipping decomposition of unit %d "
224 "(type %"PRIu32
").\n", i
, unit
->type
);
225 av_refstruct_unref(&unit
->content_ref
);
226 unit
->content
= NULL
;
227 } else if (err
< 0) {
228 av_log(ctx
->log_ctx
, AV_LOG_ERROR
, "Failed to read unit %d "
229 "(type %"PRIu32
").\n", i
, unit
->type
);
237 static int cbs_fill_fragment_data(CodedBitstreamFragment
*frag
,
238 const uint8_t *data
, size_t size
)
240 av_assert0(!frag
->data
&& !frag
->data_ref
);
243 av_buffer_alloc(size
+ AV_INPUT_BUFFER_PADDING_SIZE
);
245 return AVERROR(ENOMEM
);
247 frag
->data
= frag
->data_ref
->data
;
248 frag
->data_size
= size
;
250 memcpy(frag
->data
, data
, size
);
251 memset(frag
->data
+ size
, 0,
252 AV_INPUT_BUFFER_PADDING_SIZE
);
257 static int cbs_read_data(CodedBitstreamContext
*ctx
,
258 CodedBitstreamFragment
*frag
,
260 const uint8_t *data
, size_t size
,
266 frag
->data_ref
= av_buffer_ref(buf
);
268 return AVERROR(ENOMEM
);
270 frag
->data
= (uint8_t *)data
;
271 frag
->data_size
= size
;
274 err
= cbs_fill_fragment_data(frag
, data
, size
);
279 err
= ctx
->codec
->split_fragment(ctx
, frag
, header
);
283 return cbs_read_fragment_content(ctx
, frag
);
286 int ff_cbs_read_extradata(CodedBitstreamContext
*ctx
,
287 CodedBitstreamFragment
*frag
,
288 const AVCodecParameters
*par
)
290 return cbs_read_data(ctx
, frag
, NULL
,
292 par
->extradata_size
, 1);
295 int ff_cbs_read_extradata_from_codec(CodedBitstreamContext
*ctx
,
296 CodedBitstreamFragment
*frag
,
297 const AVCodecContext
*avctx
)
299 return cbs_read_data(ctx
, frag
, NULL
,
301 avctx
->extradata_size
, 1);
304 int ff_cbs_read_packet(CodedBitstreamContext
*ctx
,
305 CodedBitstreamFragment
*frag
,
308 return cbs_read_data(ctx
, frag
, pkt
->buf
,
309 pkt
->data
, pkt
->size
, 0);
312 int ff_cbs_read_packet_side_data(CodedBitstreamContext
*ctx
,
313 CodedBitstreamFragment
*frag
,
316 size_t side_data_size
;
317 const uint8_t *side_data
=
318 av_packet_get_side_data(pkt
, AV_PKT_DATA_NEW_EXTRADATA
,
321 return cbs_read_data(ctx
, frag
, NULL
,
322 side_data
, side_data_size
, 1);
325 int ff_cbs_read(CodedBitstreamContext
*ctx
,
326 CodedBitstreamFragment
*frag
,
327 const uint8_t *data
, size_t size
)
329 return cbs_read_data(ctx
, frag
, NULL
,
334 * Allocate a new internal data buffer of the given size in the unit.
336 * The data buffer will have input padding.
338 static int cbs_alloc_unit_data(CodedBitstreamUnit
*unit
,
341 av_assert0(!unit
->data
&& !unit
->data_ref
);
343 unit
->data_ref
= av_buffer_alloc(size
+ AV_INPUT_BUFFER_PADDING_SIZE
);
345 return AVERROR(ENOMEM
);
347 unit
->data
= unit
->data_ref
->data
;
348 unit
->data_size
= size
;
350 memset(unit
->data
+ size
, 0, AV_INPUT_BUFFER_PADDING_SIZE
);
355 static int cbs_write_unit_data(CodedBitstreamContext
*ctx
,
356 CodedBitstreamUnit
*unit
)
361 if (!ctx
->write_buffer
) {
362 // Initial write buffer size is 1MB.
363 ctx
->write_buffer_size
= 1024 * 1024;
365 reallocate_and_try_again
:
366 ret
= av_reallocp(&ctx
->write_buffer
, ctx
->write_buffer_size
);
368 av_log(ctx
->log_ctx
, AV_LOG_ERROR
, "Unable to allocate a "
369 "sufficiently large write buffer (last attempt "
370 "%"SIZE_SPECIFIER
" bytes).\n", ctx
->write_buffer_size
);
375 init_put_bits(&pbc
, ctx
->write_buffer
, ctx
->write_buffer_size
);
377 ret
= ctx
->codec
->write_unit(ctx
, unit
, &pbc
);
379 if (ret
== AVERROR(ENOSPC
)) {
381 if (ctx
->write_buffer_size
== INT_MAX
/ 8)
382 return AVERROR(ENOMEM
);
383 ctx
->write_buffer_size
= FFMIN(2 * ctx
->write_buffer_size
, INT_MAX
/ 8);
384 goto reallocate_and_try_again
;
386 // Write failed for some other reason.
390 // Overflow but we didn't notice.
391 av_assert0(put_bits_count(&pbc
) <= 8 * ctx
->write_buffer_size
);
393 if (put_bits_count(&pbc
) % 8)
394 unit
->data_bit_padding
= 8 - put_bits_count(&pbc
) % 8;
396 unit
->data_bit_padding
= 0;
398 flush_put_bits(&pbc
);
400 ret
= cbs_alloc_unit_data(unit
, put_bytes_output(&pbc
));
404 memcpy(unit
->data
, ctx
->write_buffer
, unit
->data_size
);
409 int ff_cbs_write_fragment_data(CodedBitstreamContext
*ctx
,
410 CodedBitstreamFragment
*frag
)
414 for (i
= 0; i
< frag
->nb_units
; i
++) {
415 CodedBitstreamUnit
*unit
= &frag
->units
[i
];
420 av_buffer_unref(&unit
->data_ref
);
423 err
= cbs_write_unit_data(ctx
, unit
);
425 av_log(ctx
->log_ctx
, AV_LOG_ERROR
, "Failed to write unit %d "
426 "(type %"PRIu32
").\n", i
, unit
->type
);
429 av_assert0(unit
->data
&& unit
->data_ref
);
432 av_buffer_unref(&frag
->data_ref
);
435 err
= ctx
->codec
->assemble_fragment(ctx
, frag
);
437 av_log(ctx
->log_ctx
, AV_LOG_ERROR
, "Failed to assemble fragment.\n");
440 av_assert0(frag
->data
&& frag
->data_ref
);
445 int ff_cbs_write_extradata(CodedBitstreamContext
*ctx
,
446 AVCodecParameters
*par
,
447 CodedBitstreamFragment
*frag
)
451 err
= ff_cbs_write_fragment_data(ctx
, frag
);
455 av_freep(&par
->extradata
);
456 par
->extradata_size
= 0;
458 if (!frag
->data_size
)
461 par
->extradata
= av_malloc(frag
->data_size
+
462 AV_INPUT_BUFFER_PADDING_SIZE
);
464 return AVERROR(ENOMEM
);
466 memcpy(par
->extradata
, frag
->data
, frag
->data_size
);
467 memset(par
->extradata
+ frag
->data_size
, 0,
468 AV_INPUT_BUFFER_PADDING_SIZE
);
469 par
->extradata_size
= frag
->data_size
;
474 int ff_cbs_write_packet(CodedBitstreamContext
*ctx
,
476 CodedBitstreamFragment
*frag
)
481 err
= ff_cbs_write_fragment_data(ctx
, frag
);
485 buf
= av_buffer_ref(frag
->data_ref
);
487 return AVERROR(ENOMEM
);
489 av_buffer_unref(&pkt
->buf
);
492 pkt
->data
= frag
->data
;
493 pkt
->size
= frag
->data_size
;
499 void ff_cbs_trace_header(CodedBitstreamContext
*ctx
,
502 if (!ctx
->trace_enable
)
505 av_log(ctx
->log_ctx
, ctx
->trace_level
, "%s\n", name
);
508 void ff_cbs_trace_read_log(void *trace_context
,
509 GetBitContext
*gbc
, int length
,
510 const char *str
, const int *subscripts
,
513 CodedBitstreamContext
*ctx
= trace_context
;
516 size_t name_len
, bits_len
;
517 int pad
, subs
, i
, j
, k
, n
;
520 av_assert0(value
>= INT_MIN
&& value
<= UINT32_MAX
);
522 position
= get_bits_count(gbc
);
524 av_assert0(length
< 256);
525 for (i
= 0; i
< length
; i
++)
526 bits
[i
] = get_bits1(gbc
) ? '1' : '0';
529 subs
= subscripts
? subscripts
[0] : 0;
531 for (i
= j
= 0; str
[i
];) {
535 k
= snprintf(name
+ j
, sizeof(name
) - j
, "[%d", subscripts
[n
]);
536 av_assert0(k
> 0 && j
+ k
< sizeof(name
));
538 for (++i
; str
[i
] && str
[i
] != ']'; i
++);
539 av_assert0(str
[i
] == ']');
541 while (str
[i
] && str
[i
] != ']')
542 name
[j
++] = str
[i
++];
543 av_assert0(str
[i
] == ']');
546 av_assert0(j
+ 1 < sizeof(name
));
547 name
[j
++] = str
[i
++];
550 av_assert0(j
+ 1 < sizeof(name
));
552 av_assert0(n
== subs
);
554 name_len
= strlen(name
);
557 if (name_len
+ bits_len
> 60)
562 av_log(ctx
->log_ctx
, ctx
->trace_level
, "%-10d %s%*s = %"PRId64
"\n",
563 position
, name
, pad
, bits
, value
);
566 void ff_cbs_trace_write_log(void *trace_context
,
567 PutBitContext
*pbc
, int length
,
568 const char *str
, const int *subscripts
,
571 CodedBitstreamContext
*ctx
= trace_context
;
573 // Ensure that the syntax element is written to the output buffer,
574 // make a GetBitContext pointed at the start position, then call the
575 // read log function which can read the bits back to log them.
583 flush_put_bits(&flush
);
586 position
= put_bits_count(pbc
);
587 av_assert0(position
>= length
);
589 init_get_bits(&gbc
, pbc
->buf
, position
);
591 skip_bits_long(&gbc
, position
- length
);
593 ff_cbs_trace_read_log(ctx
, &gbc
, length
, str
, subscripts
, value
);
596 static av_always_inline
int cbs_read_unsigned(CodedBitstreamContext
*ctx
,
598 int width
, const char *name
,
599 const int *subscripts
,
606 CBS_TRACE_READ_START();
608 av_assert0(width
> 0 && width
<= 32);
610 if (get_bits_left(gbc
) < width
) {
611 av_log(ctx
->log_ctx
, AV_LOG_ERROR
, "Invalid value at "
612 "%s: bitstream ended.\n", name
);
613 return AVERROR_INVALIDDATA
;
616 value
= get_bits_long(gbc
, width
);
618 CBS_TRACE_READ_END();
620 if (value
< range_min
|| value
> range_max
) {
621 av_log(ctx
->log_ctx
, AV_LOG_ERROR
, "%s out of range: "
622 "%"PRIu32
", but must be in [%"PRIu32
",%"PRIu32
"].\n",
623 name
, value
, range_min
, range_max
);
624 return AVERROR_INVALIDDATA
;
631 int ff_cbs_read_unsigned(CodedBitstreamContext
*ctx
, GetBitContext
*gbc
,
632 int width
, const char *name
,
633 const int *subscripts
, uint32_t *write_to
,
634 uint32_t range_min
, uint32_t range_max
)
636 return cbs_read_unsigned(ctx
, gbc
, width
, name
, subscripts
,
637 write_to
, range_min
, range_max
);
640 int ff_cbs_read_simple_unsigned(CodedBitstreamContext
*ctx
, GetBitContext
*gbc
,
641 int width
, const char *name
, uint32_t *write_to
)
643 return cbs_read_unsigned(ctx
, gbc
, width
, name
, NULL
,
644 write_to
, 0, UINT32_MAX
);
647 int ff_cbs_write_unsigned(CodedBitstreamContext
*ctx
, PutBitContext
*pbc
,
648 int width
, const char *name
,
649 const int *subscripts
, uint32_t value
,
650 uint32_t range_min
, uint32_t range_max
)
652 CBS_TRACE_WRITE_START();
654 av_assert0(width
> 0 && width
<= 32);
656 if (value
< range_min
|| value
> range_max
) {
657 av_log(ctx
->log_ctx
, AV_LOG_ERROR
, "%s out of range: "
658 "%"PRIu32
", but must be in [%"PRIu32
",%"PRIu32
"].\n",
659 name
, value
, range_min
, range_max
);
660 return AVERROR_INVALIDDATA
;
663 if (put_bits_left(pbc
) < width
)
664 return AVERROR(ENOSPC
);
667 put_bits(pbc
, width
, value
);
669 put_bits32(pbc
, value
);
671 CBS_TRACE_WRITE_END();
676 int ff_cbs_write_simple_unsigned(CodedBitstreamContext
*ctx
, PutBitContext
*pbc
,
677 int width
, const char *name
, uint32_t value
)
679 return ff_cbs_write_unsigned(ctx
, pbc
, width
, name
, NULL
,
680 value
, 0, MAX_UINT_BITS(width
));
683 int ff_cbs_read_signed(CodedBitstreamContext
*ctx
, GetBitContext
*gbc
,
684 int width
, const char *name
,
685 const int *subscripts
, int32_t *write_to
,
686 int32_t range_min
, int32_t range_max
)
690 CBS_TRACE_READ_START();
692 av_assert0(width
> 0 && width
<= 32);
694 if (get_bits_left(gbc
) < width
) {
695 av_log(ctx
->log_ctx
, AV_LOG_ERROR
, "Invalid value at "
696 "%s: bitstream ended.\n", name
);
697 return AVERROR_INVALIDDATA
;
700 value
= get_sbits_long(gbc
, width
);
702 CBS_TRACE_READ_END();
704 if (value
< range_min
|| value
> range_max
) {
705 av_log(ctx
->log_ctx
, AV_LOG_ERROR
, "%s out of range: "
706 "%"PRId32
", but must be in [%"PRId32
",%"PRId32
"].\n",
707 name
, value
, range_min
, range_max
);
708 return AVERROR_INVALIDDATA
;
715 int ff_cbs_write_signed(CodedBitstreamContext
*ctx
, PutBitContext
*pbc
,
716 int width
, const char *name
,
717 const int *subscripts
, int32_t value
,
718 int32_t range_min
, int32_t range_max
)
720 CBS_TRACE_WRITE_START();
722 av_assert0(width
> 0 && width
<= 32);
724 if (value
< range_min
|| value
> range_max
) {
725 av_log(ctx
->log_ctx
, AV_LOG_ERROR
, "%s out of range: "
726 "%"PRId32
", but must be in [%"PRId32
",%"PRId32
"].\n",
727 name
, value
, range_min
, range_max
);
728 return AVERROR_INVALIDDATA
;
731 if (put_bits_left(pbc
) < width
)
732 return AVERROR(ENOSPC
);
735 put_sbits(pbc
, width
, value
);
737 put_bits32(pbc
, value
);
739 CBS_TRACE_WRITE_END();
745 static int cbs_insert_unit(CodedBitstreamFragment
*frag
,
748 CodedBitstreamUnit
*units
;
750 if (frag
->nb_units
< frag
->nb_units_allocated
) {
753 if (position
< frag
->nb_units
)
754 memmove(units
+ position
+ 1, units
+ position
,
755 (frag
->nb_units
- position
) * sizeof(*units
));
757 units
= av_malloc_array(frag
->nb_units
*2 + 1, sizeof(*units
));
759 return AVERROR(ENOMEM
);
761 frag
->nb_units_allocated
= 2*frag
->nb_units_allocated
+ 1;
764 memcpy(units
, frag
->units
, position
* sizeof(*units
));
766 if (position
< frag
->nb_units
)
767 memcpy(units
+ position
+ 1, frag
->units
+ position
,
768 (frag
->nb_units
- position
) * sizeof(*units
));
771 memset(units
+ position
, 0, sizeof(*units
));
773 if (units
!= frag
->units
) {
774 av_free(frag
->units
);
783 int ff_cbs_insert_unit_content(CodedBitstreamFragment
*frag
,
785 CodedBitstreamUnitType type
,
789 CodedBitstreamUnit
*unit
;
793 position
= frag
->nb_units
;
794 av_assert0(position
>= 0 && position
<= frag
->nb_units
);
796 err
= cbs_insert_unit(frag
, position
);
801 // Create our own reference out of the user-supplied one.
802 content_ref
= av_refstruct_ref(content_ref
);
805 unit
= &frag
->units
[position
];
807 unit
->content
= content
;
808 unit
->content_ref
= content_ref
;
813 static int cbs_insert_unit_data(CodedBitstreamFragment
*frag
,
814 CodedBitstreamUnitType type
,
815 uint8_t *data
, size_t data_size
,
816 AVBufferRef
*data_buf
,
819 CodedBitstreamUnit
*unit
;
820 AVBufferRef
*data_ref
;
823 av_assert0(position
>= 0 && position
<= frag
->nb_units
);
826 data_ref
= av_buffer_ref(data_buf
);
828 data_ref
= av_buffer_create(data
, data_size
, NULL
, NULL
, 0);
832 return AVERROR(ENOMEM
);
835 err
= cbs_insert_unit(frag
, position
);
837 av_buffer_unref(&data_ref
);
841 unit
= &frag
->units
[position
];
844 unit
->data_size
= data_size
;
845 unit
->data_ref
= data_ref
;
850 int ff_cbs_append_unit_data(CodedBitstreamFragment
*frag
,
851 CodedBitstreamUnitType type
,
852 uint8_t *data
, size_t data_size
,
853 AVBufferRef
*data_buf
)
855 return cbs_insert_unit_data(frag
, type
,
856 data
, data_size
, data_buf
,
860 void ff_cbs_delete_unit(CodedBitstreamFragment
*frag
,
863 av_assert0(0 <= position
&& position
< frag
->nb_units
864 && "Unit to be deleted not in fragment.");
866 cbs_unit_uninit(&frag
->units
[position
]);
870 if (frag
->nb_units
> 0)
871 memmove(frag
->units
+ position
,
872 frag
->units
+ position
+ 1,
873 (frag
->nb_units
- position
) * sizeof(*frag
->units
));
876 static void cbs_default_free_unit_content(AVRefStructOpaque opaque
, void *content
)
878 const CodedBitstreamUnitTypeDescriptor
*desc
= opaque
.c
;
880 for (int i
= 0; i
< desc
->type
.ref
.nb_offsets
; i
++) {
881 void **ptr
= (void**)((char*)content
+ desc
->type
.ref
.offsets
[i
]);
882 av_buffer_unref((AVBufferRef
**)(ptr
+ 1));
886 static const CodedBitstreamUnitTypeDescriptor
887 *cbs_find_unit_type_desc(CodedBitstreamContext
*ctx
,
888 CodedBitstreamUnit
*unit
)
890 const CodedBitstreamUnitTypeDescriptor
*desc
;
893 if (!ctx
->codec
->unit_types
)
897 desc
= &ctx
->codec
->unit_types
[i
];
898 if (desc
->nb_unit_types
== 0)
900 if (desc
->nb_unit_types
== CBS_UNIT_TYPE_RANGE
) {
901 if (unit
->type
>= desc
->unit_type
.range
.start
&&
902 unit
->type
<= desc
->unit_type
.range
.end
)
905 for (j
= 0; j
< desc
->nb_unit_types
; j
++) {
906 if (desc
->unit_type
.list
[j
] == unit
->type
)
914 static void *cbs_alloc_content(const CodedBitstreamUnitTypeDescriptor
*desc
)
916 return av_refstruct_alloc_ext_c(desc
->content_size
, 0,
917 (AVRefStructOpaque
){ .c
= desc
},
918 desc
->content_type
== CBS_CONTENT_TYPE_COMPLEX
919 ? desc
->type
.complex.content_free
920 : cbs_default_free_unit_content
);
923 int ff_cbs_alloc_unit_content(CodedBitstreamContext
*ctx
,
924 CodedBitstreamUnit
*unit
)
926 const CodedBitstreamUnitTypeDescriptor
*desc
;
928 av_assert0(!unit
->content
&& !unit
->content_ref
);
930 desc
= cbs_find_unit_type_desc(ctx
, unit
);
932 return AVERROR(ENOSYS
);
934 unit
->content_ref
= cbs_alloc_content(desc
);
935 if (!unit
->content_ref
)
936 return AVERROR(ENOMEM
);
937 unit
->content
= unit
->content_ref
;
942 static int cbs_clone_noncomplex_unit_content(void **clonep
,
943 const CodedBitstreamUnit
*unit
,
944 const CodedBitstreamUnitTypeDescriptor
*desc
)
950 av_assert0(unit
->content
);
953 copy
= cbs_alloc_content(desc
);
955 return AVERROR(ENOMEM
);
956 memcpy(copy
, src
, desc
->content_size
);
957 for (int i
= 0; i
< desc
->type
.ref
.nb_offsets
; i
++) {
958 void **ptr
= (void**)(copy
+ desc
->type
.ref
.offsets
[i
]);
959 /* Zero all the AVBufferRefs as they are owned by src. */
963 for (i
= 0; i
< desc
->type
.ref
.nb_offsets
; i
++) {
964 const uint8_t *const *src_ptr
= (const uint8_t* const*)(src
+ desc
->type
.ref
.offsets
[i
]);
965 const AVBufferRef
*src_buf
= *(AVBufferRef
**)(src_ptr
+ 1);
966 uint8_t **copy_ptr
= (uint8_t**)(copy
+ desc
->type
.ref
.offsets
[i
]);
967 AVBufferRef
**copy_buf
= (AVBufferRef
**)(copy_ptr
+ 1);
970 av_assert0(!src_buf
);
974 // We can't handle a non-refcounted pointer here - we don't
975 // have enough information to handle whatever structure lies
976 // at the other end of it.
977 err
= AVERROR(EINVAL
);
981 *copy_buf
= av_buffer_ref(src_buf
);
983 err
= AVERROR(ENOMEM
);
992 av_refstruct_unref(©
);
997 * On success, unit->content and unit->content_ref are updated with
998 * the new content; unit is untouched on failure.
999 * Any old content_ref is simply overwritten and not freed.
1001 static int cbs_clone_unit_content(CodedBitstreamContext
*ctx
,
1002 CodedBitstreamUnit
*unit
)
1004 const CodedBitstreamUnitTypeDescriptor
*desc
;
1008 desc
= cbs_find_unit_type_desc(ctx
, unit
);
1010 return AVERROR(ENOSYS
);
1012 switch (desc
->content_type
) {
1013 case CBS_CONTENT_TYPE_INTERNAL_REFS
:
1014 err
= cbs_clone_noncomplex_unit_content(&new_content
, unit
, desc
);
1017 case CBS_CONTENT_TYPE_COMPLEX
:
1018 if (!desc
->type
.complex.content_clone
)
1019 return AVERROR_PATCHWELCOME
;
1020 err
= desc
->type
.complex.content_clone(&new_content
, unit
);
1024 av_assert0(0 && "Invalid content type.");
1030 unit
->content_ref
= new_content
;
1031 unit
->content
= new_content
;
1035 int ff_cbs_make_unit_refcounted(CodedBitstreamContext
*ctx
,
1036 CodedBitstreamUnit
*unit
)
1038 av_assert0(unit
->content
);
1039 if (unit
->content_ref
)
1041 return cbs_clone_unit_content(ctx
, unit
);
1044 int ff_cbs_make_unit_writable(CodedBitstreamContext
*ctx
,
1045 CodedBitstreamUnit
*unit
)
1047 void *ref
= unit
->content_ref
;
1050 av_assert0(unit
->content
);
1051 if (ref
&& av_refstruct_exclusive(ref
))
1054 err
= cbs_clone_unit_content(ctx
, unit
);
1057 av_refstruct_unref(&ref
);
1061 void ff_cbs_discard_units(CodedBitstreamContext
*ctx
,
1062 CodedBitstreamFragment
*frag
,
1063 enum AVDiscard skip
,
1066 if (!ctx
->codec
->discarded_unit
)
1069 for (int i
= frag
->nb_units
- 1; i
>= 0; i
--) {
1070 if (ctx
->codec
->discarded_unit(ctx
, &frag
->units
[i
], skip
)) {
1071 // discard all units
1072 if (!(flags
& DISCARD_FLAG_KEEP_NON_VCL
)) {
1073 ff_cbs_fragment_free(frag
);
1077 ff_cbs_delete_unit(frag
, i
);