|
|
|
@ -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 }, |
|
|
|
|