| @@ -1619,6 +1619,120 @@ fail_and_free: | |||
| return ret; | |||
| } | |||
| static int mxf_read_utf16_string(AVIOContext *pb, int size, char** str) | |||
| { | |||
| int ret; | |||
| size_t buf_size; | |||
| if (size < 0) | |||
| return AVERROR(EINVAL); | |||
| buf_size = size + size/2 + 1; | |||
| *str = av_malloc(buf_size); | |||
| if (!*str) | |||
| return AVERROR(ENOMEM); | |||
| if ((ret = avio_get_str16be(pb, size, *str, buf_size)) < 0) { | |||
| av_freep(str); | |||
| return ret; | |||
| } | |||
| return ret; | |||
| } | |||
| static int mxf_uid_to_str(UID uid, char **str) | |||
| { | |||
| int i; | |||
| char *p; | |||
| p = *str = av_mallocz(sizeof(UID) * 2 + 4 + 1); | |||
| if (!p) | |||
| return AVERROR(ENOMEM); | |||
| for (i = 0; i < sizeof(UID); i++) { | |||
| snprintf(p, 2 + 1, "%.2x", uid[i]); | |||
| p += 2; | |||
| if (i == 3 || i == 5 || i == 7 || i == 9) { | |||
| snprintf(p, 1 + 1, "-"); | |||
| p++; | |||
| } | |||
| } | |||
| 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(pb, name, str) do { \ | |||
| if ((ret = mxf_read_utf16_string(pb, size, &str)) < 0) \ | |||
| return ret; \ | |||
| av_dict_set(&s->metadata, name, str, AV_DICT_DONT_STRDUP_VAL); \ | |||
| } while (0) | |||
| #define SET_UID_METADATA(pb, name, var, str) do { \ | |||
| avio_read(pb, var, 16); \ | |||
| if ((ret = mxf_uid_to_str(var, &str)) < 0) \ | |||
| return ret; \ | |||
| av_dict_set(&s->metadata, name, str, AV_DICT_DONT_STRDUP_VAL); \ | |||
| } while (0) | |||
| #define SET_TS_METADATA(pb, name, var, str) do { \ | |||
| var = avio_rb64(pb); \ | |||
| if ((ret = mxf_timestamp_to_str(var, &str)) < 0) \ | |||
| return ret; \ | |||
| av_dict_set(&s->metadata, name, str, AV_DICT_DONT_STRDUP_VAL); \ | |||
| } while (0) | |||
| 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 0x3C01: | |||
| SET_STR_METADATA(pb, "company_name", str); | |||
| break; | |||
| case 0x3C02: | |||
| SET_STR_METADATA(pb, "product_name", str); | |||
| break; | |||
| case 0x3C04: | |||
| SET_STR_METADATA(pb, "product_version", str); | |||
| break; | |||
| case 0x3C05: | |||
| SET_UID_METADATA(pb, "product_uid", uid, str); | |||
| break; | |||
| case 0x3C06: | |||
| SET_TS_METADATA(pb, "modification_date", ts, str); | |||
| break; | |||
| case 0x3C08: | |||
| SET_STR_METADATA(pb, "application_platform", str); | |||
| break; | |||
| case 0x3C09: | |||
| SET_UID_METADATA(pb, "generation_uid", uid, str); | |||
| break; | |||
| case 0x3C0A: | |||
| SET_UID_METADATA(pb, "uid", uid, 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 +1745,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 }, | |||