/* * 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
*/
zeroes = 0; while (zeroes < 32) { if (get_bits_left(gbc) < 1) {
av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid uvlc code at " "%s: bitstream ended.\n", name); return AVERROR_INVALIDDATA;
}
if (get_bits1(gbc)) break;
++zeroes;
}
if (zeroes >= 32) { // The spec allows at least thirty-two zero bits followed by a // one to mean 2^32-1, with no constraint on the number of // zeroes. The libaom reference decoder does not match this, // instead reading thirty-two zeroes but not the following one // to mean 2^32-1. These two interpretations are incompatible // and other implementations may follow one or the other. // Therefore we reject thirty-two zeroes because the intended // behaviour is not clear.
av_log(ctx->log_ctx, AV_LOG_ERROR, "Thirty-two zero bits in " "%s uvlc code: considered invalid due to conflicting " "standard and reference decoder behaviour.\n", name); return AVERROR_INVALIDDATA;
} else { if (get_bits_left(gbc) < zeroes) {
av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid uvlc code at " "%s: bitstream ended.\n", name); return AVERROR_INVALIDDATA;
}
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 (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;
}
zeroes = av_log2(value + 1);
v = value - (1U << zeroes) + 1;
if (put_bits_left(pbc) < 2 * zeroes + 1) return AVERROR(ENOSPC);
value = 0; for (i = 0; i < 8; i++) { if (get_bits_left(gbc) < 8) {
av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid leb128 at " "%s: bitstream ended.\n", name); return AVERROR_INVALIDDATA;
}
byte = get_bits(gbc, 8);
value |= (uint64_t)(byte & 0x7f) << (i * 7); if (!(byte & 0x80)) break;
}
if (value > UINT32_MAX) return AVERROR_INVALIDDATA;
CBS_TRACE_READ_END_NO_SUBSCRIPTS();
*write_to = value; return 0;
}
staticint cbs_av1_write_leb128(CodedBitstreamContext *ctx, PutBitContext *pbc, constchar *name, uint64_t value, int fixed_length)
{ int len, i;
uint8_t byte;
CBS_TRACE_WRITE_START();
len = (av_log2(value) + 7) / 7;
if (fixed_length) { if (fixed_length < len) {
av_log(ctx->log_ctx, AV_LOG_ERROR, "OBU is too large for " "fixed length size field (%d > %d).\n",
len, fixed_length); return AVERROR(EINVAL);
}
len = fixed_length;
}
for (i = 0; i < len; i++) { if (put_bits_left(pbc) < 8) return AVERROR(ENOSPC);
byte = value >> (7 * i) & 0x7f; if (i < len - 1)
byte |= 0x80;
put_bits(pbc, 8, byte);
}
CBS_TRACE_WRITE_END_NO_SUBSCRIPTS();
return 0;
}
staticint cbs_av1_read_ns(CodedBitstreamContext *ctx, GetBitContext *gbc,
uint32_t n, constchar *name, constint *subscripts, uint32_t *write_to)
{
uint32_t m, v, extra_bit, value; int w;
CBS_TRACE_READ_START();
av_assert0(n > 0);
w = av_log2(n) + 1;
m = (1 << w) - n;
if (get_bits_left(gbc) < w) {
av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid non-symmetric value at " "%s: bitstream ended.\n", name); return AVERROR_INVALIDDATA;
}
if (w - 1 > 0)
v = get_bits(gbc, w - 1); else
v = 0;
if (v < m) {
value = v;
} else {
extra_bit = get_bits1(gbc);
value = (v << 1) - m + extra_bit;
}
CBS_TRACE_READ_END();
*write_to = value; return 0;
}
staticint cbs_av1_write_ns(CodedBitstreamContext *ctx, PutBitContext *pbc,
uint32_t n, constchar *name, constint *subscripts, uint32_t value)
{
uint32_t w, m, v, extra_bit;
CBS_TRACE_WRITE_START();
if (value > n) {
av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: " "%"PRIu32", but must be in [0,%"PRIu32"].\n",
name, value, n); return AVERROR_INVALIDDATA;
}
w = av_log2(n) + 1;
m = (1 << w) - n;
if (put_bits_left(pbc) < w) return AVERROR(ENOSPC);
if (value < m) {
v = value;
put_bits(pbc, w - 1, v);
} else {
v = m + ((value - m) >> 1);
extra_bit = (value - m) & 1;
put_bits(pbc, w - 1, v);
put_bits(pbc, 1, extra_bit);
}
av_assert0(range_min <= range_max && range_max - range_min < 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 (value == range_max)
len = range_max - range_min; else
len = value - range_min + 1; if (put_bits_left(pbc) < len) return AVERROR(ENOSPC);
if (value > range_max) {
av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: " "%"PRIu32", but must be in [0,%"PRIu32"].\n",
name, value, range_max); return AVERROR_INVALIDDATA;
}
if (value < 8) {
range_bits = 3;
range_offset = 0;
len = 0;
} else {
range_bits = av_log2(value);
len = range_bits - 2; if (len > max_len) { // The top bin is combined with the one below it.
av_assert0(len == max_len + 1);
--range_bits;
len = max_len;
}
range_offset = 1 << range_bits;
}
#define delta_q(name) do { \
xf(1, name.delta_coded, current->name != 0, 0, 1, 0, ); \ if (current->name) \
xsu(1 + 6, name.delta_q, current->name, 0, ); \
} while (0)
#define leb128(name) do { \
CHECK(cbs_av1_write_leb128(ctx, rw, #name, current->name, 0)); \
} while (0)
#define infer(name, value) do { \ if (current->name != (value)) { \
av_log(ctx->log_ctx, AV_LOG_ERROR, \ "%s does not match inferred value: " \ "%"PRId64", but should be %"PRId64".\n", \ #name, (int64_t)current->name, (int64_t)(value)); \ return AVERROR_INVALIDDATA; \
} \
} while (0)
if (header && size && data[0] & 0x80) { // first bit is nonzero, the extradata does not consist purely of // OBUs. Expect MP4/Matroska AV1CodecConfigurationRecord int config_record_version = data[0] & 0x7f;
if (config_record_version != 1) {
av_log(ctx->log_ctx, AV_LOG_ERROR, "Unknown version %d of AV1CodecConfigurationRecord " "found!\n",
config_record_version);
err = AVERROR_INVALIDDATA; goto fail;
}
// In AV1CodecConfigurationRecord v1, actual OBUs start after // four bytes. Thus set the offset as required for properly // parsing them.
data += 4;
size -= 4;
}
while (size > 0) {
AV1RawOBUHeader obu_header;
uint64_t obu_size;
pos = get_bits_count(gbc); if (pos >= 8 * unit->data_size) {
av_log(ctx->log_ctx, AV_LOG_ERROR, "Bitstream ended before " "any data in tile group (%d bits read).\n", pos); return AVERROR_INVALIDDATA;
} // Must be byte-aligned at this point.
av_assert0(pos % 8 == 0);
td->data_ref = av_buffer_ref(unit->data_ref); if (!td->data_ref) return AVERROR(ENOMEM);
// OBUs in the normal bitstream format must contain a size field // in every OBU (in annex B it is optional, but we don't support // writing that).
obu->header.obu_has_size_field = 1;
av1ctx = *priv;
if (priv->sequence_header_ref) {
av1ctx.sequence_header_ref = av_refstruct_ref(priv->sequence_header_ref);
}
if (priv->frame_header_ref) {
av1ctx.frame_header_ref = av_buffer_ref(priv->frame_header_ref); if (!av1ctx.frame_header_ref) {
err = AVERROR(ENOMEM); goto error;
}
}
if (obu->header.obu_has_size_field) {
pbc_tmp = *pbc; if (priv->fixed_obu_size_length) { for (int i = 0; i < priv->fixed_obu_size_length; i++)
put_bits(pbc, 8, 0);
} else { // Add space for the size field to fill later.
put_bits32(pbc, 0);
put_bits32(pbc, 0);
}
}
td = NULL;
start_pos = put_bits_count(pbc);
switch (obu->header.obu_type) { case AV1_OBU_SEQUENCE_HEADER:
{
err = cbs_av1_write_sequence_header_obu(ctx, pbc,
&obu->obu.sequence_header); if (err < 0) goto error;
if (obu->obu_size > 0) { if (!priv->fixed_obu_size_length) {
memmove(pbc->buf + data_pos,
pbc->buf + start_pos, header_size);
} else { // The size was fixed so the following data was // already written in the correct place.
}
skip_put_bytes(pbc, header_size);
switch (md->metadata_type) { case AV1_METADATA_TYPE_HDR_CLL: case AV1_METADATA_TYPE_HDR_MDCV: case AV1_METADATA_TYPE_SCALABILITY: case AV1_METADATA_TYPE_TIMECODE: break; case AV1_METADATA_TYPE_ITUT_T35:
av_buffer_unref(&md->metadata.itut_t35.payload_ref); break; default:
av_buffer_unref(&md->metadata.unknown.payload_ref);
}
}
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.