diff mbox series

[FFmpeg-devel,20/27] cbs: Add interface to allow BSFs easy access to metadata manipulation

Message ID 20210101213537.169546-21-sw@jkqxz.net
State New
Headers show
Series Metadata handling in CBS
Related show

Checks

Context Check Description
andriy/x86_make success Make finished
andriy/x86_make_fate success Make fate finished
andriy/PPC64_make success Make finished
andriy/PPC64_make_fate success Make fate finished

Commit Message

Mark Thompson Jan. 1, 2021, 9:35 p.m. UTC
---
 libavcodec/cbs_bsf.c | 73 ++++++++++++++++++++++++++++++++++++++++++++
 libavcodec/cbs_bsf.h |  6 ++++
 2 files changed, 79 insertions(+)
diff mbox series

Patch

diff --git a/libavcodec/cbs_bsf.c b/libavcodec/cbs_bsf.c
index 429f360014..fe6304a0d4 100644
--- a/libavcodec/cbs_bsf.c
+++ b/libavcodec/cbs_bsf.c
@@ -18,6 +18,7 @@ 
 
 #include "bsf_internal.h"
 #include "cbs_bsf.h"
+#include "cbs_metadata.h"
 
 static int ff_cbs_bsf_update_side_data(AVBSFContext *bsf, AVPacket *pkt)
 {
@@ -159,3 +160,75 @@  void ff_cbs_bsf_close(AVBSFContext *bsf)
     ff_cbs_close(&ctx->input);
     ff_cbs_close(&ctx->output);
 }
+
+int ff_cbs_bsf_apply_metadata(AVBSFContext *bsf,
+                              AVPacket *pkt,
+                              CodedBitstreamFragment *frag,
+                              enum CBSMetadataType type, int action)
+{
+    CBSBSFContext *ctx = bsf->priv_data;
+    const CBSMetadataTypeDescriptor *desc;
+    uint8_t *side_data;
+    size_t size;
+    int err, ignored;
+
+    desc = ff_cbs_metadata_find_type(type);
+    if (!desc)
+        return AVERROR(EINVAL);
+    if (!desc->has_packet_side_data)
+        return AVERROR(EINVAL);
+
+    switch (action) {
+    case BSF_ELEMENT_PASS:
+        // Nothing to do.
+        return 0;
+
+    case BSF_ELEMENT_REMOVE:
+        // Remove all existing instances of the metadata.
+        err = ff_cbs_remove_metadata(ctx->output, frag, type);
+        if (err < 0) {
+            av_log(bsf, AV_LOG_ERROR, "Failed to remove %s metadata "
+                   "from %s.\n", desc->name, ctx->type->fragment_name);
+        }
+        return err;
+
+    case BSF_ELEMENT_INSERT:
+        // Insert matching side-data to replace existing metadata.
+        side_data = av_packet_get_side_data(pkt,
+                                            desc->packet_side_data_type,
+                                            &ignored);
+        if (!side_data) {
+            // No side data of this type.
+            return 0;
+        }
+        err = ff_cbs_insert_metadata(ctx->output, frag, type, side_data);
+        if (err < 0) {
+            av_log(bsf, AV_LOG_ERROR, "Failed to insert %s metadata "
+                   "into %s.\n", desc->name, ctx->type->fragment_name);
+        }
+
+    case BSF_ELEMENT_EXTRACT:
+        // Extract the metadata and attach it to the packet as side-data.
+        side_data = ff_cbs_alloc_metadata(type, &size);
+        if (!side_data)
+            return AVERROR(ENOMEM);
+        err = ff_cbs_extract_metadata(ctx->output, frag, type, side_data);
+        if (err == AVERROR(ENOENT)) {
+            // No metadata of that type.
+            return 0;
+        }
+        if (err < 0) {
+            av_log(bsf, AV_LOG_ERROR, "Failed to extract %s metadata "
+                   "from %s.\n", desc->name, ctx->type->fragment_name);
+            return err;
+        }
+        err = av_packet_add_side_data(pkt, desc->packet_side_data_type,
+                                      side_data, size);
+        if (err < 0)
+            av_free(side_data);
+        return err;
+
+    default:
+        return AVERROR(EINVAL);
+    }
+}
diff --git a/libavcodec/cbs_bsf.h b/libavcodec/cbs_bsf.h
index 8cab3f144c..95cae316b2 100644
--- a/libavcodec/cbs_bsf.h
+++ b/libavcodec/cbs_bsf.h
@@ -55,6 +55,12 @@  int ff_cbs_bsf_filter(AVBSFContext *bsf, AVPacket *pkt);
 int ff_cbs_bsf_init(AVBSFContext *bsf, const CBSBSFType *type);
 void ff_cbs_bsf_close(AVBSFContext *bsf);
 
+enum CBSMetadataType;
+
+int ff_cbs_bsf_apply_metadata(AVBSFContext *bsf,
+                              AVPacket *pkt,
+                              CodedBitstreamFragment *frag,
+                              enum CBSMetadataType type, int action);
 
 // Options for element manipulation.
 enum {