[FFmpeg-devel] [PATCH v1 2/2] avcodec/h265_metadata_bsf: add option to insert a string as SEI unregistered user data
lance.lmwang at gmail.com
lance.lmwang at gmail.com
Wed Dec 11 17:02:04 EET 2019
From: Limin Wang <lance.lmwang at gmail.com>
Signed-off-by: Limin Wang <lance.lmwang at gmail.com>
---
doc/bitstream_filters.texi | 8 ++++++
libavcodec/h265_metadata_bsf.c | 65 +++++++++++++++++++++++++++++++++++++++++-
2 files changed, 72 insertions(+), 1 deletion(-)
diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi
index 8fe5b3a..81b41d7 100644
--- a/doc/bitstream_filters.texi
+++ b/doc/bitstream_filters.texi
@@ -376,6 +376,14 @@ The argument must be the name of a level (for example, @samp{5.1}), a
or the special name @samp{auto} indicating that the filter should
attempt to guess the level from the input stream properties.
+ at item sei_user_data
+Insert a string as SEI unregistered user data. The argument must
+be of the form @emph{UUID+string}, where the UUID is as a 32-character
+(16 bytes) hexadecimal string possibly separated by hyphens, and the
+string can be anything.
+
+For example, @samp{086f3693-b7b3-4f2c-9653-21492feee5b8+hello} will
+insert the string ``hello'' associated with the given 32-bit UUID.
@end table
@section hevc_mp4toannexb
diff --git a/libavcodec/h265_metadata_bsf.c b/libavcodec/h265_metadata_bsf.c
index b3a1fda..f32ddf0 100644
--- a/libavcodec/h265_metadata_bsf.c
+++ b/libavcodec/h265_metadata_bsf.c
@@ -16,6 +16,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "libavutil/avstring.h"
#include "libavutil/common.h"
#include "libavutil/opt.h"
@@ -23,6 +24,7 @@
#include "cbs.h"
#include "cbs_h265.h"
#include "hevc.h"
+#include "hevc_sei.h"
#include "h265_profile_level.h"
enum {
@@ -65,6 +67,8 @@ typedef struct H265MetadataContext {
int crop_top;
int crop_bottom;
+ const char *sei_user_data;
+
int level;
int level_guess;
int level_warned;
@@ -340,7 +344,7 @@ static int h265_metadata_filter(AVBSFContext *bsf, AVPacket *pkt)
{
H265MetadataContext *ctx = bsf->priv_data;
CodedBitstreamFragment *au = &ctx->access_unit;
- int err, i;
+ int err, i, j, has_sps = 0, has_vps = 0;
err = ff_bsf_get_packet_ref(bsf, pkt);
if (err < 0)
@@ -410,11 +414,67 @@ static int h265_metadata_filter(AVBSFContext *bsf, AVPacket *pkt)
err = h265_metadata_update_vps(bsf, au->units[i].content);
if (err < 0)
goto fail;
+ has_vps = 1;
}
if (au->units[i].type == HEVC_NAL_SPS) {
err = h265_metadata_update_sps(bsf, au->units[i].content);
if (err < 0)
goto fail;
+ has_sps = 1;
+ }
+ }
+
+ // Only insert the SEI in access units containing SPSs or VPSs
+ if (ctx->sei_user_data && (has_sps || has_vps)) {
+ H265RawSEIPayload payload = {
+ .payload_type = HEVC_SEI_TYPE_USER_DATA_UNREGISTERED,
+ };
+ H265RawSEIUserDataUnregistered *udu =
+ &payload.payload.user_data_unregistered;
+
+ for (i = j = 0; j < 32 && ctx->sei_user_data[i]; i++) {
+ int c, v;
+ c = ctx->sei_user_data[i];
+ if (c == '-') {
+ continue;
+ } else if (av_isxdigit(c)) {
+ c = av_tolower(c);
+ v = (c <= '9' ? c - '0' : c - 'a' + 10);
+ } else {
+ goto invalid_user_data;
+ }
+ if (i & 1)
+ udu->uuid_iso_iec_11578[j / 2] |= v;
+ else
+ udu->uuid_iso_iec_11578[j / 2] = v << 4;
+ ++j;
+ }
+ if (j == 32 && ctx->sei_user_data[i] == '+') {
+ size_t len = strlen(ctx->sei_user_data + i + 1);
+
+ udu->data_ref = av_buffer_alloc(len + 1);
+ if (!udu->data_ref) {
+ err = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ udu->data = udu->data_ref->data;
+ udu->data_length = len + 1;
+ memcpy(udu->data, ctx->sei_user_data + i + 1, len + 1);
+
+ err = ff_cbs_h265_add_sei_prefix_message(ctx->cbc, au, &payload);
+ if (err < 0) {
+ av_log(bsf, AV_LOG_ERROR, "Failed to add user data SEI "
+ "message to access unit.\n");
+ goto fail;
+ }
+
+ } else {
+invalid_user_data:
+ av_log(bsf, AV_LOG_ERROR, "Invalid user data: "
+ "must be \"UUID+string\".\n");
+ err = AVERROR(EINVAL);
+ goto fail;
}
}
@@ -547,6 +607,9 @@ static const AVOption h265_metadata_options[] = {
OFFSET(crop_bottom), AV_OPT_TYPE_INT,
{ .i64 = -1 }, -1, HEVC_MAX_HEIGHT, FLAGS },
+ { "sei_user_data", "Insert SEI user data (UUID+string)",
+ OFFSET(sei_user_data), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS },
+
{ "level", "Set level (tables A.6 and A.7)",
OFFSET(level), AV_OPT_TYPE_INT,
{ .i64 = LEVEL_UNSET }, LEVEL_UNSET, 0xff, FLAGS, "level" },
--
2.9.5
More information about the ffmpeg-devel
mailing list