X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fcbs_av1.c;h=fc228086c297c200cb7aa49e70f89f2824955732;hb=c31ba86c37d6caeed6983343b22e8dbc99dce3cf;hp=b3f81ae93a5347a8ac58cdb094443afdf0d904b8;hpb=0b7269e62d0345fec5f1ee9ee7b960e8d25c5dd1;p=ffmpeg diff --git a/libavcodec/cbs_av1.c b/libavcodec/cbs_av1.c index b3f81ae93a5..fc228086c29 100644 --- a/libavcodec/cbs_av1.c +++ b/libavcodec/cbs_av1.c @@ -29,45 +29,67 @@ static int cbs_av1_read_uvlc(CodedBitstreamContext *ctx, GetBitContext *gbc, const char *name, uint32_t *write_to, uint32_t range_min, uint32_t range_max) { - uint32_t value; - int position, zeroes, i, j; - char bits[65]; + uint32_t zeroes, bits_value, value; + int position; if (ctx->trace_enable) position = get_bits_count(gbc); - zeroes = i = 0; + zeroes = 0; while (1) { - if (get_bits_left(gbc) < zeroes + 1) { + 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)) { - bits[i++] = '1'; + if (get_bits1(gbc)) break; - } else { - bits[i++] = '0'; - ++zeroes; - } + ++zeroes; } if (zeroes >= 32) { value = MAX_UINT_BITS(32); } else { - value = get_bits_long(gbc, zeroes); - - for (j = 0; j < zeroes; j++) - bits[i++] = (value >> (zeroes - j - 1) & 1) ? '1' : '0'; + 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; + } - value += (1 << zeroes) - 1; + bits_value = get_bits_long(gbc, zeroes); + value = bits_value + (UINT32_C(1) << zeroes) - 1; } if (ctx->trace_enable) { + char bits[65]; + int i, j, k; + + if (zeroes >= 32) { + while (zeroes > 32) { + k = FFMIN(zeroes - 32, 32); + for (i = 0; i < k; i++) + bits[i] = '0'; + bits[i] = 0; + ff_cbs_trace_syntax_element(ctx, position, name, + NULL, bits, 0); + zeroes -= k; + position += k; + } + } + + for (i = 0; i < zeroes; i++) + bits[i] = '0'; + bits[i++] = '1'; + + if (zeroes < 32) { + for (j = 0; j < zeroes; j++) + bits[i++] = (bits_value >> (zeroes - j - 1) & 1) ? '1' : '0'; + } + bits[i] = 0; - ff_cbs_trace_syntax_element(ctx, position, name, NULL, - bits, value); + ff_cbs_trace_syntax_element(ctx, position, name, + NULL, bits, value); } if (value < range_min || value > range_max) { @@ -148,6 +170,9 @@ static int cbs_av1_read_leb128(CodedBitstreamContext *ctx, GetBitContext *gbc, break; } + if (value > UINT32_MAX) + return AVERROR_INVALIDDATA; + if (ctx->trace_enable) ff_cbs_trace_syntax_element(ctx, position, name, NULL, "", value); @@ -185,68 +210,12 @@ static int cbs_av1_write_leb128(CodedBitstreamContext *ctx, PutBitContext *pbc, return 0; } -static int cbs_av1_read_su(CodedBitstreamContext *ctx, GetBitContext *gbc, - int width, const char *name, - const int *subscripts, int32_t *write_to) -{ - int position; - int32_t value; - - if (ctx->trace_enable) - position = get_bits_count(gbc); - - if (get_bits_left(gbc) < width) { - av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid signed value at " - "%s: bitstream ended.\n", name); - return AVERROR_INVALIDDATA; - } - - value = get_sbits(gbc, width); - - if (ctx->trace_enable) { - char bits[33]; - int i; - for (i = 0; i < width; i++) - bits[i] = value & (1 << (width - i - 1)) ? '1' : '0'; - bits[i] = 0; - - ff_cbs_trace_syntax_element(ctx, position, - name, subscripts, bits, value); - } - - *write_to = value; - return 0; -} - -static int cbs_av1_write_su(CodedBitstreamContext *ctx, PutBitContext *pbc, - int width, const char *name, - const int *subscripts, int32_t value) -{ - if (put_bits_left(pbc) < width) - return AVERROR(ENOSPC); - - if (ctx->trace_enable) { - char bits[33]; - int i; - for (i = 0; i < width; i++) - bits[i] = value & (1 << (width - i - 1)) ? '1' : '0'; - bits[i] = 0; - - ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc), - name, subscripts, bits, value); - } - - put_sbits(pbc, width, value); - - return 0; -} - static int cbs_av1_read_ns(CodedBitstreamContext *ctx, GetBitContext *gbc, uint32_t n, const char *name, const int *subscripts, uint32_t *write_to) { - uint32_t w, m, v, extra_bit, value; - int position; + uint32_t m, v, extra_bit, value; + int position, w; av_assert0(n > 0); @@ -552,6 +521,17 @@ static int cbs_av1_get_relative_dist(const AV1RawSequenceHeader *seq, return diff; } +static size_t cbs_av1_get_payload_bytes_left(GetBitContext *gbc) +{ + GetBitContext tmp = *gbc; + size_t size = 0; + for (int i = 0; get_bits_left(&tmp) >= 8; i++) { + if (get_bits(&tmp, 8)) + size = i; + } + return size; +} + #define HEADER(name) do { \ ff_cbs_trace_header(ctx, name); \ @@ -570,12 +550,12 @@ static int cbs_av1_get_relative_dist(const AV1RawSequenceHeader *seq, #define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs, __VA_ARGS__ }) : NULL) #define fb(width, name) \ - xf(width, name, current->name, 0, MAX_UINT_BITS(width), 0) + xf(width, name, current->name, 0, MAX_UINT_BITS(width), 0, ) #define fc(width, name, range_min, range_max) \ - xf(width, name, current->name, range_min, range_max, 0) + xf(width, name, current->name, range_min, range_max, 0, ) #define flag(name) fb(1, name) #define su(width, name) \ - xsu(width, name, current->name, 0) + xsu(width, name, current->name, 0, ) #define fbs(width, name, subs, ...) \ xf(width, name, current->name, 0, MAX_UINT_BITS(width), subs, __VA_ARGS__) @@ -588,7 +568,7 @@ static int cbs_av1_get_relative_dist(const AV1RawSequenceHeader *seq, #define fixed(width, name, value) do { \ av_unused uint32_t fixed_value = value; \ - xf(width, name, fixed_value, value, value, 0); \ + xf(width, name, fixed_value, value, value, 0, ); \ } while (0) @@ -597,7 +577,7 @@ static int cbs_av1_get_relative_dist(const AV1RawSequenceHeader *seq, #define RWContext GetBitContext #define xf(width, name, var, range_min, range_max, subs, ...) do { \ - uint32_t value = range_min; \ + uint32_t value; \ CHECK(ff_cbs_read_unsigned(ctx, rw, width, #name, \ SUBSCRIPTS(subs, __VA_ARGS__), \ &value, range_min, range_max)); \ @@ -605,34 +585,36 @@ static int cbs_av1_get_relative_dist(const AV1RawSequenceHeader *seq, } while (0) #define xsu(width, name, var, subs, ...) do { \ - int32_t value = 0; \ - CHECK(cbs_av1_read_su(ctx, rw, width, #name, \ - SUBSCRIPTS(subs, __VA_ARGS__), &value)); \ + int32_t value; \ + CHECK(ff_cbs_read_signed(ctx, rw, width, #name, \ + SUBSCRIPTS(subs, __VA_ARGS__), &value, \ + MIN_INT_BITS(width), \ + MAX_INT_BITS(width))); \ var = value; \ } while (0) #define uvlc(name, range_min, range_max) do { \ - uint32_t value = range_min; \ + uint32_t value; \ CHECK(cbs_av1_read_uvlc(ctx, rw, #name, \ &value, range_min, range_max)); \ current->name = value; \ } while (0) #define ns(max_value, name, subs, ...) do { \ - uint32_t value = 0; \ + uint32_t value; \ CHECK(cbs_av1_read_ns(ctx, rw, max_value, #name, \ SUBSCRIPTS(subs, __VA_ARGS__), &value)); \ current->name = value; \ } while (0) #define increment(name, min, max) do { \ - uint32_t value = 0; \ + uint32_t value; \ CHECK(cbs_av1_read_increment(ctx, rw, min, max, #name, &value)); \ current->name = value; \ } while (0) #define subexp(name, max, subs, ...) do { \ - uint32_t value = 0; \ + uint32_t value; \ CHECK(cbs_av1_read_subexp(ctx, rw, max, #name, \ SUBSCRIPTS(subs, __VA_ARGS__), &value)); \ current->name = value; \ @@ -641,16 +623,16 @@ static int cbs_av1_get_relative_dist(const AV1RawSequenceHeader *seq, #define delta_q(name) do { \ uint8_t delta_coded; \ int8_t delta_q; \ - xf(1, name.delta_coded, delta_coded, 0, 1, 0); \ + xf(1, name.delta_coded, delta_coded, 0, 1, 0, ); \ if (delta_coded) \ - xsu(1 + 6, name.delta_q, delta_q, 0); \ + xsu(1 + 6, name.delta_q, delta_q, 0, ); \ else \ delta_q = 0; \ current->name = delta_q; \ } while (0) #define leb128(name) do { \ - uint64_t value = 0; \ + uint64_t value; \ CHECK(cbs_av1_read_leb128(ctx, rw, #name, &value)); \ current->name = value; \ } while (0) @@ -669,7 +651,6 @@ static int cbs_av1_get_relative_dist(const AV1RawSequenceHeader *seq, #undef xf #undef xsu #undef uvlc -#undef leb128 #undef ns #undef increment #undef subexp @@ -690,8 +671,10 @@ static int cbs_av1_get_relative_dist(const AV1RawSequenceHeader *seq, } while (0) #define xsu(width, name, var, subs, ...) do { \ - CHECK(cbs_av1_write_su(ctx, rw, width, #name, \ - SUBSCRIPTS(subs, __VA_ARGS__), var)); \ + CHECK(ff_cbs_write_signed(ctx, rw, width, #name, \ + SUBSCRIPTS(subs, __VA_ARGS__), var, \ + MIN_INT_BITS(width), \ + MAX_INT_BITS(width))); \ } while (0) #define uvlc(name, range_min, range_max) do { \ @@ -717,9 +700,9 @@ static int cbs_av1_get_relative_dist(const AV1RawSequenceHeader *seq, } while (0) #define delta_q(name) do { \ - xf(1, name.delta_coded, current->name != 0, 0, 1, 0); \ + xf(1, name.delta_coded, current->name != 0, 0, 1, 0, ); \ if (current->name) \ - xsu(1 + 6, name.delta_q, current->name, 0); \ + xsu(1 + 6, name.delta_q, current->name, 0, ); \ } while (0) #define leb128(name) do { \ @@ -739,17 +722,17 @@ static int cbs_av1_get_relative_dist(const AV1RawSequenceHeader *seq, #include "cbs_av1_syntax_template.c" -#undef READ +#undef WRITE #undef READWRITE #undef RWContext #undef xf #undef xsu #undef uvlc -#undef leb128 #undef ns #undef increment #undef subexp #undef delta_q +#undef leb128 #undef infer #undef byte_alignment @@ -788,14 +771,13 @@ static int cbs_av1_split_fragment(CodedBitstreamContext *ctx, if (err < 0) goto fail; - if (get_bits_left(&gbc) < 8) { - av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid OBU: fragment " - "too short (%"SIZE_SPECIFIER" bytes).\n", size); - err = AVERROR_INVALIDDATA; - goto fail; - } - if (header.obu_has_size_field) { + if (get_bits_left(&gbc) < 8) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid OBU: fragment " + "too short (%"SIZE_SPECIFIER" bytes).\n", size); + err = AVERROR_INVALIDDATA; + goto fail; + } err = cbs_av1_read_leb128(ctx, &gbc, "obu_size", &obu_size); if (err < 0) goto fail; @@ -835,6 +817,11 @@ static void cbs_av1_free_tile_data(AV1RawTileData *td) av_buffer_unref(&td->data_ref); } +static void cbs_av1_free_padding(AV1RawPadding *pd) +{ + av_buffer_unref(&pd->payload_ref); +} + static void cbs_av1_free_metadata(AV1RawMetadata *md) { switch (md->metadata_type) { @@ -844,7 +831,7 @@ static void cbs_av1_free_metadata(AV1RawMetadata *md) } } -static void cbs_av1_free_obu(void *unit, uint8_t *content) +static void cbs_av1_free_obu(void *opaque, uint8_t *content) { AV1RawOBU *obu = (AV1RawOBU*)content; @@ -861,6 +848,9 @@ static void cbs_av1_free_obu(void *unit, uint8_t *content) case AV1_OBU_METADATA: cbs_av1_free_metadata(&obu->obu.metadata); break; + case AV1_OBU_PADDING: + cbs_av1_free_padding(&obu->obu.padding); + break; } av_freep(&obu); @@ -934,7 +924,7 @@ static int cbs_av1_read_unit(CodedBitstreamContext *ctx, if (obu->header.obu_extension_flag) { priv->temporal_id = obu->header.temporal_id; - priv->spatial_id = obu->header.temporal_id; + priv->spatial_id = obu->header.spatial_id; if (obu->header.obu_type != AV1_OBU_SEQUENCE_HEADER && obu->header.obu_type != AV1_OBU_TEMPORAL_DELIMITER && @@ -952,6 +942,8 @@ static int cbs_av1_read_unit(CodedBitstreamContext *ctx, priv->spatial_id = 0; } + priv->ref = (AV1ReferenceFrameState *)&priv->read_ref; + switch (obu->header.obu_type) { case AV1_OBU_SEQUENCE_HEADER: { @@ -1035,6 +1027,12 @@ static int cbs_av1_read_unit(CodedBitstreamContext *ctx, } break; case AV1_OBU_PADDING: + { + err = cbs_av1_read_padding_obu(ctx, &gbc, &obu->obu.padding); + if (err < 0) + return err; + } + break; default: return AVERROR(ENOSYS); } @@ -1044,9 +1042,14 @@ static int cbs_av1_read_unit(CodedBitstreamContext *ctx, if (obu->obu_size > 0 && obu->header.obu_type != AV1_OBU_TILE_GROUP && + obu->header.obu_type != AV1_OBU_TILE_LIST && obu->header.obu_type != AV1_OBU_FRAME) { - err = cbs_av1_read_trailing_bits(ctx, &gbc, - obu->obu_size * 8 + start_pos - end_pos); + int nb_bits = obu->obu_size * 8 + start_pos - end_pos; + + if (nb_bits <= 0) + return AVERROR_INVALIDDATA; + + err = cbs_av1_read_trailing_bits(ctx, &gbc, nb_bits); if (err < 0) return err; } @@ -1084,6 +1087,8 @@ static int cbs_av1_write_obu(CodedBitstreamContext *ctx, td = NULL; start_pos = put_bits_count(pbc); + priv->ref = (AV1ReferenceFrameState *)&priv->write_ref; + switch (obu->header.obu_type) { case AV1_OBU_SEQUENCE_HEADER: { @@ -1156,6 +1161,12 @@ static int cbs_av1_write_obu(CodedBitstreamContext *ctx, } break; case AV1_OBU_PADDING: + { + err = cbs_av1_write_padding_obu(ctx, pbc, &obu->obu.padding); + if (err < 0) + return err; + } + break; default: return AVERROR(ENOSYS); } @@ -1196,66 +1207,19 @@ static int cbs_av1_write_obu(CodedBitstreamContext *ctx, return AVERROR(ENOSPC); if (obu->obu_size > 0) { - memmove(priv->write_buffer + data_pos, - priv->write_buffer + start_pos, header_size); + memmove(pbc->buf + data_pos, + pbc->buf + start_pos, header_size); skip_put_bytes(pbc, header_size); if (td) { - memcpy(priv->write_buffer + data_pos + header_size, + memcpy(pbc->buf + data_pos + header_size, td->data, td->data_size); skip_put_bytes(pbc, td->data_size); } } - return 0; -} - -static int cbs_av1_write_unit(CodedBitstreamContext *ctx, - CodedBitstreamUnit *unit) -{ - CodedBitstreamAV1Context *priv = ctx->priv_data; - PutBitContext pbc; - int err; - - if (!priv->write_buffer) { - // Initial write buffer size is 1MB. - priv->write_buffer_size = 1024 * 1024; - - reallocate_and_try_again: - err = av_reallocp(&priv->write_buffer, priv->write_buffer_size); - if (err < 0) { - av_log(ctx->log_ctx, AV_LOG_ERROR, "Unable to allocate a " - "sufficiently large write buffer (last attempt " - "%"SIZE_SPECIFIER" bytes).\n", priv->write_buffer_size); - return err; - } - } - - init_put_bits(&pbc, priv->write_buffer, priv->write_buffer_size); - - err = cbs_av1_write_obu(ctx, unit, &pbc); - if (err == AVERROR(ENOSPC)) { - // Overflow. - priv->write_buffer_size *= 2; - goto reallocate_and_try_again; - } - if (err < 0) - return err; - - // Overflow but we didn't notice. - av_assert0(put_bits_count(&pbc) <= 8 * priv->write_buffer_size); - // OBU data must be byte-aligned. - av_assert0(put_bits_count(&pbc) % 8 == 0); - - unit->data_size = put_bits_count(&pbc) / 8; - flush_put_bits(&pbc); - - err = ff_cbs_alloc_unit_data(ctx, unit, unit->data_size); - if (err < 0) - return err; - - memcpy(unit->data, priv->write_buffer, unit->data_size); + av_assert0(put_bits_count(pbc) % 8 == 0); return 0; } @@ -1294,8 +1258,6 @@ static void cbs_av1_close(CodedBitstreamContext *ctx) av_buffer_unref(&priv->sequence_header_ref); av_buffer_unref(&priv->frame_header_ref); - - av_freep(&priv->write_buffer); } const CodedBitstreamType ff_cbs_type_av1 = { @@ -1305,7 +1267,7 @@ const CodedBitstreamType ff_cbs_type_av1 = { .split_fragment = &cbs_av1_split_fragment, .read_unit = &cbs_av1_read_unit, - .write_unit = &cbs_av1_write_unit, + .write_unit = &cbs_av1_write_obu, .assemble_fragment = &cbs_av1_assemble_fragment, .close = &cbs_av1_close,