/* * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
av_cold int ff_cbs_init(CodedBitstreamContext **ctx_ptr, enum AVCodecID codec_id, void *log_ctx)
{
CodedBitstreamContext *ctx; const CodedBitstreamType *type; int i;
type = NULL; for (i = 0; i < FF_ARRAY_ELEMS(cbs_type_table); i++) { if (cbs_type_table[i]->codec_id == codec_id) {
type = cbs_type_table[i]; break;
}
} if (!type) return AVERROR(EINVAL);
ctx = av_mallocz(sizeof(*ctx)); if (!ctx) return AVERROR(ENOMEM);
ctx->log_ctx = log_ctx;
ctx->codec = type; /* Must be before any error */
if (type->priv_data_size) {
ctx->priv_data = av_mallocz(ctx->codec->priv_data_size); if (!ctx->priv_data) {
av_freep(&ctx); return AVERROR(ENOMEM);
} if (type->priv_class) {
*(const AVClass **)ctx->priv_data = type->priv_class;
av_opt_set_defaults(ctx->priv_data);
}
}
/** * Allocate a new internal data buffer of the given size in the unit. * * The data buffer will have input padding.
*/ staticint cbs_alloc_unit_data(CodedBitstreamUnit *unit,
size_t size)
{
av_assert0(!unit->data && !unit->data_ref);
unit->data_ref = av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE); if (!unit->data_ref) return AVERROR(ENOMEM);
// Ensure that the syntax element is written to the output buffer, // make a GetBitContext pointed at the start position, then call the // read log function which can read the bits back to log them.
if (get_bits_left(gbc) < width) {
av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid value at " "%s: bitstream ended.\n", name); return AVERROR_INVALIDDATA;
}
value = get_bits_long(gbc, width);
CBS_TRACE_READ_END();
if (value < range_min || value > range_max) {
av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: " "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n",
name, value, range_min, range_max); return AVERROR_INVALIDDATA;
}
int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc, int width, constchar *name, constint *subscripts, uint32_t value,
uint32_t range_min, uint32_t range_max)
{
CBS_TRACE_WRITE_START();
av_assert0(width > 0 && width <= 32);
if (value < range_min || value > range_max) {
av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: " "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n",
name, value, range_min, range_max); return AVERROR_INVALIDDATA;
}
if (put_bits_left(pbc) < width) return AVERROR(ENOSPC);
if (width < 32)
put_bits(pbc, width, value); else
put_bits32(pbc, value);
int ff_cbs_read_signed(CodedBitstreamContext *ctx, GetBitContext *gbc, int width, constchar *name, constint *subscripts, int32_t *write_to,
int32_t range_min, int32_t range_max)
{
int32_t value;
CBS_TRACE_READ_START();
av_assert0(width > 0 && width <= 32);
if (get_bits_left(gbc) < width) {
av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid value at " "%s: bitstream ended.\n", name); return AVERROR_INVALIDDATA;
}
value = get_sbits_long(gbc, width);
CBS_TRACE_READ_END();
if (value < range_min || value > range_max) {
av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: " "%"PRId32", but must be in [%"PRId32",%"PRId32"].\n",
name, value, range_min, range_max); return AVERROR_INVALIDDATA;
}
*write_to = value; return 0;
}
int ff_cbs_write_signed(CodedBitstreamContext *ctx, PutBitContext *pbc, int width, constchar *name, constint *subscripts, int32_t value,
int32_t range_min, int32_t range_max)
{
CBS_TRACE_WRITE_START();
av_assert0(width > 0 && width <= 32);
if (value < range_min || value > range_max) {
av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: " "%"PRId32", but must be in [%"PRId32",%"PRId32"].\n",
name, value, range_min, range_max); return AVERROR_INVALIDDATA;
}
if (put_bits_left(pbc) < width) return AVERROR(ENOSPC);
if (width < 32)
put_sbits(pbc, width, value); else
put_bits32(pbc, value);
CBS_TRACE_WRITE_END();
return 0;
}
staticint cbs_insert_unit(CodedBitstreamFragment *frag, int position)
{
CodedBitstreamUnit *units;
if (frag->nb_units < frag->nb_units_allocated) {
units = frag->units;
if (position < frag->nb_units)
memmove(units + position + 1, units + position,
(frag->nb_units - position) * sizeof(*units));
} else {
units = av_malloc_array(frag->nb_units*2 + 1, sizeof(*units)); if (!units) return AVERROR(ENOMEM);
void ff_cbs_delete_unit(CodedBitstreamFragment *frag, int position)
{
av_assert0(0 <= position && position < frag->nb_units
&& "Unit to be deleted not in fragment.");
cbs_unit_uninit(&frag->units[position]);
--frag->nb_units;
if (frag->nb_units > 0)
memmove(frag->units + position,
frag->units + position + 1,
(frag->nb_units - position) * sizeof(*frag->units));
}
copy = cbs_alloc_content(desc); if (!copy) return AVERROR(ENOMEM);
memcpy(copy, src, desc->content_size); for (int i = 0; i < desc->type.ref.nb_offsets; i++) { void **ptr = (void**)(copy + desc->type.ref.offsets[i]); /* Zero all the AVBufferRefs as they are owned by src. */
*(ptr + 1) = NULL;
}
if (!*src_ptr) {
av_assert0(!src_buf); continue;
} if (!src_buf) { // We can't handle a non-refcounted pointer here - we don't // have enough information to handle whatever structure lies // at the other end of it.
err = AVERROR(EINVAL); goto fail;
}
/* * On success, unit->content and unit->content_ref are updated with * the new content; unit is untouched on failure. * Any old content_ref is simply overwritten and not freed.
*/ staticint cbs_clone_unit_content(CodedBitstreamContext *ctx,
CodedBitstreamUnit *unit)
{ const CodedBitstreamUnitTypeDescriptor *desc; void *new_content; int err;
desc = cbs_find_unit_type_desc(ctx, unit); if (!desc) return AVERROR(ENOSYS);
switch (desc->content_type) { case CBS_CONTENT_TYPE_INTERNAL_REFS:
err = cbs_clone_noncomplex_unit_content(&new_content, unit, desc); break;
case CBS_CONTENT_TYPE_COMPLEX: if (!desc->type.complex.content_clone) return AVERROR_PATCHWELCOME;
err = desc->type.complex.content_clone(&new_content, unit); break;
void ff_cbs_discard_units(CodedBitstreamContext *ctx,
CodedBitstreamFragment *frag, enum AVDiscard skip, int flags)
{ if (!ctx->codec->discarded_unit) return;
for (int i = frag->nb_units - 1; i >= 0; i--) { if (ctx->codec->discarded_unit(ctx, &frag->units[i], skip)) { // discard all units if (!(flags & DISCARD_FLAG_KEEP_NON_VCL)) {
ff_cbs_fragment_free(frag); return;
}
ff_cbs_delete_unit(frag, i);
}
}
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.