--- libavformat/avio.h | 6 ++++ libavformat/aviobuf.c | 50 +++++++++++++++++--------------- libavformat/mxfenc.c | 74 ++++++++++++++++++++++++++++++++++++++++------- tests/ref/lavf/mxf | 6 ++-- tests/ref/lavf/mxf_d10 | 2 +- tests/ref/lavf/mxf_opatom | 2 +- 6 files changed, 101 insertions(+), 39 deletions(-)
diff --git a/libavformat/avio.h b/libavformat/avio.h index b9b4017..8fc7e27 100644 --- a/libavformat/avio.h +++ b/libavformat/avio.h @@ -234,6 +234,12 @@ int avio_put_str(AVIOContext *s, const char *str); int avio_put_str16le(AVIOContext *s, const char *str); /** + * Convert an UTF-8 string to UTF-16BE and write it. + * @return number of bytes written. + */ +int avio_put_str16be(AVIOContext *s, const char *str); + +/** * Passing this as the "whence" parameter to a seek function causes it to * return the filesize without seeking anywhere. Supporting this is optional. * If it is not supported then the seek function will return <0. diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 3d77a7f..506f292 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -342,29 +342,33 @@ int avio_put_str(AVIOContext *s, const char *str) return len; } -int avio_put_str16le(AVIOContext *s, const char *str) -{ - const uint8_t *q = str; - int ret = 0; - int err = 0; - - while (*q) { - uint32_t ch; - uint16_t tmp; - - GET_UTF8(ch, *q++, goto invalid;) - PUT_UTF16(ch, tmp, avio_wl16(s, tmp); ret += 2;) - continue; -invalid: - av_log(s, AV_LOG_ERROR, "Invaid UTF8 sequence in avio_put_str16le\n"); - err = AVERROR(EINVAL); - } - avio_wl16(s, 0); - if (err) - return err; - ret += 2; - return ret; -} +#define PUT_STR16(type, write) \ + int avio_put_str16 ##type(AVIOContext *s, const char *str)\ +{\ + const uint8_t *q = str;\ + int ret = 0;\ + int err = 0;\ + while (*q) {\ + uint32_t ch;\ + uint16_t tmp;\ + GET_UTF8(ch, *q++, goto invalid;)\ + PUT_UTF16(ch, tmp, write(s, tmp); ret += 2;)\ + continue;\ +invalid:\ + av_log(s, AV_LOG_ERROR, "Invaid UTF8 sequence in avio_put_str16" #type "\n");\ + err = AVERROR(EINVAL);\ + }\ + write(s, 0);\ + if (err)\ + return err;\ + ret += 2;\ + return ret;\ +}\ + +PUT_STR16(le, avio_wl16) +PUT_STR16(be, avio_wb16) + +#undef PUT_STR16 int ff_get_v_length(uint64_t val) { diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index 17ad132..c25f5fd 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -624,14 +624,44 @@ 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 uint64_t mxf_utf16_local_tag_length(const char *utf8_str) +{ + return utf8_str? 4 + mxf_utf16len(utf8_str) * 2: 0; +} + +/* + * 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) { - int i, size = strlen(value); + int size = mxf_utf16len(value); mxf_write_local_tag(pb, size*2, tag); - for (i = 0; i < size; i++) - avio_wb16(pb, value[i]); + avio_put_str16be(pb, value); } static void mxf_write_identification(AVFormatContext *s) @@ -648,7 +678,9 @@ static void mxf_write_identification(AVFormatContext *s) version = s->flags & AVFMT_FLAG_BITEXACT ? "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); // write uid @@ -659,7 +691,6 @@ static void mxf_write_identification(AVFormatContext *s) // write generation uid mxf_write_local_tag(pb, 16, 0x3C09); mxf_write_uuid(pb, Identification, 1); - 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, 0x3C04, version); // Version String @@ -1092,20 +1123,29 @@ static void mxf_write_generic_sound_desc(AVFormatContext *s, AVStream *st) 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; AVIOContext *pb = s->pb; int i, track_count = s->nb_streams+1; + uint64_t name_size = 0; + + if (package_name) + name_size = mxf_utf16_local_tag_length(package_name); + + if (name_size >= INT16_MAX){ + av_log(s, AV_LOG_WARNING, "package name size %"PRIx64" invalid (too large), ignoring\n", name_size); + name_size = 0; + } if (type == MaterialPackage) { mxf_write_metadata_key(pb, 0x013600); 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 { mxf_write_metadata_key(pb, 0x013700); 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 @@ -1119,6 +1159,10 @@ static void mxf_write_package(AVFormatContext *s, enum MXFMetadataSetType type) mxf_write_umid(s, type == SourcePackage); 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 mxf_write_local_tag(pb, 8, 0x4405); avio_wb64(pb, mxf->timestamp); @@ -1187,11 +1231,19 @@ static int mxf_write_essence_container_data(AVFormatContext *s) static int mxf_write_header_metadata_sets(AVFormatContext *s) { + char *material_package_name = NULL; + char *file_package_name = NULL; + AVDictionaryEntry *entry = NULL; + + 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; mxf_write_preface(s); mxf_write_identification(s); mxf_write_content_storage(s); - mxf_write_package(s, MaterialPackage); - mxf_write_package(s, SourcePackage); + mxf_write_package(s, MaterialPackage, material_package_name); + mxf_write_package(s, SourcePackage, file_package_name); mxf_write_essence_container_data(s); return 0; } diff --git a/tests/ref/lavf/mxf b/tests/ref/lavf/mxf index 236661c..38db9ac 100644 --- a/tests/ref/lavf/mxf +++ b/tests/ref/lavf/mxf @@ -1,9 +1,9 @@ -dbc4ced82ef1c2fa4df3571b4f994a22 *./tests/data/lavf/lavf.mxf +c4eb3fab4d6b24687b81913036c79ce9 *./tests/data/lavf/lavf.mxf 525369 ./tests/data/lavf/lavf.mxf ./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 ./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 ./tests/data/lavf/lavf.mxf CRC=0xdbfff6f1 diff --git a/tests/ref/lavf/mxf_d10 b/tests/ref/lavf/mxf_d10 index ff7d876..7a5e154 100644 --- a/tests/ref/lavf/mxf_d10 +++ b/tests/ref/lavf/mxf_d10 @@ -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 ./tests/data/lavf/lavf.mxf_d10 CRC=0x6c74d488 diff --git a/tests/ref/lavf/mxf_opatom b/tests/ref/lavf/mxf_opatom index d62d803..c6c0785 100644 --- a/tests/ref/lavf/mxf_opatom +++ b/tests/ref/lavf/mxf_opatom @@ -1,3 +1,3 @@ -8b312335b1af76e0133092c2658cd4a4 *./tests/data/lavf/lavf.mxf_opatom +17c93938b3d8c61c29caf6ad9ae5f22e *./tests/data/lavf/lavf.mxf_opatom 4716601 ./tests/data/lavf/lavf.mxf_opatom ./tests/data/lavf/lavf.mxf_opatom CRC=0xbdd696b9 -- 2.2.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel