@@ -776,13 +776,15 @@ static int cbs_av1_get_relative_dist(const AV1RawSequenceHeader *seq,
#undef byte_alignment
-static int cbs_av1_split_fragment(CodedBitstreamContext *ctx,
- CodedBitstreamFragment *frag,
- int header)
+typedef int (*cbs_av1_split_obu_callback)(CodedBitstreamContext *ctx,
+ void *priv, int obu_type,
+ const uint8_t *data, size_t size);
+
+static int cbs_av1_split_obus(CodedBitstreamContext *ctx,
+ void *priv, cbs_av1_split_obu_callback cb,
+ const uint8_t *data, size_t size)
{
GetBitContext gbc;
- uint8_t *data;
- size_t size;
uint64_t obu_length;
int pos, err, trace;
@@ -790,9 +792,6 @@ static int cbs_av1_split_fragment(CodedBitstreamContext *ctx,
trace = ctx->trace_enable;
ctx->trace_enable = 0;
- data = frag->data;
- size = frag->data_size;
-
if (INT_MAX / 8 < size) {
av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid fragment: "
"too large (%"SIZE_SPECIFIER" bytes).\n", size);
@@ -837,8 +836,7 @@ static int cbs_av1_split_fragment(CodedBitstreamContext *ctx,
goto fail;
}
- err = ff_cbs_insert_unit_data(ctx, frag, -1, header.obu_type,
- data, obu_length, frag->data_ref);
+ err = cb(ctx, priv, header.obu_type, data, obu_length);
if (err < 0)
goto fail;
@@ -852,6 +850,23 @@ fail:
return err;
}
+static int cbs_av1_insert_obu(CodedBitstreamContext *ctx,
+ void *priv, int obu_type,
+ const uint8_t *data, size_t size)
+{
+ CodedBitstreamFragment *frag = priv;
+ return ff_cbs_insert_unit_data(ctx, frag, -1, obu_type,
+ (uint8_t*)data, size, frag->data_ref);
+}
+
+static int cbs_av1_split_fragment(CodedBitstreamContext *ctx,
+ CodedBitstreamFragment *frag,
+ int header)
+{
+ return cbs_av1_split_obus(ctx, frag, &cbs_av1_insert_obu,
+ frag->data, frag->data_size);
+}
+
static void cbs_av1_free_tile_data(AV1RawTileData *td)
{
av_buffer_unref(&td->data_ref);
@@ -895,6 +910,12 @@ static int cbs_av1_ref_tile_data(CodedBitstreamContext *ctx,
{
int pos;
+ if (!unit->data_ref) {
+ // Not refcounted - only parsing headers, so tile data will
+ // not be needed.
+ return 0;
+ }
+
pos = get_bits_count(gbc);
if (pos >= 8 * unit->data_size) {
av_log(ctx->log_ctx, AV_LOG_ERROR, "Bitstream ended before "
@@ -1324,6 +1345,52 @@ static void cbs_av1_close(CodedBitstreamContext *ctx)
av_freep(&priv->write_buffer);
}
+static int cbs_av1_parse_obu(CodedBitstreamContext *ctx,
+ void *priv, int obu_type,
+ const uint8_t *data, size_t data_size)
+{
+ CodedBitstreamUnit unit;
+ int err;
+
+ // These OBU types will not affect parsing.
+ if (obu_type == AV1_OBU_METADATA ||
+ obu_type == AV1_OBU_TILE_LIST ||
+ obu_type == AV1_OBU_PADDING)
+ return 0;
+
+ unit = (CodedBitstreamUnit) {
+ .type = obu_type,
+ .data = (uint8_t*)data,
+ .data_size = data_size,
+ };
+
+ err = cbs_av1_read_unit(ctx, &unit);
+ if (err >= 0 && priv) {
+ AV1RawOBU *obu = unit.content;
+ switch (obu->header.obu_type) {
+ case AV1_OBU_FRAME_HEADER:
+ case AV1_OBU_REDUNDANT_FRAME_HEADER:
+ memcpy(priv, &obu->obu.frame_header,
+ sizeof(obu->obu.frame_header));
+ break;
+ case AV1_OBU_FRAME:
+ memcpy(priv, &obu->obu.frame.header,
+ sizeof(obu->obu.frame.header));
+ break;
+ }
+ }
+
+ av_buffer_unref(&unit.content_ref);
+
+ return err;
+}
+
+static int cbs_av1_parse_headers(CodedBitstreamContext *ctx, void *header,
+ const uint8_t *data, size_t size)
+{
+ return cbs_av1_split_obus(ctx, header, &cbs_av1_parse_obu, data, size);
+}
+
const CodedBitstreamType ff_cbs_type_av1 = {
.codec_id = AV_CODEC_ID_AV1,
@@ -1335,4 +1402,6 @@ const CodedBitstreamType ff_cbs_type_av1 = {
.assemble_fragment = &cbs_av1_assemble_fragment,
.close = &cbs_av1_close,
+
+ .parse_headers = &cbs_av1_parse_headers,
};