[FFmpeg-devel] [PATCH] lavf/mxfdec: handle identification metadata

Matthieu Bouron matthieu.bouron at gmail.com
Fri Mar 29 20:21:37 CET 2013


---
 libavformat/mxfdec.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 131 insertions(+)

diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index 4580e1b..fa1a0fe 100644
--- a/libavformat/mxfdec.c
+++ b/libavformat/mxfdec.c
@@ -1619,6 +1619,136 @@ fail_and_free:
     return ret;
 }
 
+static int mxf_read_uid(AVIOContext *pb, int size, UID uid)
+{
+    if (size != 16)
+        return AVERROR(EINVAL);
+
+    avio_read(pb, uid, size);
+
+    return 0;
+}
+
+static int mxf_read_utf16_string(AVIOContext *pb, int size, char** str)
+{
+    int ret;
+    char *buf;
+    if (size <= 0)
+        return AVERROR(EINVAL);
+
+    buf = av_malloc(size + 1);
+    if (!buf)
+        return AVERROR(ENOMEM);
+
+    if ((ret = avio_get_str16be(pb, size, buf, size + 1)) < 0) {
+        av_free(buf);
+        return ret;
+    }
+
+    avio_skip(pb, size - ret);
+    *str = buf;
+
+    return ret;
+}
+
+static int mxf_read_timestamp(AVIOContext *pb, int size, uint64_t *ts)
+{
+    if (size != 8)
+        return AVERROR(EINVAL);
+
+    *ts = avio_rb64(pb);
+    return 0;
+}
+
+
+static int mxf_uid_to_str(UID uid, char **str)
+{
+    int i;
+    char *p;
+    p = *str = av_mallocz(sizeof(UID) * 2 + 1);
+    if (!p)
+        return AVERROR(ENOMEM);
+    for (i = 0; i < sizeof(UID); i++) {
+        snprintf(p, 2 + 1, "%.2x", uid[i]);
+        p += 2;
+    }
+    return 0;
+}
+
+static int mxf_timestamp_to_str(uint64_t timestamp, char **str)
+{
+    struct tm time;
+    time.tm_year = (timestamp >> 48) - 1900;
+    time.tm_mon  = (timestamp >> 48 & 0xF) - 1;
+    time.tm_mday = (timestamp >> 32 & 0xF);
+    time.tm_hour = (timestamp >> 24 & 0XF);
+    time.tm_min  = (timestamp >> 16 & 0xF);
+    time.tm_sec  = (timestamp >> 8  & 0xF);
+
+    *str = av_mallocz(32);
+    if (!*str)
+        return AVERROR(ENOMEM);
+    strftime(*str, 32, "%F %T", &time);
+
+    return 0;
+}
+
+#define SET_STR_METADATA(name, str) \
+    if ((ret = mxf_read_utf16_string(pb, size, &str)) < 0) \
+        return ret; \
+    av_dict_set(&s->metadata, name, str, AV_DICT_DONT_STRDUP_VAL);
+
+#define SET_UID_METADATA(name, var, str) \
+    if ((ret = mxf_read_uid(pb, size, var)) < 0) \
+        return ret; \
+    if ((ret = mxf_uid_to_str(var, &str)) < 0) \
+        return ret; \
+    av_dict_set(&s->metadata, name, str, AV_DICT_DONT_STRDUP_VAL);
+
+#define SET_TS_METADATA(name, var, str) \
+    if ((ret = mxf_read_timestamp(pb, size, &var)) < 0) \
+        return ret; \
+    if ((ret = mxf_timestamp_to_str(var, &str)) < 0) \
+        return ret; \
+    av_dict_set(&s->metadata, name, str, AV_DICT_DONT_STRDUP_VAL);
+
+static int mxf_read_identification_metadata(void *arg, AVIOContext *pb, int tag, int size, UID _uid, int64_t klv_offset)
+{
+    MXFContext *mxf = arg;
+    AVFormatContext *s = mxf->fc;
+    int ret;
+    UID uid = { 0 };
+    char *str = NULL;
+    uint64_t ts;
+    switch (tag) {
+    case 0x3C0A:
+        SET_UID_METADATA("uid", uid, str)
+    break;
+    case 0x3C09:
+        SET_UID_METADATA("generation_uid", uid, str)
+    break;
+    case 0x3C01:
+        SET_STR_METADATA("company_name", str)
+    break;
+    case 0x3C02:
+        SET_STR_METADATA("product_name", str)
+    break;
+    case 0x3C04:
+        SET_STR_METADATA("product_version", str)
+    break;
+    case 0x3C05:
+        SET_UID_METADATA("product_uid", uid, str)
+    break;
+    case 0x3C06:
+        SET_TS_METADATA("modification_date", ts, str)
+    break;
+    case 0x3C08:
+        SET_STR_METADATA("application_platform", str)
+    break;
+    }
+    return 0;
+}
+
 static const MXFMetadataReadTableEntry mxf_metadata_read_table[] = {
     { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x05,0x01,0x00 }, mxf_read_primer_pack },
     { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x02,0x01,0x00 }, mxf_read_partition_pack },
@@ -1631,6 +1761,7 @@ static const MXFMetadataReadTableEntry mxf_metadata_read_table[] = {
     { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x03,0x04,0x00 }, mxf_read_partition_pack },
     { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x04,0x02,0x00 }, mxf_read_partition_pack },
     { { 0x06,0x0E,0x2B,0x34,0x02,0x05,0x01,0x01,0x0d,0x01,0x02,0x01,0x01,0x04,0x04,0x00 }, mxf_read_partition_pack },
+    { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0D,0x01,0x01,0x01,0x01,0x01,0x30,0x00 }, mxf_read_identification_metadata },
     { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x18,0x00 }, mxf_read_content_storage, 0, AnyType },
     { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x37,0x00 }, mxf_read_source_package, sizeof(MXFPackage), SourcePackage },
     { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x36,0x00 }, mxf_read_material_package, sizeof(MXFPackage), MaterialPackage },
-- 
1.8.2



More information about the ffmpeg-devel mailing list