diff --git a/libavcodec/cbs_av1.c b/libavcodec/cbs_av1.c
index 302e1f38f5..0c958c81c2 100644
--- a/libavcodec/cbs_av1.c
+++ b/libavcodec/cbs_av1.c
@@ -22,6 +22,7 @@
 
 #include "cbs.h"
 #include "cbs_internal.h"
+#include "cbs_metadata.h"
 #include "cbs_av1.h"
 #include "internal.h"
 
@@ -1267,6 +1268,143 @@ static void cbs_av1_close(CodedBitstreamContext *ctx)
     av_buffer_unref(&priv->frame_header_ref);
 }
 
+static int cbs_av1_find_metadata_unit(CodedBitstreamFragment *tu,
+                                      uint64_t metadata_type,
+                                      CodedBitstreamUnit **iter)
+{
+    int i, found;
+
+    found = 0;
+    for (i = 0; i < tu->nb_units; i++) {
+        CodedBitstreamUnit *unit = &tu->units[i];
+        AV1RawOBU *obu = unit->content;
+
+        if (!obu)
+            continue;
+
+        if (obu->header.obu_type == AV1_OBU_METADATA) {
+            if (!*iter || found) {
+                *iter = unit;
+                return 0;
+            }
+            if (unit == *iter)
+                found = 1;
+        }
+    }
+
+    return AVERROR(ENOENT);
+}
+
+static uint64_t cbs_av1_find_metadata_type(enum CBSMetadataType type)
+{
+    struct {
+        enum CBSMetadataType cbs_type;
+        uint64_t av1_type;
+    } map[] = {
+    };
+
+    for (int i = 0; i < FF_ARRAY_ELEMS(map); i++) {
+        if (map[i].cbs_type == type)
+            return map[i].av1_type;
+    }
+    return 0;
+}
+
+static void cbs_av1_delete_metadata_type(CodedBitstreamFragment *tu,
+                                         uint64_t metadata_type)
+{
+    int err;
+    while (1) {
+        CodedBitstreamUnit *unit = NULL;
+        err = cbs_av1_find_metadata_unit(tu, metadata_type, &unit);
+        if (err < 0)
+            break;
+        ff_cbs_delete_unit(tu, unit - tu->units);
+    }
+}
+
+static int cbs_av1_remove_metadata(CodedBitstreamContext *ctx,
+                                   CodedBitstreamFragment *tu,
+                                   enum CBSMetadataType type)
+{
+    uint64_t metadata_type;
+
+    metadata_type = cbs_av1_find_metadata_type(type);
+    if (metadata_type == 0)
+        return AVERROR(EINVAL);
+
+    cbs_av1_delete_metadata_type(tu, metadata_type);
+    return 0;
+}
+
+static int cbs_av1_insert_metadata(CodedBitstreamContext *ctx,
+                                   CodedBitstreamFragment *tu,
+                                   enum CBSMetadataType type,
+                                   const void *data)
+{
+    AVBufferRef *md_buf;
+    AV1RawOBU *obu;
+    uint64_t metadata_type;
+    int err;
+
+    metadata_type = cbs_av1_find_metadata_type(type);
+    if (metadata_type == 0)
+        return AVERROR(EINVAL);
+
+    md_buf = av_buffer_allocz(sizeof(AV1RawOBU));
+    if (!md_buf)
+        return AVERROR(ENOMEM);
+
+    obu = (AV1RawOBU*)md_buf->data;
+
+    obu->header = (AV1RawOBUHeader) {
+        .obu_type = AV1_OBU_METADATA,
+    };
+    obu->obu.metadata.metadata_type = metadata_type;
+
+    switch (metadata_type) {
+    default:
+        av_assert0(0);
+    }
+
+    cbs_av1_delete_metadata_type(tu, metadata_type);
+
+    err = ff_cbs_insert_unit_content(tu, -1, AV1_OBU_METADATA,
+                                     obu, md_buf);
+    av_buffer_unref(&md_buf);
+    return err;
+}
+
+static int cbs_av1_extract_metadata(CodedBitstreamContext *ctx,
+                                    CodedBitstreamFragment *tu,
+                                    enum CBSMetadataType type,
+                                    void *data)
+{
+    CodedBitstreamUnit *unit;
+    AV1RawOBU *obu;
+    uint64_t metadata_type;
+    int err;
+
+    metadata_type = cbs_av1_find_metadata_type(type);
+    if (metadata_type == 0)
+        return AVERROR(EINVAL);
+
+    unit = NULL;
+    err = cbs_av1_find_metadata_unit(tu, metadata_type, &unit);
+    if (err < 0) {
+        // No metadata with that type found.
+        return err;
+    }
+    obu = unit->content;
+
+    switch (metadata_type) {
+    default:
+        av_assert0(0);
+    }
+
+    return 0;
+}
+
 static void cbs_av1_free_metadata(void *unit, uint8_t *content)
 {
     AV1RawOBU *obu = (AV1RawOBU*)content;
@@ -1333,4 +1471,8 @@ const CodedBitstreamType ff_cbs_type_av1 = {
 
     .flush             = &cbs_av1_flush,
     .close             = &cbs_av1_close,
+
+    .insert_metadata   = &cbs_av1_insert_metadata,
+    .remove_metadata   = &cbs_av1_remove_metadata,
+    .extract_metadata  = &cbs_av1_extract_metadata,
 };
