[FFmpeg-devel] [PATCH v2 04/18] cbs_sei: Implement metadata manipulation for SEI codecs
Mark Thompson
sw at jkqxz.net
Sun Feb 21 21:51:11 EET 2021
---
libavcodec/cbs_h2645.c | 8 ++++
libavcodec/cbs_sei.c | 94 ++++++++++++++++++++++++++++++++++++++++++
libavcodec/cbs_sei.h | 35 ++++++++++++++++
3 files changed, 137 insertions(+)
diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c
index 0c591871d4..cb0005cc1b 100644
--- a/libavcodec/cbs_h2645.c
+++ b/libavcodec/cbs_h2645.c
@@ -1487,6 +1487,10 @@ const CodedBitstreamType ff_cbs_type_h264 = {
.flush = &cbs_h264_flush,
.close = &cbs_h264_close,
+
+ .insert_metadata = &ff_cbs_sei_insert_metadata,
+ .remove_metadata = &ff_cbs_sei_remove_metadata,
+ .extract_metadata = &ff_cbs_sei_extract_metadata,
};
const CodedBitstreamType ff_cbs_type_h265 = {
@@ -1503,6 +1507,10 @@ const CodedBitstreamType ff_cbs_type_h265 = {
.flush = &cbs_h265_flush,
.close = &cbs_h265_close,
+
+ .insert_metadata = &ff_cbs_sei_insert_metadata,
+ .remove_metadata = &ff_cbs_sei_remove_metadata,
+ .extract_metadata = &ff_cbs_sei_extract_metadata,
};
static const SEIMessageTypeDescriptor cbs_sei_common_types[] = {
diff --git a/libavcodec/cbs_sei.c b/libavcodec/cbs_sei.c
index 14f1cae506..83bb5cca55 100644
--- a/libavcodec/cbs_sei.c
+++ b/libavcodec/cbs_sei.c
@@ -21,6 +21,7 @@
#include "cbs_h264.h"
#include "cbs_h265.h"
#include "cbs_sei.h"
+#include "cbs_metadata.h"
static void cbs_free_user_data_registered(void *opaque, uint8_t *data)
{
@@ -372,3 +373,96 @@ void ff_cbs_sei_delete_message_type(CodedBitstreamContext *ctx,
}
}
}
+
+typedef struct SEIMetadata {
+ enum CBSMetadataType cbs_type;
+ int sei_type;
+} SEIMetadata;
+
+static const SEIMetadata cbs_sei_metadata[] = {
+};
+
+static const SEIMessageTypeDescriptor *cbs_sei_find_type_from_metadata
+ (CodedBitstreamContext *ctx, enum CBSMetadataType metadata_type)
+{
+ const SEIMetadata *metadata;
+
+ metadata = NULL;
+ for (int i = 0; i < FF_ARRAY_ELEMS(cbs_sei_metadata); i++) {
+ if (metadata_type == cbs_sei_metadata[i].cbs_type) {
+ metadata = &cbs_sei_metadata[i];
+ break;
+ }
+ }
+ if (metadata)
+ return ff_cbs_sei_find_type(ctx, metadata->sei_type);
+ else
+ return NULL;
+}
+
+int ff_cbs_sei_insert_metadata(CodedBitstreamContext *ctx,
+ CodedBitstreamFragment *au,
+ enum CBSMetadataType metadata_type,
+ const void *data)
+{
+ const SEIMessageTypeDescriptor *desc;
+ AVBufferRef *payload_buf;
+ int err;
+
+ desc = cbs_sei_find_type_from_metadata(ctx, metadata_type);
+ if (!desc || !desc->fill)
+ return AVERROR(EINVAL);
+
+ payload_buf = av_buffer_alloc(desc->size);
+ if (!payload_buf)
+ return AVERROR(ENOMEM);
+
+ desc->fill(payload_buf->data, data);
+
+ // All the metadata SEI messages must be unique in an access unit,
+ // so delete any existing ones of the given type.
+ ff_cbs_sei_delete_message_type(ctx, au, desc->type);
+
+ err = ff_cbs_sei_add_message(ctx, au, desc->prefix, desc->type,
+ payload_buf->data, payload_buf);
+ av_buffer_unref(&payload_buf);
+ return err;
+}
+
+int ff_cbs_sei_remove_metadata(CodedBitstreamContext *ctx,
+ CodedBitstreamFragment *au,
+ enum CBSMetadataType metadata_type)
+{
+ const SEIMessageTypeDescriptor *desc;
+
+ desc = cbs_sei_find_type_from_metadata(ctx, metadata_type);
+ if (!desc)
+ return AVERROR(EINVAL);
+
+ ff_cbs_sei_delete_message_type(ctx, au, desc->type);
+ return 0;
+}
+
+int ff_cbs_sei_extract_metadata(CodedBitstreamContext *ctx,
+ CodedBitstreamFragment *au,
+ enum CBSMetadataType metadata_type,
+ void *data)
+{
+ const SEIMessageTypeDescriptor *desc;
+ SEIRawMessage *message;
+ int err;
+
+ desc = cbs_sei_find_type_from_metadata(ctx, metadata_type);
+ if (!desc || !desc->extract)
+ return AVERROR(EINVAL);
+
+ message = NULL;
+ err = ff_cbs_sei_find_message(ctx, au, desc->type, &message);
+ if (err < 0) {
+ // No message of the given type found.
+ return err;
+ }
+
+ desc->extract(data, message->payload);
+ return 0;
+}
diff --git a/libavcodec/cbs_sei.h b/libavcodec/cbs_sei.h
index c7a7a95be0..4fbcb6bfc0 100644
--- a/libavcodec/cbs_sei.h
+++ b/libavcodec/cbs_sei.h
@@ -110,6 +110,8 @@ typedef int (*SEIMessageWriteFunction)(CodedBitstreamContext *ctx,
void *current,
SEIMessageState *sei);
+typedef void (*SEIConvertFunction)(void *dst, const void *src);
+
typedef struct SEIMessageTypeDescriptor {
// Payload type for the message. (-1 in this field ends a list.)
int type;
@@ -123,6 +125,10 @@ typedef struct SEIMessageTypeDescriptor {
SEIMessageReadFunction read;
// Write bitstream from SEI message.
SEIMessageWriteFunction write;
+ // Fill SEI structure from AV metadata.
+ SEIConvertFunction fill;
+ // Extract SEI metadata to AV structure.
+ SEIConvertFunction extract;
} SEIMessageTypeDescriptor;
// Macro for the read/write pair. The clumsy cast is needed because the
@@ -132,6 +138,10 @@ typedef struct SEIMessageTypeDescriptor {
.read = (SEIMessageReadFunction) cbs_ ## codec ## _read_ ## name, \
.write = (SEIMessageWriteFunction)cbs_ ## codec ## _write_ ## name
+#define SEI_MESSAGE_FE(codec, name) \
+ .fill = (SEIConvertFunction)cbs_ ## codec ## _fill_ ## name, \
+ .extract = (SEIConvertFunction)cbs_ ## codec ## _extract_ ## name
+
// End-of-list sentinel element.
#define SEI_MESSAGE_TYPE_END { .type = -1 }
@@ -189,6 +199,8 @@ int ff_cbs_sei_find_message(CodedBitstreamContext *ctx,
uint32_t payload_type,
SEIRawMessage **message);
+enum CBSMetadataType;
+
/**
* Delete all messages with the given payload type from an access unit.
*/
@@ -196,4 +208,27 @@ void ff_cbs_sei_delete_message_type(CodedBitstreamContext *ctx,
CodedBitstreamFragment *au,
uint32_t payload_type);
+/**
+ * Insert metadata into an access unit.
+ */
+int ff_cbs_sei_insert_metadata(CodedBitstreamContext *ctx,
+ CodedBitstreamFragment *au,
+ enum CBSMetadataType type,
+ const void *data);
+
+/**
+ * Remove metadata from an access unit.
+ */
+int ff_cbs_sei_remove_metadata(CodedBitstreamContext *ctx,
+ CodedBitstreamFragment *au,
+ enum CBSMetadataType type);
+
+/**
+ * Extract metadata from an access unit.
+ */
+int ff_cbs_sei_extract_metadata(CodedBitstreamContext *ctx,
+ CodedBitstreamFragment *au,
+ enum CBSMetadataType type,
+ void *data);
+
#endif /* AVCODEC_CBS_SEI_H */
--
2.30.0
More information about the ffmpeg-devel
mailing list