You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-15 14:13:16 +02:00
libavformat/mxfenc: write package name metadata
Previous-version-reviewed-by: Tomas Härdin <tomas.hardin@codemill.se> Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
committed by
Michael Niedermayer
parent
2c8cff2be4
commit
399e31419a
@@ -624,14 +624,61 @@ static void mxf_write_preface(AVFormatContext *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write a local tag containing an ascii string as utf-16
|
* Returns the length of the UTF-16 string, in 16-bit characters, that would result
|
||||||
|
* from decoding the utf-8 string.
|
||||||
|
*/
|
||||||
|
static uint64_t mxf_utf16len(const char *utf8_str)
|
||||||
|
{
|
||||||
|
const uint8_t *q = utf8_str;
|
||||||
|
uint64_t size = 0;
|
||||||
|
while (*q) {
|
||||||
|
uint32_t ch;
|
||||||
|
GET_UTF8(ch, *q++, goto invalid;)
|
||||||
|
if (ch < 0x10000)
|
||||||
|
size++;
|
||||||
|
else
|
||||||
|
size += 2;
|
||||||
|
continue;
|
||||||
|
invalid:
|
||||||
|
av_log(NULL, AV_LOG_ERROR, "Invaid UTF8 sequence in mxf_utf16len\n\n");
|
||||||
|
}
|
||||||
|
size += 1;
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the calculated length a local tag containing an utf-8 string as utf-16
|
||||||
|
*/
|
||||||
|
static int mxf_utf16_local_tag_length(const char *utf8_str)
|
||||||
|
{
|
||||||
|
uint64_t size;
|
||||||
|
|
||||||
|
if (!utf8_str)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
size = mxf_utf16len(utf8_str);
|
||||||
|
if (size >= UINT16_MAX/2) {
|
||||||
|
av_log(NULL, AV_LOG_ERROR, "utf16 local tag size %"PRIx64" invalid (too large), ignoring\n", size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 4 + size * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write a local tag containing an utf-8 string as utf-16
|
||||||
*/
|
*/
|
||||||
static void mxf_write_local_tag_utf16(AVIOContext *pb, int tag, const char *value)
|
static void mxf_write_local_tag_utf16(AVIOContext *pb, int tag, const char *value)
|
||||||
{
|
{
|
||||||
int i, size = strlen(value);
|
uint64_t size = mxf_utf16len(value);
|
||||||
|
|
||||||
|
if (size >= UINT16_MAX/2) {
|
||||||
|
av_log(NULL, AV_LOG_ERROR, "utf16 local tag size %"PRIx64" invalid (too large), ignoring\n", size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mxf_write_local_tag(pb, size*2, tag);
|
mxf_write_local_tag(pb, size*2, tag);
|
||||||
for (i = 0; i < size; i++)
|
avio_put_str16be(pb, value);
|
||||||
avio_wb16(pb, value[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mxf_write_identification(AVFormatContext *s)
|
static void mxf_write_identification(AVFormatContext *s)
|
||||||
@@ -648,7 +695,9 @@ static void mxf_write_identification(AVFormatContext *s)
|
|||||||
|
|
||||||
version = s->flags & AVFMT_FLAG_BITEXACT ?
|
version = s->flags & AVFMT_FLAG_BITEXACT ?
|
||||||
"0.0.0" : AV_STRINGIFY(LIBAVFORMAT_VERSION);
|
"0.0.0" : AV_STRINGIFY(LIBAVFORMAT_VERSION);
|
||||||
length = 84 + (strlen(company)+strlen(product)+strlen(version))*2; // utf-16
|
length = 72 + mxf_utf16_local_tag_length(company) +
|
||||||
|
mxf_utf16_local_tag_length(product) +
|
||||||
|
mxf_utf16_local_tag_length(version);
|
||||||
klv_encode_ber_length(pb, length);
|
klv_encode_ber_length(pb, length);
|
||||||
|
|
||||||
// write uid
|
// write uid
|
||||||
@@ -659,7 +708,6 @@ static void mxf_write_identification(AVFormatContext *s)
|
|||||||
// write generation uid
|
// write generation uid
|
||||||
mxf_write_local_tag(pb, 16, 0x3C09);
|
mxf_write_local_tag(pb, 16, 0x3C09);
|
||||||
mxf_write_uuid(pb, Identification, 1);
|
mxf_write_uuid(pb, Identification, 1);
|
||||||
|
|
||||||
mxf_write_local_tag_utf16(pb, 0x3C01, company); // Company Name
|
mxf_write_local_tag_utf16(pb, 0x3C01, company); // Company Name
|
||||||
mxf_write_local_tag_utf16(pb, 0x3C02, product); // Product Name
|
mxf_write_local_tag_utf16(pb, 0x3C02, product); // Product Name
|
||||||
mxf_write_local_tag_utf16(pb, 0x3C04, version); // Version String
|
mxf_write_local_tag_utf16(pb, 0x3C04, version); // Version String
|
||||||
@@ -1092,20 +1140,21 @@ static void mxf_write_generic_sound_desc(AVFormatContext *s, AVStream *st)
|
|||||||
mxf_write_generic_sound_common(s, st, mxf_generic_sound_descriptor_key, 0);
|
mxf_write_generic_sound_common(s, st, mxf_generic_sound_descriptor_key, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mxf_write_package(AVFormatContext *s, enum MXFMetadataSetType type)
|
static void mxf_write_package(AVFormatContext *s, enum MXFMetadataSetType type, const char *package_name)
|
||||||
{
|
{
|
||||||
MXFContext *mxf = s->priv_data;
|
MXFContext *mxf = s->priv_data;
|
||||||
AVIOContext *pb = s->pb;
|
AVIOContext *pb = s->pb;
|
||||||
int i, track_count = s->nb_streams+1;
|
int i, track_count = s->nb_streams+1;
|
||||||
|
int name_size = mxf_utf16_local_tag_length(package_name);
|
||||||
|
|
||||||
if (type == MaterialPackage) {
|
if (type == MaterialPackage) {
|
||||||
mxf_write_metadata_key(pb, 0x013600);
|
mxf_write_metadata_key(pb, 0x013600);
|
||||||
PRINT_KEY(s, "Material Package key", pb->buf_ptr - 16);
|
PRINT_KEY(s, "Material Package key", pb->buf_ptr - 16);
|
||||||
klv_encode_ber_length(pb, 92 + 16*track_count);
|
klv_encode_ber_length(pb, 92 + name_size + (16*track_count));
|
||||||
} else {
|
} else {
|
||||||
mxf_write_metadata_key(pb, 0x013700);
|
mxf_write_metadata_key(pb, 0x013700);
|
||||||
PRINT_KEY(s, "Source Package key", pb->buf_ptr - 16);
|
PRINT_KEY(s, "Source Package key", pb->buf_ptr - 16);
|
||||||
klv_encode_ber_length(pb, 112 + 16*track_count); // 20 bytes length for descriptor reference
|
klv_encode_ber_length(pb, 112 + name_size + (16*track_count)); // 20 bytes length for descriptor reference
|
||||||
}
|
}
|
||||||
|
|
||||||
// write uid
|
// write uid
|
||||||
@@ -1119,6 +1168,10 @@ static void mxf_write_package(AVFormatContext *s, enum MXFMetadataSetType type)
|
|||||||
mxf_write_umid(s, type == SourcePackage);
|
mxf_write_umid(s, type == SourcePackage);
|
||||||
PRINT_KEY(s, "package umid second part", pb->buf_ptr - 16);
|
PRINT_KEY(s, "package umid second part", pb->buf_ptr - 16);
|
||||||
|
|
||||||
|
// package name
|
||||||
|
if (name_size)
|
||||||
|
mxf_write_local_tag_utf16(pb, 0x4402, package_name);
|
||||||
|
|
||||||
// package creation date
|
// package creation date
|
||||||
mxf_write_local_tag(pb, 8, 0x4405);
|
mxf_write_local_tag(pb, 8, 0x4405);
|
||||||
avio_wb64(pb, mxf->timestamp);
|
avio_wb64(pb, mxf->timestamp);
|
||||||
@@ -1187,11 +1240,33 @@ static int mxf_write_essence_container_data(AVFormatContext *s)
|
|||||||
|
|
||||||
static int mxf_write_header_metadata_sets(AVFormatContext *s)
|
static int mxf_write_header_metadata_sets(AVFormatContext *s)
|
||||||
{
|
{
|
||||||
|
const char *material_package_name = NULL;
|
||||||
|
const char *file_package_name = NULL;
|
||||||
|
AVDictionaryEntry *entry = NULL;
|
||||||
|
AVStream *st = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (entry = av_dict_get(s->metadata, "material_package_name", NULL, 0))
|
||||||
|
material_package_name = entry->value;
|
||||||
|
|
||||||
|
if (entry = av_dict_get(s->metadata, "file_package_name", NULL, 0)) {
|
||||||
|
file_package_name = entry->value;
|
||||||
|
} else {
|
||||||
|
/* check if any of the streams contain a file_package_name */
|
||||||
|
for (i = 0; i < s->nb_streams; i++) {
|
||||||
|
st = s->streams[i];
|
||||||
|
if (entry = av_dict_get(st->metadata, "file_package_name", NULL, 0)) {
|
||||||
|
file_package_name = entry->value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mxf_write_preface(s);
|
mxf_write_preface(s);
|
||||||
mxf_write_identification(s);
|
mxf_write_identification(s);
|
||||||
mxf_write_content_storage(s);
|
mxf_write_content_storage(s);
|
||||||
mxf_write_package(s, MaterialPackage);
|
mxf_write_package(s, MaterialPackage, material_package_name);
|
||||||
mxf_write_package(s, SourcePackage);
|
mxf_write_package(s, SourcePackage, file_package_name);
|
||||||
mxf_write_essence_container_data(s);
|
mxf_write_essence_container_data(s);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
dbc4ced82ef1c2fa4df3571b4f994a22 *./tests/data/lavf/lavf.mxf
|
c4eb3fab4d6b24687b81913036c79ce9 *./tests/data/lavf/lavf.mxf
|
||||||
525369 ./tests/data/lavf/lavf.mxf
|
525369 ./tests/data/lavf/lavf.mxf
|
||||||
./tests/data/lavf/lavf.mxf CRC=0xdbfff6f1
|
./tests/data/lavf/lavf.mxf CRC=0xdbfff6f1
|
||||||
fe4294023cd990938f042c7855405f63 *./tests/data/lavf/lavf.mxf
|
54cb97d1fc47c58f5580e8c897ef0874 *./tests/data/lavf/lavf.mxf
|
||||||
560697 ./tests/data/lavf/lavf.mxf
|
560697 ./tests/data/lavf/lavf.mxf
|
||||||
./tests/data/lavf/lavf.mxf CRC=0x11a6178e
|
./tests/data/lavf/lavf.mxf CRC=0x11a6178e
|
||||||
ef0c741e17bf7963fc51adcb6bab8ec8 *./tests/data/lavf/lavf.mxf
|
872c48b66705925cb0c6d638c82cd7d4 *./tests/data/lavf/lavf.mxf
|
||||||
525369 ./tests/data/lavf/lavf.mxf
|
525369 ./tests/data/lavf/lavf.mxf
|
||||||
./tests/data/lavf/lavf.mxf CRC=0xdbfff6f1
|
./tests/data/lavf/lavf.mxf CRC=0xdbfff6f1
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
87e0903ef7ea55b1a032b9d878588683 *./tests/data/lavf/lavf.mxf_d10
|
c92818ebed05077efb27fc47a0351730 *./tests/data/lavf/lavf.mxf_d10
|
||||||
5330989 ./tests/data/lavf/lavf.mxf_d10
|
5330989 ./tests/data/lavf/lavf.mxf_d10
|
||||||
./tests/data/lavf/lavf.mxf_d10 CRC=0x6c74d488
|
./tests/data/lavf/lavf.mxf_d10 CRC=0x6c74d488
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
f52285c3a157c77eb86c372dd46a2bb0 *./tests/data/lavf/lavf.mxf_opatom
|
6e2d9890ebda56b2e167e257750618ad *./tests/data/lavf/lavf.mxf_opatom
|
||||||
4716601 ./tests/data/lavf/lavf.mxf_opatom
|
4716601 ./tests/data/lavf/lavf.mxf_opatom
|
||||||
./tests/data/lavf/lavf.mxf_opatom CRC=0xbdd696b9
|
./tests/data/lavf/lavf.mxf_opatom CRC=0xbdd696b9
|
||||||
|
Reference in New Issue
Block a user