From 4aad03c3d3fb57f142f054b79f737741ab3549ab Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Wed, 22 Nov 2023 12:14:28 +0000 Subject: [PATCH 01/65] libmxf: Add ADM sets and items to data model --- deps/libMXF/mxf/mxf_baseline_data_model.h | 151 ++++++++++++++++++++++ deps/libMXF/mxf/mxf_data_model.h | 1 + deps/libMXF/mxf/mxf_header_metadata.c | 23 ++++ deps/libMXF/mxf/mxf_header_metadata.h | 4 + deps/libMXF/mxf/mxf_types.h | 10 ++ 5 files changed, 189 insertions(+) diff --git a/deps/libMXF/mxf/mxf_baseline_data_model.h b/deps/libMXF/mxf/mxf_baseline_data_model.h index 013f4c97..e572063a 100644 --- a/deps/libMXF/mxf/mxf_baseline_data_model.h +++ b/deps/libMXF/mxf/mxf_baseline_data_model.h @@ -111,6 +111,7 @@ MXF_ARRAY_TYPE_DEF(MXF_RGBALAYOUT_TYPE, "RGBALayout", MXF_ MXF_ARRAY_TYPE_DEF(MXF_AES3_FIXED_DATA_ARRAY_TYPE, "AES3FixedDataArray", MXF_AES3_FIXED_DATA_TYPE, 0); MXF_ARRAY_TYPE_DEF(MXF_J2K_COMPONENT_SIZING_ARRAY_TYPE, "J2KComponentSizingArray", MXF_J2K_COMPONENT_SIZING_TYPE, 0); MXF_ARRAY_TYPE_DEF(MXF_THREE_COLOR_PRIMARIES_TYPE, "ThreeColorPrimaries", MXF_COLOR_PRIMARY_TYPE, 3); +MXF_ARRAY_TYPE_DEF(MXF_RIFF_CHUNK_ID_TYPE, "RIFFChunkIDType", MXF_ISO7_TYPE, 4); MXF_COMPOUND_TYPE_DEF(MXF_RATIONAL_TYPE, "Rational"); @@ -2063,6 +2064,156 @@ MXF_SET_DEFINITION(SubDescriptor, ContainerConstraintsSubDescriptor, MXF_LABEL(0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x67,0x00) ); +MXF_SET_DEFINITION(SubDescriptor, RIFFChunkDefinitionSubDescriptor, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x81,0x0d) +); + + MXF_ITEM_DEFINITION(RIFFChunkDefinitionSubDescriptor, RIFFChunkStreamID, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x08,0x01,0x00,0x00,0x00), + 0x0000, + MXF_UINT32_TYPE, + 1 + ); + + MXF_ITEM_DEFINITION(RIFFChunkDefinitionSubDescriptor, RIFFChunkID, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x08,0x02,0x00,0x00,0x00), + 0x0000, + MXF_RIFF_CHUNK_ID_TYPE, + 1 + ); + + MXF_ITEM_DEFINITION(RIFFChunkDefinitionSubDescriptor, RIFFChunkUUID, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x08,0x03,0x00,0x00,0x00), + 0x0000, + MXF_UUID_TYPE, + 0 + ); + + MXF_ITEM_DEFINITION(RIFFChunkDefinitionSubDescriptor, RIFFChunkHashSHA1, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x08,0x04,0x00,0x00,0x00), + 0x0000, + MXF_DATAVALUE_TYPE, + 0 + ); + +MXF_SET_DEFINITION(SubDescriptor, ADM_CHNASubDescriptor, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x81,0x0e) +); + + MXF_ITEM_DEFINITION(ADM_CHNASubDescriptor, NumLocalChannels, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x09,0x01,0x00,0x00,0x00), + 0x0000, + MXF_UINT16_TYPE, + 1 + ); + + MXF_ITEM_DEFINITION(ADM_CHNASubDescriptor, NumADMAudioTrackUIDs, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x09,0x02,0x00,0x00,0x00), + 0x0000, + MXF_UINT16_TYPE, + 1 + ); + + MXF_ITEM_DEFINITION(ADM_CHNASubDescriptor, ADMChannelMappingsArray, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x09,0x03,0x00,0x00,0x00), + 0x0000, + MXF_STRONGREFARRAY_TYPE, + 1 + ); + +MXF_SET_DEFINITION(InterchangeObject, ADMChannelMapping, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x81,0x0f) +); + + MXF_ITEM_DEFINITION(ADMChannelMapping, LocalChannelID, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x09,0x04,0x00,0x00,0x00), + 0x0000, + MXF_UINT32_TYPE, + 1 + ); + + MXF_ITEM_DEFINITION(ADMChannelMapping, ADMAudioTrackUID, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x09,0x05,0x00,0x00,0x00), + 0x0000, + MXF_UTF16STRING_TYPE, + 1 + ); + + MXF_ITEM_DEFINITION(ADMChannelMapping, ADMAudioTrackChannelFormatID, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x09,0x06,0x00,0x00,0x00), + 0x0000, + MXF_UTF16STRING_TYPE, + 1 + ); + + MXF_ITEM_DEFINITION(ADMChannelMapping, ADMAudioPackFormatID, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x09,0x07,0x00,0x00,0x00), + 0x0000, + MXF_UTF16STRING_TYPE, + 0 + ); + +MXF_SET_DEFINITION(SubDescriptor, RIFFChunkReferencesSubDescriptor, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x81,0x10) +); + + MXF_ITEM_DEFINITION(RIFFChunkReferencesSubDescriptor, RIFFChunkStreamIDsArray, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x08,0x06,0x00,0x00,0x00), + 0x0000, + MXF_UINT32ARRAY_TYPE, + 1 + ); + +MXF_SET_DEFINITION(SubDescriptor, ADMAudioMetadataSubDescriptor, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x81,0x11) +); + + MXF_ITEM_DEFINITION(ADMAudioMetadataSubDescriptor, RIFFChunkStreamID_link1, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x0a,0x01,0x00,0x00,0x00), + 0x0000, + MXF_UINT32_TYPE, + 1 + ); + + MXF_ITEM_DEFINITION(ADMAudioMetadataSubDescriptor, ADMProfileLevelULBatch, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x0a,0x02,0x00,0x00,0x00), + 0x0000, + MXF_ULBATCH_TYPE, + 0 + ); + +MXF_SET_DEFINITION(SoundfieldGroupLabelSubDescriptor, ADMSoundfieldGroupLabelSubDescriptor, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x81,0x12) +); + + MXF_ITEM_DEFINITION(ADMSoundfieldGroupLabelSubDescriptor, RIFFChunkStreamID_link2, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x0b,0x01,0x00,0x00,0x00), + 0x0000, + MXF_UINT32_TYPE, + 1 + ); + + MXF_ITEM_DEFINITION(ADMSoundfieldGroupLabelSubDescriptor, ADMAudioProgrammeID_ST2131, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x0b,0x02,0x00,0x00,0x00), + 0x0000, + MXF_UTF16STRING_TYPE, + 0 + ); + + MXF_ITEM_DEFINITION(ADMSoundfieldGroupLabelSubDescriptor, ADMAudioContentID_ST2131, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x0b,0x03,0x00,0x00,0x00), + 0x0000, + MXF_UTF16STRING_TYPE, + 0 + ); + + MXF_ITEM_DEFINITION(ADMSoundfieldGroupLabelSubDescriptor, ADMAudioObjectID_ST2131, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x0b,0x04,0x00,0x00,0x00), + 0x0000, + MXF_UTF16STRING_TYPE, + 0 + ); + #if !defined(KEEP_DATA_MODEL_DEFS) #undef MXF_BASIC_TYPE_DEF diff --git a/deps/libMXF/mxf/mxf_data_model.h b/deps/libMXF/mxf/mxf_data_model.h index 835c50f7..b4dcbf10 100644 --- a/deps/libMXF/mxf/mxf_data_model.h +++ b/deps/libMXF/mxf/mxf_data_model.h @@ -177,6 +177,7 @@ typedef enum MXF_AES3_FIXED_DATA_ARRAY_TYPE, MXF_J2K_COMPONENT_SIZING_ARRAY_TYPE, MXF_THREE_COLOR_PRIMARIES_TYPE, + MXF_RIFF_CHUNK_ID_TYPE, /* compound */ MXF_RATIONAL_TYPE, diff --git a/deps/libMXF/mxf/mxf_header_metadata.c b/deps/libMXF/mxf/mxf_header_metadata.c index cba656b8..53db8ed8 100644 --- a/deps/libMXF/mxf/mxf_header_metadata.c +++ b/deps/libMXF/mxf/mxf_header_metadata.c @@ -273,6 +273,9 @@ static int validate_set(MXFMetadataSet *set, MXFSetDef *setDef, int logErrors) case MXF_THREE_COLOR_PRIMARIES_TYPE: CHECK_LENGTH(12) break; + case MXF_RIFF_CHUNK_ID_TYPE: + CHECK_LENGTH(4); + break; case MXF_RATIONAL_TYPE: CHECK_LENGTH(8) break; @@ -1281,6 +1284,11 @@ void mxf_get_three_color_primaries(const uint8_t *value, mxfThreeColorPrimaries } } +void mxf_get_riff_chunk_id_type(const uint8_t *value, mxfRIFFChunkIDType *result) +{ + memcpy(result, value, mxfRIFFChunkIDType_extlen); +} + void mxf_get_array_header(const uint8_t *value, uint32_t *arrayLen, uint32_t *arrayItemLen) { mxf_get_uint32(value, arrayLen); @@ -1784,6 +1792,11 @@ void mxf_set_three_color_primaries(const mxfThreeColorPrimaries *value, uint8_t } } +void mxf_set_riff_chunk_id_type(const mxfRIFFChunkIDType *value, uint8_t *result) +{ + memcpy(result, value, mxfRIFFChunkIDType_extlen); +} + void mxf_set_array_header(uint32_t arrayLen, uint32_t arrayElementLen, uint8_t *result) { mxf_set_uint32(arrayLen, result); @@ -2097,6 +2110,11 @@ int mxf_set_video_line_map_item(MXFMetadataSet *set, const mxfKey *itemKey, cons return 1; } +int mxf_set_riff_chunk_id_type_item(MXFMetadataSet *set, const mxfKey *itemKey, const mxfRIFFChunkIDType *value) +{ + SET_VALUE(mxfRIFFChunkIDType_extlen, mxf_set_riff_chunk_id_type); +} + int mxf_alloc_array_item_elements(MXFMetadataSet *set, const mxfKey *itemKey, uint32_t elementLen, uint32_t count, uint8_t **elements) { @@ -2530,6 +2548,11 @@ int mxf_get_video_line_map_item(MXFMetadataSet *set, const mxfKey *itemKey, mxfV return 1; } +int mxf_get_riff_chunk_id_type_item(MXFMetadataSet *set, const mxfKey *itemKey, mxfRIFFChunkIDType *value) +{ + GET_VALUE(mxfRIFFChunkIDType_extlen, mxf_get_riff_chunk_id_type); +} + int mxf_get_array_item_count(MXFMetadataSet *set, const mxfKey *itemKey, uint32_t *count) { MXFMetadataItem *item = NULL; diff --git a/deps/libMXF/mxf/mxf_header_metadata.h b/deps/libMXF/mxf/mxf_header_metadata.h index ce352a9c..6c1d564d 100644 --- a/deps/libMXF/mxf/mxf_header_metadata.h +++ b/deps/libMXF/mxf/mxf_header_metadata.h @@ -164,6 +164,7 @@ void mxf_get_j2k_component_sizing(const uint8_t *value, mxfJ2KComponentSizing *r int mxf_get_j2k_ext_capabilities(const uint8_t *value, uint16_t value_len, mxfJ2KExtendedCapabilities *result); void mxf_get_color_primary(const uint8_t *value, mxfColorPrimary *result); void mxf_get_three_color_primaries(const uint8_t *value, mxfThreeColorPrimaries *result); +void mxf_get_riff_chunk_id_type(const uint8_t *value, mxfRIFFChunkIDType *result); void mxf_get_array_header(const uint8_t *value, uint32_t *arrayLen, uint32_t *arrayItemLen); uint16_t mxf_get_utf16string_size(const uint8_t *value, uint16_t valueLen); void mxf_get_utf16string(const uint8_t *value, uint16_t valueLen, mxfUTF16Char *result); @@ -220,6 +221,7 @@ uint16_t mxf_get_external_j2k_ext_capabilities_size(const mxfJ2KExtendedCapabili void mxf_set_j2k_ext_capabilities(const mxfJ2KExtendedCapabilities *value, uint8_t *result); void mxf_set_color_primary(const mxfColorPrimary *value, uint8_t *result); void mxf_set_three_color_primaries(const mxfThreeColorPrimaries *value, uint8_t *result); +void mxf_set_riff_chunk_id_type(const mxfRIFFChunkIDType *value, uint8_t *result); void mxf_set_array_header(uint32_t arrayLen, uint32_t arrayElementLen, uint8_t *result); @@ -260,6 +262,7 @@ int mxf_set_rgba_layout_item(MXFMetadataSet *set, const mxfKey *itemKey, const m int mxf_set_j2k_ext_capabilities_item(MXFMetadataSet *set, const mxfKey *itemKey, const mxfJ2KExtendedCapabilities *value); int mxf_set_color_primary_item(MXFMetadataSet *set, const mxfKey *itemKey, const mxfColorPrimary *value); int mxf_set_three_color_primaries_item(MXFMetadataSet *set, const mxfKey *itemKey, const mxfThreeColorPrimaries *value); +int mxf_set_riff_chunk_id_type_item(MXFMetadataSet *set, const mxfKey *itemKey, const mxfRIFFChunkIDType *value); int mxf_set_video_line_map_item(MXFMetadataSet *set, const mxfKey *itemKey, const mxfVideoLineMap *value); int mxf_alloc_array_item_elements(MXFMetadataSet *set, const mxfKey *itemKey, uint32_t elementLen, @@ -310,6 +313,7 @@ int mxf_get_rgba_layout_item(MXFMetadataSet *set, const mxfKey *itemKey, mxfRGBA int mxf_get_j2k_ext_capabilities_item(MXFMetadataSet *set, const mxfKey *itemKey, mxfJ2KExtendedCapabilities *value); int mxf_get_color_primary_item(MXFMetadataSet *set, const mxfKey *itemKey, mxfColorPrimary *value); int mxf_get_three_color_primaries_item(MXFMetadataSet *set, const mxfKey *itemKey, mxfThreeColorPrimaries *value); +int mxf_get_riff_chunk_id_type_item(MXFMetadataSet *set, const mxfKey *itemKey, mxfRIFFChunkIDType *value); int mxf_get_video_line_map_item(MXFMetadataSet *set, const mxfKey *itemKey, mxfVideoLineMap *value); int mxf_get_array_item_count(MXFMetadataSet *set, const mxfKey *itemKey, uint32_t *count); diff --git a/deps/libMXF/mxf/mxf_types.h b/deps/libMXF/mxf/mxf_types.h index 6e71cad9..f87f9fb5 100644 --- a/deps/libMXF/mxf/mxf_types.h +++ b/deps/libMXF/mxf/mxf_types.h @@ -306,6 +306,13 @@ typedef struct mxfColorPrimary primaries[3]; } mxfThreeColorPrimaries; +typedef struct { + uint8_t c0; + uint8_t c1; + uint8_t c2; + uint8_t c3; +} mxfRIFFChunkIDType; + typedef struct { int32_t first; /* first line number of first field or FULL_FRAME progressive frame */ @@ -334,6 +341,7 @@ typedef struct #define mxfJ2KComponentSizing_extlen 3 #define mxfColorPrimary_extlen 4 #define mxfThreeColorPrimaries_extlen 12 +#define mxfRIFFChunkIDType_extlen 4 static const mxfUUID g_Null_UUID = @@ -358,6 +366,8 @@ static const mxfRational g_Null_Rational = {0, 0}; static const mxfThreeColorPrimaries g_Null_Three_Color_Primaries = {{{0, 0}}}; static const mxfColorPrimary g_Null_Color_Primary = {0, 0}; +static const mxfRIFFChunkIDType g_Null_RIFFChunkIDType = {0, 0, 0, 0}; + static const mxfVideoLineMap g_Null_Video_Line_Map = {0, 0}; From 33f8ae0d20b25551bf857378ece8d1752c14728b Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Wed, 22 Nov 2023 12:15:32 +0000 Subject: [PATCH 02/65] libmxf: Add Wave chunk generic stream key --- deps/libMXF/mxf/mxf_labels_and_keys.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/deps/libMXF/mxf/mxf_labels_and_keys.h b/deps/libMXF/mxf/mxf_labels_and_keys.h index 86720313..fc5fcb6f 100644 --- a/deps/libMXF/mxf/mxf_labels_and_keys.h +++ b/deps/libMXF/mxf/mxf_labels_and_keys.h @@ -939,6 +939,11 @@ static const mxfKey MXF_EE_K(RP2057_ENDIAN_UNK) = MXF_GS_DATA_ELEMENT_KEY(MXF_GS static const mxfKey MXF_EE_K(TimedTextAnc) = MXF_GS_DATA_ELEMENT_KEY(MXF_GS_DATA_BASE | MXF_GS_DATA_BYTES, MXF_GS_WRAP_BASE); +/* Wave Chunk */ + +static const mxfKey MXF_EE_K(WaveChunk) = MXF_GS_DATA_ELEMENT_KEY(MXF_GS_DATA_BASE | MXF_GS_DATA_BYTES, MXF_GS_WRAP_BASE); + + /* * * Partition pack keys From f1e655135803fc94d04a610c263417e33ed8010a Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Wed, 22 Nov 2023 12:16:21 +0000 Subject: [PATCH 03/65] libmxf: Add ITU 2076 ADM audio metadata profiles and levels label --- deps/libMXF/mxf/mxf_labels_and_keys.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/deps/libMXF/mxf/mxf_labels_and_keys.h b/deps/libMXF/mxf/mxf_labels_and_keys.h index fc5fcb6f..0e476bf3 100644 --- a/deps/libMXF/mxf/mxf_labels_and_keys.h +++ b/deps/libMXF/mxf/mxf_labels_and_keys.h @@ -704,6 +704,11 @@ static const mxfUL CENTER_CUT_4_3 = MXF_ALTERNATIVE_CENTER_CUT_L(0x01) static const mxfUL CENTER_CUT_14_9 = MXF_ALTERNATIVE_CENTER_CUT_L(0x02) +/* ADM audio metadata profiles and levels */ + +static const mxfUL ADM_ITU2076_PROFILES_LEVELS = + {0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x0d, 0x04, 0x02, 0x02, 0x11, 0x01, 0x01, 0x00, 0x00}; + /* * From e64d40eebfe0d4ec60e8bc2f9f4c723dbd0b87cf Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Wed, 22 Nov 2023 12:18:47 +0000 Subject: [PATCH 04/65] libmxf: Add MGA sound descriptors and labels --- deps/libMXF/mxf/mxf_baseline_data_model.h | 108 ++++++++++++++++++++++ deps/libMXF/mxf/mxf_labels_and_keys.h | 17 ++++ 2 files changed, 125 insertions(+) diff --git a/deps/libMXF/mxf/mxf_baseline_data_model.h b/deps/libMXF/mxf/mxf_baseline_data_model.h index e572063a..e4b4e159 100644 --- a/deps/libMXF/mxf/mxf_baseline_data_model.h +++ b/deps/libMXF/mxf/mxf_baseline_data_model.h @@ -2214,6 +2214,114 @@ MXF_SET_DEFINITION(SoundfieldGroupLabelSubDescriptor, ADMSoundfieldGroupLabelSub 0 ); +MXF_SET_DEFINITION(GenericSoundEssenceDescriptor, MGASoundEssenceDescriptor, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x81,0x06) +); + + MXF_ITEM_DEFINITION(MGASoundEssenceDescriptor, MGASoundEssenceBlockAlign, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x04,0x01,0x00,0x00,0x00), + 0x0000, + MXF_UINT16_TYPE, + 1 + ); + + MXF_ITEM_DEFINITION(MGASoundEssenceDescriptor, MGASoundEssenceAverageBytesPerSecond, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x04,0x02,0x00,0x00,0x00), + 0x0000, + MXF_UINT32_TYPE, + 1 + ); + + MXF_ITEM_DEFINITION(MGASoundEssenceDescriptor, MGASoundEssenceSequenceOffset, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x04,0x03,0x00,0x00,0x00), + 0x0000, + MXF_UINT8_TYPE, + 0 + ); + +MXF_SET_DEFINITION(SubDescriptor, MGAAudioMetadataSubDescriptor, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x81,0x07) +); + + MXF_ITEM_DEFINITION(MGAAudioMetadataSubDescriptor, MGALinkID, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0xe,0x04,0x02,0x03,0x05,0x01,0x00,0x00,0x00), + 0x0000, + MXF_UUID_TYPE, + 1 + ); + + MXF_ITEM_DEFINITION(MGAAudioMetadataSubDescriptor, MGAAudioMetadataIndex, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0xe,0x04,0x02,0x03,0x05,0x02,0x00,0x00,0x00), + 0x0000, + MXF_UINT8_TYPE, + 1 + ); + + MXF_ITEM_DEFINITION(MGAAudioMetadataSubDescriptor, MGAAudioMetadataIdentifier, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0xe,0x04,0x02,0x03,0x05,0x03,0x00,0x00,0x00), + 0x0000, + MXF_UINT8_TYPE, + 1 + ); + + MXF_ITEM_DEFINITION(MGAAudioMetadataSubDescriptor, MGAAudioMetadataPayloadULArray, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0xe,0x04,0x02,0x03,0x05,0x04,0x00,0x00,0x00), + 0x0000, + MXF_ULARRAY_TYPE, + 1 + ); + +MXF_SET_DEFINITION(SubDescriptor, SADMAudioMetadataSubDescriptor, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x81,0x09) +); + + MXF_ITEM_DEFINITION(SADMAudioMetadataSubDescriptor, SADMMetadataSectionLinkID, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x07,0x01,0x00,0x00,0x00), + 0x0000, + MXF_UUID_TYPE, + 1 + ); + + MXF_ITEM_DEFINITION(SADMAudioMetadataSubDescriptor, SADMProfileLevelULBatch, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x07,0x02,0x00,0x00,0x00), + 0x0000, + MXF_ULBATCH_TYPE, + 0 + ); + +MXF_SET_DEFINITION(SoundfieldGroupLabelSubDescriptor, MGASoundfieldGroupLabelSubDescriptor, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x81,0x08) +); + + MXF_ITEM_DEFINITION(MGASoundfieldGroupLabelSubDescriptor, MGAMetadataSectionLinkID, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x06,0x01,0x00,0x00,0x00), + 0x0000, + MXF_UUID_TYPE, + 1 + ); + + MXF_ITEM_DEFINITION(MGASoundfieldGroupLabelSubDescriptor, ADMAudioProgrammeID, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x06,0x02,0x00,0x00,0x00), + 0x0000, + MXF_UTF16STRING_TYPE, + 0 + ); + + MXF_ITEM_DEFINITION(MGASoundfieldGroupLabelSubDescriptor, ADMAudioContentID, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x06,0x03,0x00,0x00,0x00), + 0x0000, + MXF_UTF16STRING_TYPE, + 0 + ); + + MXF_ITEM_DEFINITION(MGASoundfieldGroupLabelSubDescriptor, ADMAudioObjectID, + MXF_LABEL(0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x04,0x02,0x03,0x06,0x04,0x00,0x00,0x00), + 0x0000, + MXF_UTF16STRING_TYPE, + 0 + ); + + #if !defined(KEEP_DATA_MODEL_DEFS) #undef MXF_BASIC_TYPE_DEF diff --git a/deps/libMXF/mxf/mxf_labels_and_keys.h b/deps/libMXF/mxf/mxf_labels_and_keys.h index 0e476bf3..69fb01b4 100644 --- a/deps/libMXF/mxf/mxf_labels_and_keys.h +++ b/deps/libMXF/mxf/mxf_labels_and_keys.h @@ -347,6 +347,14 @@ static const mxfUL MXF_CMDEF_L(ST382_UNC_SOUND) = MXF_UNC_SOUND_CMDEV_L(0x0a, 0x static const mxfUL MXF_CMDEF_L(UNDEFINED_SOUND) = MXF_UNC_SOUND_CMDEV_L(0x01, 0x7f, 0x00, 0x00, 0x00); +/* Metadata-Guided Audio sound coding */ + +#define MXF_MGA_SOUND_CMDEV_L(byte14) \ + {0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x0d, 0x04, 0x02, 0x02, 0x01, 0x02, byte14, 0x00, 0x00} + +static const mxfUL MXF_CMDEF_L(MGA_UNC_SOUND) = MXF_MGA_SOUND_CMDEV_L(0x01); + + /* * * Essence container labels @@ -573,6 +581,15 @@ static const mxfUL MXF_EC_L(ANCData) = MXF_GENERIC_CONTAINER_LABEL(0x09, 0x0e, 0 static const mxfUL MXF_EC_L(TimedText) = MXF_GENERIC_CONTAINER_LABEL(0x0a, 0x13, 0x01, 0x01); +/* Metadata-Guided Audio */ + +#define MXF_MGA_EC_L(byte15) \ + MXF_GENERIC_CONTAINER_LABEL(0x0d, 0x25, byte15, 0x00) + +static const mxfUL MXF_EC_L(MGAFrameWrapped) = MXF_MGA_EC_L(0x01); +static const mxfUL MXF_EC_L(MGAClipWrapped) = MXF_MGA_EC_L(0x02); + + /* * From d4242321656ded3beceb3f48723f6e40963f3e90 Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Wed, 22 Nov 2023 12:29:14 +0000 Subject: [PATCH 05/65] libmxfpp: Add ADM classes --- deps/libMXFpp/libMXF++/HeaderMetadata.cpp | 6 + deps/libMXFpp/libMXF++/MetadataSet.cpp | 12 ++ deps/libMXFpp/libMXF++/MetadataSet.h | 2 + .../ADMAudioMetadataSubDescriptor.cpp | 55 +++++++++ .../metadata/ADMAudioMetadataSubDescriptor.h | 64 ++++++++++ .../libMXF++/metadata/ADMChannelMapping.cpp | 55 +++++++++ .../libMXF++/metadata/ADMChannelMapping.h | 64 ++++++++++ .../ADMSoundfieldGroupLabelSubDescriptor.cpp | 53 ++++++++ .../ADMSoundfieldGroupLabelSubDescriptor.h | 64 ++++++++++ .../metadata/ADM_CHNASubDescriptor.cpp | 55 +++++++++ .../libMXF++/metadata/ADM_CHNASubDescriptor.h | 64 ++++++++++ deps/libMXFpp/libMXF++/metadata/Metadata.h | 6 + .../RIFFChunkDefinitionSubDescriptor.cpp | 55 +++++++++ .../RIFFChunkDefinitionSubDescriptor.h | 64 ++++++++++ .../RIFFChunkReferencesSubDescriptor.cpp | 55 +++++++++ .../RIFFChunkReferencesSubDescriptor.h | 64 ++++++++++ .../ADMAudioMetadataSubDescriptorBase.cpp | 91 ++++++++++++++ .../base/ADMAudioMetadataSubDescriptorBase.h | 77 ++++++++++++ .../metadata/base/ADMChannelMappingBase.cpp | 105 ++++++++++++++++ .../metadata/base/ADMChannelMappingBase.h | 80 ++++++++++++ ...MSoundfieldGroupLabelSubDescriptorBase.cpp | 115 ++++++++++++++++++ ...ADMSoundfieldGroupLabelSubDescriptorBase.h | 82 +++++++++++++ .../base/ADM_CHNASubDescriptorBase.cpp | 104 ++++++++++++++++ .../metadata/base/ADM_CHNASubDescriptorBase.h | 79 ++++++++++++ .../RIFFChunkDefinitionSubDescriptorBase.cpp | 111 +++++++++++++++++ .../RIFFChunkDefinitionSubDescriptorBase.h | 81 ++++++++++++ .../RIFFChunkReferencesSubDescriptorBase.cpp | 76 ++++++++++++ .../RIFFChunkReferencesSubDescriptorBase.h | 74 +++++++++++ 28 files changed, 1813 insertions(+) create mode 100644 deps/libMXFpp/libMXF++/metadata/ADMAudioMetadataSubDescriptor.cpp create mode 100644 deps/libMXFpp/libMXF++/metadata/ADMAudioMetadataSubDescriptor.h create mode 100644 deps/libMXFpp/libMXF++/metadata/ADMChannelMapping.cpp create mode 100644 deps/libMXFpp/libMXF++/metadata/ADMChannelMapping.h create mode 100644 deps/libMXFpp/libMXF++/metadata/ADMSoundfieldGroupLabelSubDescriptor.cpp create mode 100644 deps/libMXFpp/libMXF++/metadata/ADMSoundfieldGroupLabelSubDescriptor.h create mode 100644 deps/libMXFpp/libMXF++/metadata/ADM_CHNASubDescriptor.cpp create mode 100644 deps/libMXFpp/libMXF++/metadata/ADM_CHNASubDescriptor.h create mode 100644 deps/libMXFpp/libMXF++/metadata/RIFFChunkDefinitionSubDescriptor.cpp create mode 100644 deps/libMXFpp/libMXF++/metadata/RIFFChunkDefinitionSubDescriptor.h create mode 100644 deps/libMXFpp/libMXF++/metadata/RIFFChunkReferencesSubDescriptor.cpp create mode 100644 deps/libMXFpp/libMXF++/metadata/RIFFChunkReferencesSubDescriptor.h create mode 100644 deps/libMXFpp/libMXF++/metadata/base/ADMAudioMetadataSubDescriptorBase.cpp create mode 100644 deps/libMXFpp/libMXF++/metadata/base/ADMAudioMetadataSubDescriptorBase.h create mode 100644 deps/libMXFpp/libMXF++/metadata/base/ADMChannelMappingBase.cpp create mode 100644 deps/libMXFpp/libMXF++/metadata/base/ADMChannelMappingBase.h create mode 100644 deps/libMXFpp/libMXF++/metadata/base/ADMSoundfieldGroupLabelSubDescriptorBase.cpp create mode 100644 deps/libMXFpp/libMXF++/metadata/base/ADMSoundfieldGroupLabelSubDescriptorBase.h create mode 100644 deps/libMXFpp/libMXF++/metadata/base/ADM_CHNASubDescriptorBase.cpp create mode 100644 deps/libMXFpp/libMXF++/metadata/base/ADM_CHNASubDescriptorBase.h create mode 100644 deps/libMXFpp/libMXF++/metadata/base/RIFFChunkDefinitionSubDescriptorBase.cpp create mode 100644 deps/libMXFpp/libMXF++/metadata/base/RIFFChunkDefinitionSubDescriptorBase.h create mode 100644 deps/libMXFpp/libMXF++/metadata/base/RIFFChunkReferencesSubDescriptorBase.cpp create mode 100644 deps/libMXFpp/libMXF++/metadata/base/RIFFChunkReferencesSubDescriptorBase.h diff --git a/deps/libMXFpp/libMXF++/HeaderMetadata.cpp b/deps/libMXFpp/libMXF++/HeaderMetadata.cpp index 97076892..d9bd46fb 100644 --- a/deps/libMXFpp/libMXF++/HeaderMetadata.cpp +++ b/deps/libMXFpp/libMXF++/HeaderMetadata.cpp @@ -313,6 +313,12 @@ void HeaderMetadata::initialiseObjectFactory() REGISTER_CLASS(DCTimedTextDescriptor); REGISTER_CLASS(DCTimedTextResourceSubDescriptor); REGISTER_CLASS(JPEG2000SubDescriptor); + REGISTER_CLASS(RIFFChunkDefinitionSubDescriptor); + REGISTER_CLASS(ADM_CHNASubDescriptor); + REGISTER_CLASS(ADMAudioMetadataSubDescriptor); + REGISTER_CLASS(ADMChannelMapping); + REGISTER_CLASS(RIFFChunkReferencesSubDescriptor); + REGISTER_CLASS(ADMSoundfieldGroupLabelSubDescriptor); REGISTER_CLASS(ContainerConstraintsSubDescriptor); // Add new classes here diff --git a/deps/libMXFpp/libMXF++/MetadataSet.cpp b/deps/libMXFpp/libMXF++/MetadataSet.cpp index 1a34153b..ea6c9048 100644 --- a/deps/libMXFpp/libMXF++/MetadataSet.cpp +++ b/deps/libMXFpp/libMXF++/MetadataSet.cpp @@ -331,6 +331,13 @@ mxfColorPrimary MetadataSet::getColorPrimaryItem(const mxfKey *itemKey) const return result; } +mxfRIFFChunkIDType MetadataSet::getRIFFChunkIDTypeItem(const mxfKey *itemKey) const +{ + mxfRIFFChunkIDType result; + MXFPP_CHECK(mxf_get_riff_chunk_id_type_item(_cMetadataSet, itemKey, &result)); + return result; +} + string MetadataSet::getStringItem(const mxfKey *itemKey) const { string result; @@ -944,6 +951,11 @@ void MetadataSet::setColorPrimaryItem(const mxfKey *itemKey, mxfColorPrimary val MXFPP_CHECK(mxf_set_color_primary_item(_cMetadataSet, itemKey, &value)); } +void MetadataSet::setRIFFChunkIDTypeItem(const mxfKey *itemKey, mxfRIFFChunkIDType value) const +{ + MXFPP_CHECK(mxf_set_riff_chunk_id_type_item(_cMetadataSet, itemKey, &value)); +} + void MetadataSet::setStringItem(const mxfKey *itemKey, string value) { mxfUTF16Char *utf16Val = 0; diff --git a/deps/libMXFpp/libMXF++/MetadataSet.h b/deps/libMXFpp/libMXF++/MetadataSet.h index 43cfb63d..8a05b029 100644 --- a/deps/libMXFpp/libMXF++/MetadataSet.h +++ b/deps/libMXFpp/libMXF++/MetadataSet.h @@ -151,6 +151,7 @@ class MetadataSet mxfJ2KExtendedCapabilities getJ2KExtendedCapabilitiesItem(const mxfKey *itemKey) const; mxfThreeColorPrimaries getThreeColorPrimariesItem(const mxfKey *itemKey) const; mxfColorPrimary getColorPrimaryItem(const mxfKey *itemKey) const; + mxfRIFFChunkIDType getRIFFChunkIDTypeItem(const mxfKey *itemKey) const; std::string getStringItem(const mxfKey *itemKey) const; std::string getUTF8StringItem(const mxfKey *itemKey) const; std::string getISO7StringItem(const mxfKey *itemKey) const; @@ -209,6 +210,7 @@ class MetadataSet void setJ2KExtendedCapabilitiesItem(const mxfKey *itemKey, mxfJ2KExtendedCapabilities value); void setThreeColorPrimariesItem(const mxfKey *itemKey, mxfThreeColorPrimaries value) const; void setColorPrimaryItem(const mxfKey *itemKey, mxfColorPrimary value) const; + void setRIFFChunkIDTypeItem(const mxfKey *itemKey, mxfRIFFChunkIDType value) const; void setStringItem(const mxfKey *itemKey, std::string value); void setFixedSizeStringItem(const mxfKey *itemKey, std::string value, uint16_t size); void setUTF8StringItem(const mxfKey *itemKey, std::string value); diff --git a/deps/libMXFpp/libMXF++/metadata/ADMAudioMetadataSubDescriptor.cpp b/deps/libMXFpp/libMXF++/metadata/ADMAudioMetadataSubDescriptor.cpp new file mode 100644 index 00000000..0c5d5522 --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/ADMAudioMetadataSubDescriptor.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + + +using namespace std; +using namespace mxfpp; + + + +ADMAudioMetadataSubDescriptor::ADMAudioMetadataSubDescriptor(HeaderMetadata *headerMetadata) +: ADMAudioMetadataSubDescriptorBase(headerMetadata) +{} + +ADMAudioMetadataSubDescriptor::ADMAudioMetadataSubDescriptor(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet) +: ADMAudioMetadataSubDescriptorBase(headerMetadata, cMetadataSet) +{} + +ADMAudioMetadataSubDescriptor::~ADMAudioMetadataSubDescriptor() +{} + + diff --git a/deps/libMXFpp/libMXF++/metadata/ADMAudioMetadataSubDescriptor.h b/deps/libMXFpp/libMXF++/metadata/ADMAudioMetadataSubDescriptor.h new file mode 100644 index 00000000..c447fcd1 --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/ADMAudioMetadataSubDescriptor.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MXFPP_ADMAUDIOMETADATASUBDESCRIPTOR_H_ +#define MXFPP_ADMAUDIOMETADATASUBDESCRIPTOR_H_ + + + +#include + + +namespace mxfpp +{ + + +class ADMAudioMetadataSubDescriptor : public ADMAudioMetadataSubDescriptorBase +{ +public: + friend class MetadataSetFactory; + +public: + ADMAudioMetadataSubDescriptor(HeaderMetadata *headerMetadata); + virtual ~ADMAudioMetadataSubDescriptor(); + + + + +protected: + ADMAudioMetadataSubDescriptor(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet); +}; + + +}; + + +#endif diff --git a/deps/libMXFpp/libMXF++/metadata/ADMChannelMapping.cpp b/deps/libMXFpp/libMXF++/metadata/ADMChannelMapping.cpp new file mode 100644 index 00000000..222b7432 --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/ADMChannelMapping.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + + +using namespace std; +using namespace mxfpp; + + + +ADMChannelMapping::ADMChannelMapping(HeaderMetadata *headerMetadata) +: ADMChannelMappingBase(headerMetadata) +{} + +ADMChannelMapping::ADMChannelMapping(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet) +: ADMChannelMappingBase(headerMetadata, cMetadataSet) +{} + +ADMChannelMapping::~ADMChannelMapping() +{} + + diff --git a/deps/libMXFpp/libMXF++/metadata/ADMChannelMapping.h b/deps/libMXFpp/libMXF++/metadata/ADMChannelMapping.h new file mode 100644 index 00000000..2f2a40f0 --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/ADMChannelMapping.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MXFPP_ADMCHANNELMAPPING_H_ +#define MXFPP_ADMCHANNELMAPPING_H_ + + + +#include + + +namespace mxfpp +{ + + +class ADMChannelMapping : public ADMChannelMappingBase +{ +public: + friend class MetadataSetFactory; + +public: + ADMChannelMapping(HeaderMetadata *headerMetadata); + virtual ~ADMChannelMapping(); + + + + +protected: + ADMChannelMapping(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet); +}; + + +}; + + +#endif diff --git a/deps/libMXFpp/libMXF++/metadata/ADMSoundfieldGroupLabelSubDescriptor.cpp b/deps/libMXFpp/libMXF++/metadata/ADMSoundfieldGroupLabelSubDescriptor.cpp new file mode 100644 index 00000000..7c3389ed --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/ADMSoundfieldGroupLabelSubDescriptor.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + + +using namespace std; +using namespace mxfpp; + + + +ADMSoundfieldGroupLabelSubDescriptor::ADMSoundfieldGroupLabelSubDescriptor(HeaderMetadata *headerMetadata) +: ADMSoundfieldGroupLabelSubDescriptorBase(headerMetadata) +{} + +ADMSoundfieldGroupLabelSubDescriptor::ADMSoundfieldGroupLabelSubDescriptor(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet) +: ADMSoundfieldGroupLabelSubDescriptorBase(headerMetadata, cMetadataSet) +{} + +ADMSoundfieldGroupLabelSubDescriptor::~ADMSoundfieldGroupLabelSubDescriptor() +{} diff --git a/deps/libMXFpp/libMXF++/metadata/ADMSoundfieldGroupLabelSubDescriptor.h b/deps/libMXFpp/libMXF++/metadata/ADMSoundfieldGroupLabelSubDescriptor.h new file mode 100644 index 00000000..4a73d2e5 --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/ADMSoundfieldGroupLabelSubDescriptor.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MXFPP_ADMSOUNDFIELDGROUPLABELSUBDESCRIPTOR_H_ +#define MXFPP_ADMSOUNDFIELDGROUPLABELSUBDESCRIPTOR_H_ + + + +#include + + +namespace mxfpp +{ + + +class ADMSoundfieldGroupLabelSubDescriptor : public ADMSoundfieldGroupLabelSubDescriptorBase +{ +public: + friend class MetadataSetFactory; + +public: + ADMSoundfieldGroupLabelSubDescriptor(HeaderMetadata *headerMetadata); + virtual ~ADMSoundfieldGroupLabelSubDescriptor(); + + + + +protected: + ADMSoundfieldGroupLabelSubDescriptor(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet); +}; + + +}; + + +#endif diff --git a/deps/libMXFpp/libMXF++/metadata/ADM_CHNASubDescriptor.cpp b/deps/libMXFpp/libMXF++/metadata/ADM_CHNASubDescriptor.cpp new file mode 100644 index 00000000..bfec00db --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/ADM_CHNASubDescriptor.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + + +using namespace std; +using namespace mxfpp; + + + +ADM_CHNASubDescriptor::ADM_CHNASubDescriptor(HeaderMetadata *headerMetadata) +: ADM_CHNASubDescriptorBase(headerMetadata) +{} + +ADM_CHNASubDescriptor::ADM_CHNASubDescriptor(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet) +: ADM_CHNASubDescriptorBase(headerMetadata, cMetadataSet) +{} + +ADM_CHNASubDescriptor::~ADM_CHNASubDescriptor() +{} + + diff --git a/deps/libMXFpp/libMXF++/metadata/ADM_CHNASubDescriptor.h b/deps/libMXFpp/libMXF++/metadata/ADM_CHNASubDescriptor.h new file mode 100644 index 00000000..6e8ecab9 --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/ADM_CHNASubDescriptor.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MXFPP_ADM_CHNASUBDESCRIPTOR_H_ +#define MXFPP_ADM_CHNASUBDESCRIPTOR_H_ + + + +#include + + +namespace mxfpp +{ + + +class ADM_CHNASubDescriptor : public ADM_CHNASubDescriptorBase +{ +public: + friend class MetadataSetFactory; + +public: + ADM_CHNASubDescriptor(HeaderMetadata *headerMetadata); + virtual ~ADM_CHNASubDescriptor(); + + + + +protected: + ADM_CHNASubDescriptor(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet); +}; + + +}; + + +#endif diff --git a/deps/libMXFpp/libMXF++/metadata/Metadata.h b/deps/libMXFpp/libMXF++/metadata/Metadata.h index 7d450bb3..bcb5b1b5 100644 --- a/deps/libMXFpp/libMXF++/metadata/Metadata.h +++ b/deps/libMXFpp/libMXF++/metadata/Metadata.h @@ -85,6 +85,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include diff --git a/deps/libMXFpp/libMXF++/metadata/RIFFChunkDefinitionSubDescriptor.cpp b/deps/libMXFpp/libMXF++/metadata/RIFFChunkDefinitionSubDescriptor.cpp new file mode 100644 index 00000000..0731e45d --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/RIFFChunkDefinitionSubDescriptor.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + + +using namespace std; +using namespace mxfpp; + + + +RIFFChunkDefinitionSubDescriptor::RIFFChunkDefinitionSubDescriptor(HeaderMetadata *headerMetadata) +: RIFFChunkDefinitionSubDescriptorBase(headerMetadata) +{} + +RIFFChunkDefinitionSubDescriptor::RIFFChunkDefinitionSubDescriptor(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet) +: RIFFChunkDefinitionSubDescriptorBase(headerMetadata, cMetadataSet) +{} + +RIFFChunkDefinitionSubDescriptor::~RIFFChunkDefinitionSubDescriptor() +{} + + diff --git a/deps/libMXFpp/libMXF++/metadata/RIFFChunkDefinitionSubDescriptor.h b/deps/libMXFpp/libMXF++/metadata/RIFFChunkDefinitionSubDescriptor.h new file mode 100644 index 00000000..0d7daba1 --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/RIFFChunkDefinitionSubDescriptor.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MXFPP_RIFFCHUNKDEFINITIONSUBDESCRIPTOR_H_ +#define MXFPP_RIFFCHUNKDEFINITIONSUBDESCRIPTOR_H_ + + + +#include + + +namespace mxfpp +{ + + +class RIFFChunkDefinitionSubDescriptor : public RIFFChunkDefinitionSubDescriptorBase +{ +public: + friend class MetadataSetFactory; + +public: + RIFFChunkDefinitionSubDescriptor(HeaderMetadata *headerMetadata); + virtual ~RIFFChunkDefinitionSubDescriptor(); + + + + +protected: + RIFFChunkDefinitionSubDescriptor(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet); +}; + + +}; + + +#endif diff --git a/deps/libMXFpp/libMXF++/metadata/RIFFChunkReferencesSubDescriptor.cpp b/deps/libMXFpp/libMXF++/metadata/RIFFChunkReferencesSubDescriptor.cpp new file mode 100644 index 00000000..38553078 --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/RIFFChunkReferencesSubDescriptor.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + + +using namespace std; +using namespace mxfpp; + + + +RIFFChunkReferencesSubDescriptor::RIFFChunkReferencesSubDescriptor(HeaderMetadata *headerMetadata) +: RIFFChunkReferencesSubDescriptorBase(headerMetadata) +{} + +RIFFChunkReferencesSubDescriptor::RIFFChunkReferencesSubDescriptor(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet) +: RIFFChunkReferencesSubDescriptorBase(headerMetadata, cMetadataSet) +{} + +RIFFChunkReferencesSubDescriptor::~RIFFChunkReferencesSubDescriptor() +{} + + diff --git a/deps/libMXFpp/libMXF++/metadata/RIFFChunkReferencesSubDescriptor.h b/deps/libMXFpp/libMXF++/metadata/RIFFChunkReferencesSubDescriptor.h new file mode 100644 index 00000000..90c0cdaa --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/RIFFChunkReferencesSubDescriptor.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MXFPP_RIFFCHUNKREFERENCESSUBDESCRIPTOR_H_ +#define MXFPP_RIFFCHUNKREFERENCESSUBDESCRIPTOR_H_ + + + +#include + + +namespace mxfpp +{ + + +class RIFFChunkReferencesSubDescriptor : public RIFFChunkReferencesSubDescriptorBase +{ +public: + friend class MetadataSetFactory; + +public: + RIFFChunkReferencesSubDescriptor(HeaderMetadata *headerMetadata); + virtual ~RIFFChunkReferencesSubDescriptor(); + + + + +protected: + RIFFChunkReferencesSubDescriptor(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet); +}; + + +}; + + +#endif diff --git a/deps/libMXFpp/libMXF++/metadata/base/ADMAudioMetadataSubDescriptorBase.cpp b/deps/libMXFpp/libMXF++/metadata/base/ADMAudioMetadataSubDescriptorBase.cpp new file mode 100644 index 00000000..c7ccf7ca --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/base/ADMAudioMetadataSubDescriptorBase.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + + +using namespace std; +using namespace mxfpp; + + +const mxfKey ADMAudioMetadataSubDescriptorBase::setKey = MXF_SET_K(ADMAudioMetadataSubDescriptor); + + +ADMAudioMetadataSubDescriptorBase::ADMAudioMetadataSubDescriptorBase(HeaderMetadata *headerMetadata) +: SubDescriptor(headerMetadata, headerMetadata->createCSet(&setKey)) +{ + headerMetadata->add(this); +} + +ADMAudioMetadataSubDescriptorBase::ADMAudioMetadataSubDescriptorBase(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet) +: SubDescriptor(headerMetadata, cMetadataSet) +{} + +ADMAudioMetadataSubDescriptorBase::~ADMAudioMetadataSubDescriptorBase() +{} + + +uint32_t ADMAudioMetadataSubDescriptorBase::getRIFFChunkStreamID_link1() const +{ + return getUInt32Item(&MXF_ITEM_K(ADMAudioMetadataSubDescriptor, RIFFChunkStreamID_link1)); +} + +bool ADMAudioMetadataSubDescriptorBase::haveADMProfileLevelULBatch() const +{ + return haveItem(&MXF_ITEM_K(ADMAudioMetadataSubDescriptor, ADMProfileLevelULBatch)); +} + +vector ADMAudioMetadataSubDescriptorBase::getADMProfileLevelULBatch() const +{ + return getULArrayItem(&MXF_ITEM_K(ADMAudioMetadataSubDescriptor, ADMProfileLevelULBatch)); +} + +void ADMAudioMetadataSubDescriptorBase::setRIFFChunkStreamID_link1(uint32_t value) +{ + setUInt32Item(&MXF_ITEM_K(ADMAudioMetadataSubDescriptor, RIFFChunkStreamID_link1), value); +} + +void ADMAudioMetadataSubDescriptorBase::setADMProfileLevelULBatch(const vector &value) +{ + setULArrayItem(&MXF_ITEM_K(ADMAudioMetadataSubDescriptor, ADMProfileLevelULBatch), value); +} + +void ADMAudioMetadataSubDescriptorBase::appendADMProfileLevelULBatch(mxfUL value) +{ + appendULArrayItem(&MXF_ITEM_K(ADMAudioMetadataSubDescriptor, ADMProfileLevelULBatch), value); +} + diff --git a/deps/libMXFpp/libMXF++/metadata/base/ADMAudioMetadataSubDescriptorBase.h b/deps/libMXFpp/libMXF++/metadata/base/ADMAudioMetadataSubDescriptorBase.h new file mode 100644 index 00000000..47c4e955 --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/base/ADMAudioMetadataSubDescriptorBase.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MXFPP_ADMAUDIOMETADATASUBDESCRIPTOR_BASE_H_ +#define MXFPP_ADMAUDIOMETADATASUBDESCRIPTOR_BASE_H_ + + + +#include + + +namespace mxfpp +{ + + +class ADMAudioMetadataSubDescriptorBase : public SubDescriptor +{ +public: + friend class MetadataSetFactory; + static const mxfKey setKey; + +public: + ADMAudioMetadataSubDescriptorBase(HeaderMetadata *headerMetadata); + virtual ~ADMAudioMetadataSubDescriptorBase(); + + + // getters + + uint32_t getRIFFChunkStreamID_link1() const; + bool haveADMProfileLevelULBatch() const; + std::vector getADMProfileLevelULBatch() const; + + + // setters + + void setRIFFChunkStreamID_link1(uint32_t value); + void setADMProfileLevelULBatch(const std::vector &value); + void appendADMProfileLevelULBatch(mxfUL value); + + +protected: + ADMAudioMetadataSubDescriptorBase(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet); +}; + + +}; + + +#endif diff --git a/deps/libMXFpp/libMXF++/metadata/base/ADMChannelMappingBase.cpp b/deps/libMXFpp/libMXF++/metadata/base/ADMChannelMappingBase.cpp new file mode 100644 index 00000000..bf4cd006 --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/base/ADMChannelMappingBase.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + + +using namespace std; +using namespace mxfpp; + + +const mxfKey ADMChannelMappingBase::setKey = MXF_SET_K(ADMChannelMapping); + + +ADMChannelMappingBase::ADMChannelMappingBase(HeaderMetadata *headerMetadata) +: InterchangeObject(headerMetadata, headerMetadata->createCSet(&setKey)) +{ + headerMetadata->add(this); +} + +ADMChannelMappingBase::ADMChannelMappingBase(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet) +: InterchangeObject(headerMetadata, cMetadataSet) +{} + +ADMChannelMappingBase::~ADMChannelMappingBase() +{} + + +uint32_t ADMChannelMappingBase::getLocalChannelID() const +{ + return getUInt32Item(&MXF_ITEM_K(ADMChannelMapping, LocalChannelID)); +} + +string ADMChannelMappingBase::getADMAudioTrackUID() const +{ + return getStringItem(&MXF_ITEM_K(ADMChannelMapping, ADMAudioTrackUID)); +} + +string ADMChannelMappingBase::getADMAudioTrackChannelFormatID() const +{ + return getStringItem(&MXF_ITEM_K(ADMChannelMapping, ADMAudioTrackChannelFormatID)); +} + +bool ADMChannelMappingBase::haveADMAudioPackFormatID() const +{ + return haveItem(&MXF_ITEM_K(ADMChannelMapping, ADMAudioPackFormatID)); +} + +string ADMChannelMappingBase::getADMAudioPackFormatID() const +{ + return getStringItem(&MXF_ITEM_K(ADMChannelMapping, ADMAudioPackFormatID)); +} + +void ADMChannelMappingBase::setLocalChannelID(uint32_t value) +{ + setUInt32Item(&MXF_ITEM_K(ADMChannelMapping, LocalChannelID), value); +} + +void ADMChannelMappingBase::setADMAudioTrackUID(const string &value) +{ + setStringItem(&MXF_ITEM_K(ADMChannelMapping, ADMAudioTrackUID), value); +} + +void ADMChannelMappingBase::setADMAudioTrackChannelFormatID(const string &value) +{ + setStringItem(&MXF_ITEM_K(ADMChannelMapping, ADMAudioTrackChannelFormatID), value); +} + +void ADMChannelMappingBase::setADMAudioPackFormatID(const string &value) +{ + setStringItem(&MXF_ITEM_K(ADMChannelMapping, ADMAudioPackFormatID), value); +} diff --git a/deps/libMXFpp/libMXF++/metadata/base/ADMChannelMappingBase.h b/deps/libMXFpp/libMXF++/metadata/base/ADMChannelMappingBase.h new file mode 100644 index 00000000..bb24609d --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/base/ADMChannelMappingBase.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MXFPP_ADMCHANNELMAPPING_BASE_H_ +#define MXFPP_ADMCHANNELMAPPING_BASE_H_ + + + +#include + + +namespace mxfpp +{ + + +class ADMChannelMappingBase : public InterchangeObject +{ +public: + friend class MetadataSetFactory; + static const mxfKey setKey; + +public: + ADMChannelMappingBase(HeaderMetadata *headerMetadata); + virtual ~ADMChannelMappingBase(); + + + // getters + + uint32_t getLocalChannelID() const; + std::string getADMAudioTrackUID() const; + std::string getADMAudioTrackChannelFormatID() const; + bool haveADMAudioPackFormatID() const; + std::string getADMAudioPackFormatID() const; + + + // setters + + void setLocalChannelID(uint32_t value); + void setADMAudioTrackUID(const std::string &value); + void setADMAudioTrackChannelFormatID(const std::string &value); + void setADMAudioPackFormatID(const std::string &value); + + +protected: + ADMChannelMappingBase(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet); +}; + + +}; + + +#endif diff --git a/deps/libMXFpp/libMXF++/metadata/base/ADMSoundfieldGroupLabelSubDescriptorBase.cpp b/deps/libMXFpp/libMXF++/metadata/base/ADMSoundfieldGroupLabelSubDescriptorBase.cpp new file mode 100644 index 00000000..d2fae208 --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/base/ADMSoundfieldGroupLabelSubDescriptorBase.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + + +using namespace std; +using namespace mxfpp; + + +const mxfKey ADMSoundfieldGroupLabelSubDescriptorBase::setKey = MXF_SET_K(ADMSoundfieldGroupLabelSubDescriptor); + + +ADMSoundfieldGroupLabelSubDescriptorBase::ADMSoundfieldGroupLabelSubDescriptorBase(HeaderMetadata *headerMetadata) +: SoundfieldGroupLabelSubDescriptor(headerMetadata, headerMetadata->createCSet(&setKey)) +{ + headerMetadata->add(this); +} + +ADMSoundfieldGroupLabelSubDescriptorBase::ADMSoundfieldGroupLabelSubDescriptorBase(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet) +: SoundfieldGroupLabelSubDescriptor(headerMetadata, cMetadataSet) +{} + +ADMSoundfieldGroupLabelSubDescriptorBase::~ADMSoundfieldGroupLabelSubDescriptorBase() +{} + + +uint32_t ADMSoundfieldGroupLabelSubDescriptorBase::getRIFFChunkStreamID_link2() const +{ + return getUInt32Item(&MXF_ITEM_K(ADMSoundfieldGroupLabelSubDescriptor, RIFFChunkStreamID_link2)); +} + +bool ADMSoundfieldGroupLabelSubDescriptorBase::haveADMAudioProgrammeID_ST2131() const +{ + return haveItem(&MXF_ITEM_K(ADMSoundfieldGroupLabelSubDescriptor, ADMAudioProgrammeID_ST2131)); +} + +string ADMSoundfieldGroupLabelSubDescriptorBase::getADMAudioProgrammeID_ST2131() const +{ + return getStringItem(&MXF_ITEM_K(ADMSoundfieldGroupLabelSubDescriptor, ADMAudioProgrammeID_ST2131)); +} + +bool ADMSoundfieldGroupLabelSubDescriptorBase::haveADMAudioContentID_ST2131() const +{ + return haveItem(&MXF_ITEM_K(ADMSoundfieldGroupLabelSubDescriptor, ADMAudioContentID_ST2131)); +} + +string ADMSoundfieldGroupLabelSubDescriptorBase::getADMAudioContentID_ST2131() const +{ + return getStringItem(&MXF_ITEM_K(ADMSoundfieldGroupLabelSubDescriptor, ADMAudioContentID_ST2131)); +} + +bool ADMSoundfieldGroupLabelSubDescriptorBase::haveADMAudioObjectID_ST2131() const +{ + return haveItem(&MXF_ITEM_K(ADMSoundfieldGroupLabelSubDescriptor, ADMAudioObjectID_ST2131)); +} + +string ADMSoundfieldGroupLabelSubDescriptorBase::getADMAudioObjectID_ST2131() const +{ + return getStringItem(&MXF_ITEM_K(ADMSoundfieldGroupLabelSubDescriptor, ADMAudioObjectID_ST2131)); +} + +void ADMSoundfieldGroupLabelSubDescriptorBase::setRIFFChunkStreamID_link2(uint32_t value) +{ + setUInt32Item(&MXF_ITEM_K(ADMSoundfieldGroupLabelSubDescriptor, RIFFChunkStreamID_link2), value); +} + +void ADMSoundfieldGroupLabelSubDescriptorBase::setADMAudioProgrammeID_ST2131(const string &value) +{ + setStringItem(&MXF_ITEM_K(ADMSoundfieldGroupLabelSubDescriptor, ADMAudioProgrammeID_ST2131), value); +} + +void ADMSoundfieldGroupLabelSubDescriptorBase::setADMAudioContentID_ST2131(const string &value) +{ + setStringItem(&MXF_ITEM_K(ADMSoundfieldGroupLabelSubDescriptor, ADMAudioContentID_ST2131), value); +} + +void ADMSoundfieldGroupLabelSubDescriptorBase::setADMAudioObjectID_ST2131(const string &value) +{ + setStringItem(&MXF_ITEM_K(ADMSoundfieldGroupLabelSubDescriptor, ADMAudioObjectID_ST2131), value); +} diff --git a/deps/libMXFpp/libMXF++/metadata/base/ADMSoundfieldGroupLabelSubDescriptorBase.h b/deps/libMXFpp/libMXF++/metadata/base/ADMSoundfieldGroupLabelSubDescriptorBase.h new file mode 100644 index 00000000..7e50e2b1 --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/base/ADMSoundfieldGroupLabelSubDescriptorBase.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MXFPP_ADMSOUNDFIELDGROUPLABELSUBDESCRIPTOR_BASE_H_ +#define MXFPP_ADMSOUNDFIELDGROUPLABELSUBDESCRIPTOR_BASE_H_ + + + +#include + + +namespace mxfpp +{ + + +class ADMSoundfieldGroupLabelSubDescriptorBase : public SoundfieldGroupLabelSubDescriptor +{ +public: + friend class MetadataSetFactory; + static const mxfKey setKey; + +public: + ADMSoundfieldGroupLabelSubDescriptorBase(HeaderMetadata *headerMetadata); + virtual ~ADMSoundfieldGroupLabelSubDescriptorBase(); + + + // getters + + uint32_t getRIFFChunkStreamID_link2() const; + bool haveADMAudioProgrammeID_ST2131() const; + std::string getADMAudioProgrammeID_ST2131() const; + bool haveADMAudioContentID_ST2131() const; + std::string getADMAudioContentID_ST2131() const; + bool haveADMAudioObjectID_ST2131() const; + std::string getADMAudioObjectID_ST2131() const; + + + // setters + + void setRIFFChunkStreamID_link2(uint32_t value); + void setADMAudioProgrammeID_ST2131(const std::string &value); + void setADMAudioContentID_ST2131(const std::string &value); + void setADMAudioObjectID_ST2131(const std::string &value); + + +protected: + ADMSoundfieldGroupLabelSubDescriptorBase(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet); +}; + + +}; + + +#endif diff --git a/deps/libMXFpp/libMXF++/metadata/base/ADM_CHNASubDescriptorBase.cpp b/deps/libMXFpp/libMXF++/metadata/base/ADM_CHNASubDescriptorBase.cpp new file mode 100644 index 00000000..7d984a37 --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/base/ADM_CHNASubDescriptorBase.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + + +using namespace std; +using namespace mxfpp; + + +const mxfKey ADM_CHNASubDescriptorBase::setKey = MXF_SET_K(ADM_CHNASubDescriptor); + + +ADM_CHNASubDescriptorBase::ADM_CHNASubDescriptorBase(HeaderMetadata *headerMetadata) +: SubDescriptor(headerMetadata, headerMetadata->createCSet(&setKey)) +{ + headerMetadata->add(this); +} + +ADM_CHNASubDescriptorBase::ADM_CHNASubDescriptorBase(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet) +: SubDescriptor(headerMetadata, cMetadataSet) +{} + +ADM_CHNASubDescriptorBase::~ADM_CHNASubDescriptorBase() +{} + + +uint16_t ADM_CHNASubDescriptorBase::getNumLocalChannels() const +{ + return getUInt16Item(&MXF_ITEM_K(ADM_CHNASubDescriptor, NumLocalChannels)); +} + +uint16_t ADM_CHNASubDescriptorBase::getNumADMAudioTrackUIDs() const +{ + return getUInt16Item(&MXF_ITEM_K(ADM_CHNASubDescriptor, NumADMAudioTrackUIDs)); +} + +vector ADM_CHNASubDescriptorBase::getADMChannelMappingsArray() const +{ + vector result; + unique_ptr iter(getStrongRefArrayItem(&MXF_ITEM_K(ADM_CHNASubDescriptor, ADMChannelMappingsArray))); + while (iter->next()) + { + MXFPP_CHECK(dynamic_cast(iter->get()) != 0); + result.push_back(dynamic_cast(iter->get())); + } + return result; +} + +void ADM_CHNASubDescriptorBase::setNumLocalChannels(uint16_t value) +{ + setUInt16Item(&MXF_ITEM_K(ADM_CHNASubDescriptor, NumLocalChannels), value); +} + +void ADM_CHNASubDescriptorBase::setNumADMAudioTrackUIDs(uint16_t value) +{ + setUInt16Item(&MXF_ITEM_K(ADM_CHNASubDescriptor, NumADMAudioTrackUIDs), value); +} + +void ADM_CHNASubDescriptorBase::setADMChannelMappingsArray(const vector &value) +{ + WrapObjectVectorIterator iter(value); + setStrongRefArrayItem(&MXF_ITEM_K(ADM_CHNASubDescriptor, ADMChannelMappingsArray), &iter); +} + +void ADM_CHNASubDescriptorBase::appendADMChannelMappingsArray(ADMChannelMapping *value) +{ + appendStrongRefArrayItem(&MXF_ITEM_K(ADM_CHNASubDescriptor, ADMChannelMappingsArray), value); +} + diff --git a/deps/libMXFpp/libMXF++/metadata/base/ADM_CHNASubDescriptorBase.h b/deps/libMXFpp/libMXF++/metadata/base/ADM_CHNASubDescriptorBase.h new file mode 100644 index 00000000..87b4e416 --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/base/ADM_CHNASubDescriptorBase.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MXFPP_ADM_CHNASUBDESCRIPTOR_BASE_H_ +#define MXFPP_ADM_CHNASUBDESCRIPTOR_BASE_H_ + + + +#include +#include + + +namespace mxfpp +{ + + +class ADM_CHNASubDescriptorBase : public SubDescriptor +{ +public: + friend class MetadataSetFactory; + static const mxfKey setKey; + +public: + ADM_CHNASubDescriptorBase(HeaderMetadata *headerMetadata); + virtual ~ADM_CHNASubDescriptorBase(); + + + // getters + + uint16_t getNumLocalChannels() const; + uint16_t getNumADMAudioTrackUIDs() const; + std::vector getADMChannelMappingsArray() const; + + + // setters + + void setNumLocalChannels(uint16_t value); + void setNumADMAudioTrackUIDs(uint16_t value); + void setADMChannelMappingsArray(const std::vector &value); + void appendADMChannelMappingsArray(ADMChannelMapping *value); + + +protected: + ADM_CHNASubDescriptorBase(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet); +}; + + +}; + + +#endif diff --git a/deps/libMXFpp/libMXF++/metadata/base/RIFFChunkDefinitionSubDescriptorBase.cpp b/deps/libMXFpp/libMXF++/metadata/base/RIFFChunkDefinitionSubDescriptorBase.cpp new file mode 100644 index 00000000..5881935a --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/base/RIFFChunkDefinitionSubDescriptorBase.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + + +using namespace std; +using namespace mxfpp; + + +const mxfKey RIFFChunkDefinitionSubDescriptorBase::setKey = MXF_SET_K(RIFFChunkDefinitionSubDescriptor); + + +RIFFChunkDefinitionSubDescriptorBase::RIFFChunkDefinitionSubDescriptorBase(HeaderMetadata *headerMetadata) +: SubDescriptor(headerMetadata, headerMetadata->createCSet(&setKey)) +{ + headerMetadata->add(this); +} + +RIFFChunkDefinitionSubDescriptorBase::RIFFChunkDefinitionSubDescriptorBase(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet) +: SubDescriptor(headerMetadata, cMetadataSet) +{} + +RIFFChunkDefinitionSubDescriptorBase::~RIFFChunkDefinitionSubDescriptorBase() +{} + + +uint32_t RIFFChunkDefinitionSubDescriptorBase::getRIFFChunkStreamID() const +{ + return getUInt32Item(&MXF_ITEM_K(RIFFChunkDefinitionSubDescriptor, RIFFChunkStreamID)); +} + +mxfRIFFChunkIDType RIFFChunkDefinitionSubDescriptorBase::getRIFFChunkID() const +{ + return getRIFFChunkIDTypeItem(&MXF_ITEM_K(RIFFChunkDefinitionSubDescriptor, RIFFChunkID)); +} + +bool RIFFChunkDefinitionSubDescriptorBase::haveRIFFChunkUUID() const +{ + return haveItem(&MXF_ITEM_K(RIFFChunkDefinitionSubDescriptor, RIFFChunkUUID)); +} + +mxfUUID RIFFChunkDefinitionSubDescriptorBase::getRIFFChunkUUID() const +{ + return getUUIDItem(&MXF_ITEM_K(RIFFChunkDefinitionSubDescriptor, RIFFChunkUUID)); +} + +bool RIFFChunkDefinitionSubDescriptorBase::haveRIFFChunkHashSHA1() const +{ + return haveItem(&MXF_ITEM_K(RIFFChunkDefinitionSubDescriptor, RIFFChunkHashSHA1)); +} + +ByteArray RIFFChunkDefinitionSubDescriptorBase::getRIFFChunkHashSHA1() const +{ + return getRawBytesItem(&MXF_ITEM_K(RIFFChunkDefinitionSubDescriptor, RIFFChunkHashSHA1)); +} + +void RIFFChunkDefinitionSubDescriptorBase::setRIFFChunkStreamID(uint32_t value) +{ + setUInt32Item(&MXF_ITEM_K(RIFFChunkDefinitionSubDescriptor, RIFFChunkStreamID), value); +} + +void RIFFChunkDefinitionSubDescriptorBase::setRIFFChunkID(mxfRIFFChunkIDType value) +{ + setRIFFChunkIDTypeItem(&MXF_ITEM_K(RIFFChunkDefinitionSubDescriptor, RIFFChunkID), value); +} + +void RIFFChunkDefinitionSubDescriptorBase::setRIFFChunkUUID(mxfUUID value) +{ + setUUIDItem(&MXF_ITEM_K(RIFFChunkDefinitionSubDescriptor, RIFFChunkUUID), value); +} + +void RIFFChunkDefinitionSubDescriptorBase::setRIFFChunkHashSHA1(ByteArray value) +{ + setRawBytesItem(&MXF_ITEM_K(RIFFChunkDefinitionSubDescriptor, RIFFChunkHashSHA1), value); +} + diff --git a/deps/libMXFpp/libMXF++/metadata/base/RIFFChunkDefinitionSubDescriptorBase.h b/deps/libMXFpp/libMXF++/metadata/base/RIFFChunkDefinitionSubDescriptorBase.h new file mode 100644 index 00000000..32a40002 --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/base/RIFFChunkDefinitionSubDescriptorBase.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MXFPP_RIFFCHUNKDEFINITIONSUBDESCRIPTOR_BASE_H_ +#define MXFPP_RIFFCHUNKDEFINITIONSUBDESCRIPTOR_BASE_H_ + + + +#include + + +namespace mxfpp +{ + + +class RIFFChunkDefinitionSubDescriptorBase : public SubDescriptor +{ +public: + friend class MetadataSetFactory; + static const mxfKey setKey; + +public: + RIFFChunkDefinitionSubDescriptorBase(HeaderMetadata *headerMetadata); + virtual ~RIFFChunkDefinitionSubDescriptorBase(); + + + // getters + + uint32_t getRIFFChunkStreamID() const; + mxfRIFFChunkIDType getRIFFChunkID() const; + bool haveRIFFChunkUUID() const; + mxfUUID getRIFFChunkUUID() const; + bool haveRIFFChunkHashSHA1() const; + ByteArray getRIFFChunkHashSHA1() const; + + + // setters + + void setRIFFChunkStreamID(uint32_t value); + void setRIFFChunkID(mxfRIFFChunkIDType value); + void setRIFFChunkUUID(mxfUUID value); + void setRIFFChunkHashSHA1(ByteArray value); + + +protected: + RIFFChunkDefinitionSubDescriptorBase(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet); +}; + + +}; + + +#endif diff --git a/deps/libMXFpp/libMXF++/metadata/base/RIFFChunkReferencesSubDescriptorBase.cpp b/deps/libMXFpp/libMXF++/metadata/base/RIFFChunkReferencesSubDescriptorBase.cpp new file mode 100644 index 00000000..b3af2e88 --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/base/RIFFChunkReferencesSubDescriptorBase.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + + +using namespace std; +using namespace mxfpp; + + +const mxfKey RIFFChunkReferencesSubDescriptorBase::setKey = MXF_SET_K(RIFFChunkReferencesSubDescriptor); + + +RIFFChunkReferencesSubDescriptorBase::RIFFChunkReferencesSubDescriptorBase(HeaderMetadata *headerMetadata) +: SubDescriptor(headerMetadata, headerMetadata->createCSet(&setKey)) +{ + headerMetadata->add(this); +} + +RIFFChunkReferencesSubDescriptorBase::RIFFChunkReferencesSubDescriptorBase(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet) +: SubDescriptor(headerMetadata, cMetadataSet) +{} + +RIFFChunkReferencesSubDescriptorBase::~RIFFChunkReferencesSubDescriptorBase() +{} + + +vector RIFFChunkReferencesSubDescriptorBase::getRIFFChunkStreamIDsArray() const +{ + return getUInt32ArrayItem(&MXF_ITEM_K(RIFFChunkReferencesSubDescriptor, RIFFChunkStreamIDsArray)); +} + +void RIFFChunkReferencesSubDescriptorBase::setRIFFChunkStreamIDsArray(const vector &value) +{ + setUInt32ArrayItem(&MXF_ITEM_K(RIFFChunkReferencesSubDescriptor, RIFFChunkStreamIDsArray), value); +} + +void RIFFChunkReferencesSubDescriptorBase::appendRIFFChunkStreamIDsArray(uint32_t value) +{ + appendUInt32ArrayItem(&MXF_ITEM_K(RIFFChunkReferencesSubDescriptor, RIFFChunkStreamIDsArray), value); +} + diff --git a/deps/libMXFpp/libMXF++/metadata/base/RIFFChunkReferencesSubDescriptorBase.h b/deps/libMXFpp/libMXF++/metadata/base/RIFFChunkReferencesSubDescriptorBase.h new file mode 100644 index 00000000..01027fb5 --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/base/RIFFChunkReferencesSubDescriptorBase.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MXFPP_RIFFCHUNKREFERENCESSUBDESCRIPTOR_BASE_H_ +#define MXFPP_RIFFCHUNKREFERENCESSUBDESCRIPTOR_BASE_H_ + + + +#include + + +namespace mxfpp +{ + + +class RIFFChunkReferencesSubDescriptorBase : public SubDescriptor +{ +public: + friend class MetadataSetFactory; + static const mxfKey setKey; + +public: + RIFFChunkReferencesSubDescriptorBase(HeaderMetadata *headerMetadata); + virtual ~RIFFChunkReferencesSubDescriptorBase(); + + + // getters + + std::vector getRIFFChunkStreamIDsArray() const; + + + // setters + + void setRIFFChunkStreamIDsArray(const std::vector &value); + void appendRIFFChunkStreamIDsArray(uint32_t value); + + +protected: + RIFFChunkReferencesSubDescriptorBase(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet); +}; + + +}; + + +#endif From 30f18c0cd14f370e77f5648e777389c70bfaa012 Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Wed, 22 Nov 2023 12:35:05 +0000 Subject: [PATCH 06/65] libmxfpp: Include mxf.h where it's required in headers --- deps/libMXFpp/libMXF++/AvidHeaderMetadata.h | 2 ++ deps/libMXFpp/libMXF++/DataModel.h | 1 + deps/libMXFpp/libMXF++/File.h | 4 ++-- deps/libMXFpp/libMXF++/HeaderMetadata.h | 2 ++ deps/libMXFpp/libMXF++/IndexTable.h | 1 + deps/libMXFpp/libMXF++/MetadataSet.h | 1 + deps/libMXFpp/libMXF++/Partition.h | 1 + 7 files changed, 10 insertions(+), 2 deletions(-) diff --git a/deps/libMXFpp/libMXF++/AvidHeaderMetadata.h b/deps/libMXFpp/libMXF++/AvidHeaderMetadata.h index 0b52f1d7..54ee4cfe 100644 --- a/deps/libMXFpp/libMXF++/AvidHeaderMetadata.h +++ b/deps/libMXFpp/libMXF++/AvidHeaderMetadata.h @@ -33,6 +33,8 @@ #define MXFPP_AVIDHEADERMETADATA_H_ +#include + #include diff --git a/deps/libMXFpp/libMXF++/DataModel.h b/deps/libMXFpp/libMXF++/DataModel.h index 97248e5d..dd32fd00 100644 --- a/deps/libMXFpp/libMXF++/DataModel.h +++ b/deps/libMXFpp/libMXF++/DataModel.h @@ -32,6 +32,7 @@ #ifndef MXFPP_DATA_MODEL_H_ #define MXFPP_DATA_MODEL_H_ +#include namespace mxfpp diff --git a/deps/libMXFpp/libMXF++/File.h b/deps/libMXFpp/libMXF++/File.h index 9ba07166..77b8598a 100644 --- a/deps/libMXFpp/libMXF++/File.h +++ b/deps/libMXFpp/libMXF++/File.h @@ -35,10 +35,10 @@ #include #include -#include - +#include #include +#include namespace mxfpp diff --git a/deps/libMXFpp/libMXF++/HeaderMetadata.h b/deps/libMXFpp/libMXF++/HeaderMetadata.h index 028af3d1..8912a17d 100644 --- a/deps/libMXFpp/libMXF++/HeaderMetadata.h +++ b/deps/libMXFpp/libMXF++/HeaderMetadata.h @@ -34,6 +34,8 @@ #include +#include + #include #include diff --git a/deps/libMXFpp/libMXF++/IndexTable.h b/deps/libMXFpp/libMXF++/IndexTable.h index f24c547c..284621f0 100644 --- a/deps/libMXFpp/libMXF++/IndexTable.h +++ b/deps/libMXFpp/libMXF++/IndexTable.h @@ -34,6 +34,7 @@ #include +#include namespace mxfpp diff --git a/deps/libMXFpp/libMXF++/MetadataSet.h b/deps/libMXFpp/libMXF++/MetadataSet.h index 8a05b029..0ee9991d 100644 --- a/deps/libMXFpp/libMXF++/MetadataSet.h +++ b/deps/libMXFpp/libMXF++/MetadataSet.h @@ -35,6 +35,7 @@ #include #include +#include namespace mxfpp diff --git a/deps/libMXFpp/libMXF++/Partition.h b/deps/libMXFpp/libMXF++/Partition.h index 523514e8..08d86dfd 100644 --- a/deps/libMXFpp/libMXF++/Partition.h +++ b/deps/libMXFpp/libMXF++/Partition.h @@ -32,6 +32,7 @@ #ifndef MXFPP_PARTITION_H_ #define MXFPP_PARTITION_H_ +#include namespace mxfpp From 3b4926fdd5cdf6691fe8dec0f2ff29b606be9e7a Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Wed, 22 Nov 2023 12:35:37 +0000 Subject: [PATCH 07/65] libmxfpp: Add missing include for msvc 2019 build --- deps/libMXFpp/libMXF++/MetadataSet.h | 1 + 1 file changed, 1 insertion(+) diff --git a/deps/libMXFpp/libMXF++/MetadataSet.h b/deps/libMXFpp/libMXF++/MetadataSet.h index 0ee9991d..33a48028 100644 --- a/deps/libMXFpp/libMXF++/MetadataSet.h +++ b/deps/libMXFpp/libMXF++/MetadataSet.h @@ -34,6 +34,7 @@ #include #include +#include #include From a4e7a9ab8a0fd19c7dbd0271e05ab849cbb455c1 Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Wed, 22 Nov 2023 12:38:24 +0000 Subject: [PATCH 08/65] libmxfpp: Add MGA sound descriptors --- deps/libMXFpp/libMXF++/HeaderMetadata.cpp | 4 + .../MGAAudioMetadataSubDescriptor.cpp | 53 ++++++++ .../metadata/MGAAudioMetadataSubDescriptor.h | 62 ++++++++++ .../metadata/MGASoundEssenceDescriptor.cpp | 52 ++++++++ .../metadata/MGASoundEssenceDescriptor.h | 60 +++++++++ .../MGASoundfieldGroupLabelSubDescriptor.cpp | 53 ++++++++ .../MGASoundfieldGroupLabelSubDescriptor.h | 62 ++++++++++ deps/libMXFpp/libMXF++/metadata/Metadata.h | 4 + .../SADMAudioMetadataSubDescriptor.cpp | 53 ++++++++ .../metadata/SADMAudioMetadataSubDescriptor.h | 62 ++++++++++ .../MGAAudioMetadataSubDescriptorBase.cpp | 105 ++++++++++++++++ .../base/MGAAudioMetadataSubDescriptorBase.h | 79 ++++++++++++ .../base/MGASoundEssenceDescriptorBase.cpp | 94 ++++++++++++++ .../base/MGASoundEssenceDescriptorBase.h | 73 +++++++++++ ...ASoundfieldGroupLabelSubDescriptorBase.cpp | 115 ++++++++++++++++++ ...MGASoundfieldGroupLabelSubDescriptorBase.h | 82 +++++++++++++ .../SADMAudioMetadataSubDescriptorBase.cpp | 90 ++++++++++++++ .../base/SADMAudioMetadataSubDescriptorBase.h | 77 ++++++++++++ 18 files changed, 1180 insertions(+) create mode 100644 deps/libMXFpp/libMXF++/metadata/MGAAudioMetadataSubDescriptor.cpp create mode 100644 deps/libMXFpp/libMXF++/metadata/MGAAudioMetadataSubDescriptor.h create mode 100644 deps/libMXFpp/libMXF++/metadata/MGASoundEssenceDescriptor.cpp create mode 100644 deps/libMXFpp/libMXF++/metadata/MGASoundEssenceDescriptor.h create mode 100644 deps/libMXFpp/libMXF++/metadata/MGASoundfieldGroupLabelSubDescriptor.cpp create mode 100644 deps/libMXFpp/libMXF++/metadata/MGASoundfieldGroupLabelSubDescriptor.h create mode 100644 deps/libMXFpp/libMXF++/metadata/SADMAudioMetadataSubDescriptor.cpp create mode 100644 deps/libMXFpp/libMXF++/metadata/SADMAudioMetadataSubDescriptor.h create mode 100644 deps/libMXFpp/libMXF++/metadata/base/MGAAudioMetadataSubDescriptorBase.cpp create mode 100644 deps/libMXFpp/libMXF++/metadata/base/MGAAudioMetadataSubDescriptorBase.h create mode 100644 deps/libMXFpp/libMXF++/metadata/base/MGASoundEssenceDescriptorBase.cpp create mode 100644 deps/libMXFpp/libMXF++/metadata/base/MGASoundEssenceDescriptorBase.h create mode 100644 deps/libMXFpp/libMXF++/metadata/base/MGASoundfieldGroupLabelSubDescriptorBase.cpp create mode 100644 deps/libMXFpp/libMXF++/metadata/base/MGASoundfieldGroupLabelSubDescriptorBase.h create mode 100644 deps/libMXFpp/libMXF++/metadata/base/SADMAudioMetadataSubDescriptorBase.cpp create mode 100644 deps/libMXFpp/libMXF++/metadata/base/SADMAudioMetadataSubDescriptorBase.h diff --git a/deps/libMXFpp/libMXF++/HeaderMetadata.cpp b/deps/libMXFpp/libMXF++/HeaderMetadata.cpp index d9bd46fb..02aec2f2 100644 --- a/deps/libMXFpp/libMXF++/HeaderMetadata.cpp +++ b/deps/libMXFpp/libMXF++/HeaderMetadata.cpp @@ -319,6 +319,10 @@ void HeaderMetadata::initialiseObjectFactory() REGISTER_CLASS(ADMChannelMapping); REGISTER_CLASS(RIFFChunkReferencesSubDescriptor); REGISTER_CLASS(ADMSoundfieldGroupLabelSubDescriptor); + REGISTER_CLASS(MGASoundEssenceDescriptor); + REGISTER_CLASS(MGAAudioMetadataSubDescriptor); + REGISTER_CLASS(SADMAudioMetadataSubDescriptor); + REGISTER_CLASS(MGASoundfieldGroupLabelSubDescriptor); REGISTER_CLASS(ContainerConstraintsSubDescriptor); // Add new classes here diff --git a/deps/libMXFpp/libMXF++/metadata/MGAAudioMetadataSubDescriptor.cpp b/deps/libMXFpp/libMXF++/metadata/MGAAudioMetadataSubDescriptor.cpp new file mode 100644 index 00000000..093ac6e8 --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/MGAAudioMetadataSubDescriptor.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2023, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + + +using namespace std; +using namespace mxfpp; + + + +MGAAudioMetadataSubDescriptor::MGAAudioMetadataSubDescriptor(HeaderMetadata *headerMetadata) +: MGAAudioMetadataSubDescriptorBase(headerMetadata) +{} + +MGAAudioMetadataSubDescriptor::MGAAudioMetadataSubDescriptor(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet) +: MGAAudioMetadataSubDescriptorBase(headerMetadata, cMetadataSet) +{} + +MGAAudioMetadataSubDescriptor::~MGAAudioMetadataSubDescriptor() +{} diff --git a/deps/libMXFpp/libMXF++/metadata/MGAAudioMetadataSubDescriptor.h b/deps/libMXFpp/libMXF++/metadata/MGAAudioMetadataSubDescriptor.h new file mode 100644 index 00000000..9e344794 --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/MGAAudioMetadataSubDescriptor.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2023, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MXFPP_MGAAUDIOMETADATASUBDESCRIPTOR_H_ +#define MXFPP_MGAAUDIOMETADATASUBDESCRIPTOR_H_ + + + +#include + + +namespace mxfpp +{ + + +class MGAAudioMetadataSubDescriptor : public MGAAudioMetadataSubDescriptorBase +{ +public: + friend class MetadataSetFactory; + +public: + MGAAudioMetadataSubDescriptor(HeaderMetadata *headerMetadata); + virtual ~MGAAudioMetadataSubDescriptor(); + + +protected: + MGAAudioMetadataSubDescriptor(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet); +}; + + +}; + + +#endif diff --git a/deps/libMXFpp/libMXF++/metadata/MGASoundEssenceDescriptor.cpp b/deps/libMXFpp/libMXF++/metadata/MGASoundEssenceDescriptor.cpp new file mode 100644 index 00000000..49047e9b --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/MGASoundEssenceDescriptor.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2023, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +using namespace std; +using namespace mxfpp; + + + +MGASoundEssenceDescriptor::MGASoundEssenceDescriptor(HeaderMetadata *headerMetadata) +: MGASoundEssenceDescriptorBase(headerMetadata) +{} + +MGASoundEssenceDescriptor::MGASoundEssenceDescriptor(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet) +: MGASoundEssenceDescriptorBase(headerMetadata, cMetadataSet) +{} + +MGASoundEssenceDescriptor::~MGASoundEssenceDescriptor() +{} diff --git a/deps/libMXFpp/libMXF++/metadata/MGASoundEssenceDescriptor.h b/deps/libMXFpp/libMXF++/metadata/MGASoundEssenceDescriptor.h new file mode 100644 index 00000000..ddf0107d --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/MGASoundEssenceDescriptor.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2023, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MXFPP_MGASOUNDESSENCEDESCRIPTOR_H_ +#define MXFPP_MGASOUNDESSENCEDESCRIPTOR_H_ + + +#include + + +namespace mxfpp +{ + + +class MGASoundEssenceDescriptor : public MGASoundEssenceDescriptorBase +{ +public: + friend class MetadataSetFactory; + +public: + MGASoundEssenceDescriptor(HeaderMetadata *headerMetadata); + virtual ~MGASoundEssenceDescriptor(); + +protected: + MGASoundEssenceDescriptor(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet); +}; + + +}; + + +#endif diff --git a/deps/libMXFpp/libMXF++/metadata/MGASoundfieldGroupLabelSubDescriptor.cpp b/deps/libMXFpp/libMXF++/metadata/MGASoundfieldGroupLabelSubDescriptor.cpp new file mode 100644 index 00000000..4ad23476 --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/MGASoundfieldGroupLabelSubDescriptor.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2023, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + + +using namespace std; +using namespace mxfpp; + + + +MGASoundfieldGroupLabelSubDescriptor::MGASoundfieldGroupLabelSubDescriptor(HeaderMetadata *headerMetadata) +: MGASoundfieldGroupLabelSubDescriptorBase(headerMetadata) +{} + +MGASoundfieldGroupLabelSubDescriptor::MGASoundfieldGroupLabelSubDescriptor(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet) +: MGASoundfieldGroupLabelSubDescriptorBase(headerMetadata, cMetadataSet) +{} + +MGASoundfieldGroupLabelSubDescriptor::~MGASoundfieldGroupLabelSubDescriptor() +{} diff --git a/deps/libMXFpp/libMXF++/metadata/MGASoundfieldGroupLabelSubDescriptor.h b/deps/libMXFpp/libMXF++/metadata/MGASoundfieldGroupLabelSubDescriptor.h new file mode 100644 index 00000000..11cdab1d --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/MGASoundfieldGroupLabelSubDescriptor.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2023, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MXFPP_MGASOUNDFIELDGROUPLABELSUBDESCRIPTOR_H_ +#define MXFPP_MGASOUNDFIELDGROUPLABELSUBDESCRIPTOR_H_ + + + +#include + + +namespace mxfpp +{ + + +class MGASoundfieldGroupLabelSubDescriptor : public MGASoundfieldGroupLabelSubDescriptorBase +{ +public: + friend class MetadataSetFactory; + +public: + MGASoundfieldGroupLabelSubDescriptor(HeaderMetadata *headerMetadata); + virtual ~MGASoundfieldGroupLabelSubDescriptor(); + + +protected: + MGASoundfieldGroupLabelSubDescriptor(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet); +}; + + +}; + + +#endif diff --git a/deps/libMXFpp/libMXF++/metadata/Metadata.h b/deps/libMXFpp/libMXF++/metadata/Metadata.h index bcb5b1b5..eb898b7c 100644 --- a/deps/libMXFpp/libMXF++/metadata/Metadata.h +++ b/deps/libMXFpp/libMXF++/metadata/Metadata.h @@ -91,6 +91,10 @@ #include #include #include +#include +#include +#include +#include #include diff --git a/deps/libMXFpp/libMXF++/metadata/SADMAudioMetadataSubDescriptor.cpp b/deps/libMXFpp/libMXF++/metadata/SADMAudioMetadataSubDescriptor.cpp new file mode 100644 index 00000000..cbb70e86 --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/SADMAudioMetadataSubDescriptor.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2023, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + + +using namespace std; +using namespace mxfpp; + + + +SADMAudioMetadataSubDescriptor::SADMAudioMetadataSubDescriptor(HeaderMetadata *headerMetadata) +: SADMAudioMetadataSubDescriptorBase(headerMetadata) +{} + +SADMAudioMetadataSubDescriptor::SADMAudioMetadataSubDescriptor(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet) +: SADMAudioMetadataSubDescriptorBase(headerMetadata, cMetadataSet) +{} + +SADMAudioMetadataSubDescriptor::~SADMAudioMetadataSubDescriptor() +{} diff --git a/deps/libMXFpp/libMXF++/metadata/SADMAudioMetadataSubDescriptor.h b/deps/libMXFpp/libMXF++/metadata/SADMAudioMetadataSubDescriptor.h new file mode 100644 index 00000000..ca711178 --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/SADMAudioMetadataSubDescriptor.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2023, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MXFPP_SADMAUDIOMETADATASUBDESCRIPTOR_H_ +#define MXFPP_SADMAUDIOMETADATASUBDESCRIPTOR_H_ + + + +#include + + +namespace mxfpp +{ + + +class SADMAudioMetadataSubDescriptor : public SADMAudioMetadataSubDescriptorBase +{ +public: + friend class MetadataSetFactory; + +public: + SADMAudioMetadataSubDescriptor(HeaderMetadata *headerMetadata); + virtual ~SADMAudioMetadataSubDescriptor(); + + +protected: + SADMAudioMetadataSubDescriptor(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet); +}; + + +}; + + +#endif diff --git a/deps/libMXFpp/libMXF++/metadata/base/MGAAudioMetadataSubDescriptorBase.cpp b/deps/libMXFpp/libMXF++/metadata/base/MGAAudioMetadataSubDescriptorBase.cpp new file mode 100644 index 00000000..e2db9f61 --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/base/MGAAudioMetadataSubDescriptorBase.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2023, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + + +using namespace std; +using namespace mxfpp; + + +const mxfKey MGAAudioMetadataSubDescriptorBase::setKey = MXF_SET_K(MGAAudioMetadataSubDescriptor); + + +MGAAudioMetadataSubDescriptorBase::MGAAudioMetadataSubDescriptorBase(HeaderMetadata *headerMetadata) +: SubDescriptor(headerMetadata, headerMetadata->createCSet(&setKey)) +{ + headerMetadata->add(this); +} + +MGAAudioMetadataSubDescriptorBase::MGAAudioMetadataSubDescriptorBase(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet) +: SubDescriptor(headerMetadata, cMetadataSet) +{} + +MGAAudioMetadataSubDescriptorBase::~MGAAudioMetadataSubDescriptorBase() +{} + + +mxfUUID MGAAudioMetadataSubDescriptorBase::getMGALinkID() const +{ + return getUUIDItem(&MXF_ITEM_K(MGAAudioMetadataSubDescriptor, MGALinkID)); +} + +uint8_t MGAAudioMetadataSubDescriptorBase::getMGAAudioMetadataIndex() const +{ + return getUInt8Item(&MXF_ITEM_K(MGAAudioMetadataSubDescriptor, MGAAudioMetadataIndex)); +} + +uint8_t MGAAudioMetadataSubDescriptorBase::getMGAAudioMetadataIdentifier() const +{ + return getUInt8Item(&MXF_ITEM_K(MGAAudioMetadataSubDescriptor, MGAAudioMetadataIdentifier)); +} + +vector MGAAudioMetadataSubDescriptorBase::getMGAAudioMetadataPayloadULArray() const +{ + return getULArrayItem(&MXF_ITEM_K(MGAAudioMetadataSubDescriptor, MGAAudioMetadataPayloadULArray)); +} + +void MGAAudioMetadataSubDescriptorBase::setMGALinkID(mxfUUID value) +{ + setUUIDItem(&MXF_ITEM_K(MGAAudioMetadataSubDescriptor, MGALinkID), value); +} + +void MGAAudioMetadataSubDescriptorBase::setMGAAudioMetadataIndex(uint8_t value) +{ + setUInt8Item(&MXF_ITEM_K(MGAAudioMetadataSubDescriptor, MGAAudioMetadataIndex), value); +} + +void MGAAudioMetadataSubDescriptorBase::setMGAAudioMetadataIdentifier(uint8_t value) +{ + setUInt8Item(&MXF_ITEM_K(MGAAudioMetadataSubDescriptor, MGAAudioMetadataIdentifier), value); +} + +void MGAAudioMetadataSubDescriptorBase::setMGAAudioMetadataPayloadULArray(const vector &value) +{ + setULArrayItem(&MXF_ITEM_K(MGAAudioMetadataSubDescriptor, MGAAudioMetadataPayloadULArray), value); +} + +void MGAAudioMetadataSubDescriptorBase::appendMGAAudioMetadataPayloadULArray(mxfUL value) +{ + appendULArrayItem(&MXF_ITEM_K(MGAAudioMetadataSubDescriptor, MGAAudioMetadataPayloadULArray), value); +} diff --git a/deps/libMXFpp/libMXF++/metadata/base/MGAAudioMetadataSubDescriptorBase.h b/deps/libMXFpp/libMXF++/metadata/base/MGAAudioMetadataSubDescriptorBase.h new file mode 100644 index 00000000..3bf5e4dc --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/base/MGAAudioMetadataSubDescriptorBase.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2023, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MXFPP_MGAAUDIOMETADATASUBDESCRIPTOR_BASE_H_ +#define MXFPP_MGAAUDIOMETADATASUBDESCRIPTOR_BASE_H_ + + +#include + + +namespace mxfpp +{ + + +class MGAAudioMetadataSubDescriptorBase : public SubDescriptor +{ +public: + friend class MetadataSetFactory; + static const mxfKey setKey; + +public: + MGAAudioMetadataSubDescriptorBase(HeaderMetadata *headerMetadata); + virtual ~MGAAudioMetadataSubDescriptorBase(); + + + // getters + + mxfUUID getMGALinkID() const; + uint8_t getMGAAudioMetadataIndex() const; + uint8_t getMGAAudioMetadataIdentifier() const; + std::vector getMGAAudioMetadataPayloadULArray() const; + + + // setters + + void setMGALinkID(mxfUUID value); + void setMGAAudioMetadataIndex(uint8_t value); + void setMGAAudioMetadataIdentifier(uint8_t value); + void setMGAAudioMetadataPayloadULArray(const std::vector &value); + void appendMGAAudioMetadataPayloadULArray(mxfUL value); + + +protected: + MGAAudioMetadataSubDescriptorBase(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet); +}; + + +}; + + +#endif diff --git a/deps/libMXFpp/libMXF++/metadata/base/MGASoundEssenceDescriptorBase.cpp b/deps/libMXFpp/libMXF++/metadata/base/MGASoundEssenceDescriptorBase.cpp new file mode 100644 index 00000000..e75fdf0d --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/base/MGASoundEssenceDescriptorBase.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2023, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + +using namespace std; +using namespace mxfpp; + + + +const mxfKey MGASoundEssenceDescriptorBase::setKey = MXF_SET_K(MGASoundEssenceDescriptor); + + +MGASoundEssenceDescriptorBase::MGASoundEssenceDescriptorBase(HeaderMetadata *headerMetadata) +: GenericSoundEssenceDescriptor(headerMetadata, headerMetadata->createCSet(&setKey)) +{ + headerMetadata->add(this); +} + +MGASoundEssenceDescriptorBase::MGASoundEssenceDescriptorBase(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet) +: GenericSoundEssenceDescriptor(headerMetadata, cMetadataSet) +{} + +MGASoundEssenceDescriptorBase::~MGASoundEssenceDescriptorBase() +{} + +uint16_t MGASoundEssenceDescriptorBase::getMGASoundEssenceBlockAlign() const +{ + return getUInt16Item(&MXF_ITEM_K(MGASoundEssenceDescriptor, MGASoundEssenceBlockAlign)); +} + +uint32_t MGASoundEssenceDescriptorBase::getMGASoundEssenceAverageBytesPerSecond() const +{ + return getUInt32Item(&MXF_ITEM_K(MGASoundEssenceDescriptor, MGASoundEssenceAverageBytesPerSecond)); +} + +bool MGASoundEssenceDescriptorBase::haveMGASoundEssenceSequenceOffset() const +{ + return haveItem(&MXF_ITEM_K(MGASoundEssenceDescriptor, MGASoundEssenceSequenceOffset)); +} + +uint8_t MGASoundEssenceDescriptorBase::getMGASoundEssenceSequenceOffset() const +{ + return getUInt8Item(&MXF_ITEM_K(MGASoundEssenceDescriptor, MGASoundEssenceSequenceOffset)); +} + +void MGASoundEssenceDescriptorBase::setMGASoundEssenceBlockAlign(uint16_t value) +{ + setUInt16Item(&MXF_ITEM_K(MGASoundEssenceDescriptor, MGASoundEssenceBlockAlign), value); +} + +void MGASoundEssenceDescriptorBase::setMGASoundEssenceAverageBytesPerSecond(uint32_t value) +{ + setUInt32Item(&MXF_ITEM_K(MGASoundEssenceDescriptor, MGASoundEssenceAverageBytesPerSecond), value); +} + +void MGASoundEssenceDescriptorBase::setMGASoundEssenceSequenceOffset(uint8_t value) +{ + setUInt8Item(&MXF_ITEM_K(MGASoundEssenceDescriptor, MGASoundEssenceSequenceOffset), value); +} diff --git a/deps/libMXFpp/libMXF++/metadata/base/MGASoundEssenceDescriptorBase.h b/deps/libMXFpp/libMXF++/metadata/base/MGASoundEssenceDescriptorBase.h new file mode 100644 index 00000000..d448ceeb --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/base/MGASoundEssenceDescriptorBase.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2023, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MXFPP_MGASOUNDESSENCEDESCRIPTOR_BASE_H_ +#define MXFPP_MGASOUNDESSENCEDESCRIPTOR_BASE_H_ + + +#include + + +namespace mxfpp +{ + + +class MGASoundEssenceDescriptorBase : public GenericSoundEssenceDescriptor +{ +public: + friend class MetadataSetFactory; + static const mxfKey setKey; + +public: + MGASoundEssenceDescriptorBase(HeaderMetadata *headerMetadata); + virtual ~MGASoundEssenceDescriptorBase(); + + // getters + uint16_t getMGASoundEssenceBlockAlign() const; + uint32_t getMGASoundEssenceAverageBytesPerSecond() const; + bool haveMGASoundEssenceSequenceOffset() const; + uint8_t getMGASoundEssenceSequenceOffset() const; + + + // setters + void setMGASoundEssenceBlockAlign(uint16_t value); + void setMGASoundEssenceAverageBytesPerSecond(uint32_t value); + void setMGASoundEssenceSequenceOffset(uint8_t value); + +protected: + MGASoundEssenceDescriptorBase(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet); +}; + + +}; + + +#endif diff --git a/deps/libMXFpp/libMXF++/metadata/base/MGASoundfieldGroupLabelSubDescriptorBase.cpp b/deps/libMXFpp/libMXF++/metadata/base/MGASoundfieldGroupLabelSubDescriptorBase.cpp new file mode 100644 index 00000000..a14b35ad --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/base/MGASoundfieldGroupLabelSubDescriptorBase.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2023, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + + +using namespace std; +using namespace mxfpp; + + +const mxfKey MGASoundfieldGroupLabelSubDescriptorBase::setKey = MXF_SET_K(MGASoundfieldGroupLabelSubDescriptor); + + +MGASoundfieldGroupLabelSubDescriptorBase::MGASoundfieldGroupLabelSubDescriptorBase(HeaderMetadata *headerMetadata) +: SoundfieldGroupLabelSubDescriptor(headerMetadata, headerMetadata->createCSet(&setKey)) +{ + headerMetadata->add(this); +} + +MGASoundfieldGroupLabelSubDescriptorBase::MGASoundfieldGroupLabelSubDescriptorBase(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet) +: SoundfieldGroupLabelSubDescriptor(headerMetadata, cMetadataSet) +{} + +MGASoundfieldGroupLabelSubDescriptorBase::~MGASoundfieldGroupLabelSubDescriptorBase() +{} + + +mxfUUID MGASoundfieldGroupLabelSubDescriptorBase::getMGAMetadataSectionLinkID() const +{ + return getUUIDItem(&MXF_ITEM_K(MGASoundfieldGroupLabelSubDescriptor, MGAMetadataSectionLinkID)); +} + +bool MGASoundfieldGroupLabelSubDescriptorBase::haveADMAudioProgrammeID() const +{ + return haveItem(&MXF_ITEM_K(MGASoundfieldGroupLabelSubDescriptor, ADMAudioProgrammeID)); +} + +string MGASoundfieldGroupLabelSubDescriptorBase::getADMAudioProgrammeID() const +{ + return getStringItem(&MXF_ITEM_K(MGASoundfieldGroupLabelSubDescriptor, ADMAudioProgrammeID)); +} + +bool MGASoundfieldGroupLabelSubDescriptorBase::haveADMAudioContentID() const +{ + return haveItem(&MXF_ITEM_K(MGASoundfieldGroupLabelSubDescriptor, ADMAudioContentID)); +} + +string MGASoundfieldGroupLabelSubDescriptorBase::getADMAudioContentID() const +{ + return getStringItem(&MXF_ITEM_K(MGASoundfieldGroupLabelSubDescriptor, ADMAudioContentID)); +} + +bool MGASoundfieldGroupLabelSubDescriptorBase::haveADMAudioObjectID() const +{ + return haveItem(&MXF_ITEM_K(MGASoundfieldGroupLabelSubDescriptor, ADMAudioObjectID)); +} + +string MGASoundfieldGroupLabelSubDescriptorBase::getADMAudioObjectID() const +{ + return getStringItem(&MXF_ITEM_K(MGASoundfieldGroupLabelSubDescriptor, ADMAudioObjectID)); +} + +void MGASoundfieldGroupLabelSubDescriptorBase::setMGAMetadataSectionLinkID(mxfUUID value) +{ + setUUIDItem(&MXF_ITEM_K(MGASoundfieldGroupLabelSubDescriptor, MGAMetadataSectionLinkID), value); +} + +void MGASoundfieldGroupLabelSubDescriptorBase::setADMAudioProgrammeID(const string &value) +{ + setStringItem(&MXF_ITEM_K(MGASoundfieldGroupLabelSubDescriptor, ADMAudioProgrammeID), value); +} + +void MGASoundfieldGroupLabelSubDescriptorBase::setADMAudioContentID(const string &value) +{ + setStringItem(&MXF_ITEM_K(MGASoundfieldGroupLabelSubDescriptor, ADMAudioContentID), value); +} + +void MGASoundfieldGroupLabelSubDescriptorBase::setADMAudioObjectID(const string &value) +{ + setStringItem(&MXF_ITEM_K(MGASoundfieldGroupLabelSubDescriptor, ADMAudioObjectID), value); +} diff --git a/deps/libMXFpp/libMXF++/metadata/base/MGASoundfieldGroupLabelSubDescriptorBase.h b/deps/libMXFpp/libMXF++/metadata/base/MGASoundfieldGroupLabelSubDescriptorBase.h new file mode 100644 index 00000000..76b8fd7d --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/base/MGASoundfieldGroupLabelSubDescriptorBase.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2023, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MXFPP_MGASOUNDFIELDGROUPLABELSUBDESCRIPTOR_BASE_H_ +#define MXFPP_MGASOUNDFIELDGROUPLABELSUBDESCRIPTOR_BASE_H_ + + + +#include + + +namespace mxfpp +{ + + +class MGASoundfieldGroupLabelSubDescriptorBase : public SoundfieldGroupLabelSubDescriptor +{ +public: + friend class MetadataSetFactory; + static const mxfKey setKey; + +public: + MGASoundfieldGroupLabelSubDescriptorBase(HeaderMetadata *headerMetadata); + virtual ~MGASoundfieldGroupLabelSubDescriptorBase(); + + + // getters + + mxfUUID getMGAMetadataSectionLinkID() const; + bool haveADMAudioProgrammeID() const; + std::string getADMAudioProgrammeID() const; + bool haveADMAudioContentID() const; + std::string getADMAudioContentID() const; + bool haveADMAudioObjectID() const; + std::string getADMAudioObjectID() const; + + + // setters + + void setMGAMetadataSectionLinkID(mxfUUID value); + void setADMAudioProgrammeID(const std::string &value); + void setADMAudioContentID(const std::string &value); + void setADMAudioObjectID(const std::string &value); + + +protected: + MGASoundfieldGroupLabelSubDescriptorBase(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet); +}; + + +}; + + +#endif diff --git a/deps/libMXFpp/libMXF++/metadata/base/SADMAudioMetadataSubDescriptorBase.cpp b/deps/libMXFpp/libMXF++/metadata/base/SADMAudioMetadataSubDescriptorBase.cpp new file mode 100644 index 00000000..5f06e398 --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/base/SADMAudioMetadataSubDescriptorBase.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2023, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + + +using namespace std; +using namespace mxfpp; + + +const mxfKey SADMAudioMetadataSubDescriptorBase::setKey = MXF_SET_K(SADMAudioMetadataSubDescriptor); + + +SADMAudioMetadataSubDescriptorBase::SADMAudioMetadataSubDescriptorBase(HeaderMetadata *headerMetadata) +: SubDescriptor(headerMetadata, headerMetadata->createCSet(&setKey)) +{ + headerMetadata->add(this); +} + +SADMAudioMetadataSubDescriptorBase::SADMAudioMetadataSubDescriptorBase(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet) +: SubDescriptor(headerMetadata, cMetadataSet) +{} + +SADMAudioMetadataSubDescriptorBase::~SADMAudioMetadataSubDescriptorBase() +{} + + +mxfUUID SADMAudioMetadataSubDescriptorBase::getSADMMetadataSectionLinkID() const +{ + return getUUIDItem(&MXF_ITEM_K(SADMAudioMetadataSubDescriptor, SADMMetadataSectionLinkID)); +} + +bool SADMAudioMetadataSubDescriptorBase::haveSADMProfileLevelULBatch() const +{ + return haveItem(&MXF_ITEM_K(SADMAudioMetadataSubDescriptor, SADMProfileLevelULBatch)); +} + +vector SADMAudioMetadataSubDescriptorBase::getSADMProfileLevelULBatch() const +{ + return getULArrayItem(&MXF_ITEM_K(SADMAudioMetadataSubDescriptor, SADMProfileLevelULBatch)); +} + +void SADMAudioMetadataSubDescriptorBase::setSADMMetadataSectionLinkID(mxfUUID value) +{ + setUUIDItem(&MXF_ITEM_K(SADMAudioMetadataSubDescriptor, SADMMetadataSectionLinkID), value); +} + +void SADMAudioMetadataSubDescriptorBase::setSADMProfileLevelULBatch(const vector &value) +{ + setULArrayItem(&MXF_ITEM_K(SADMAudioMetadataSubDescriptor, SADMProfileLevelULBatch), value); +} + +void SADMAudioMetadataSubDescriptorBase::appendSADMProfileLevelULBatch(mxfUL value) +{ + appendULArrayItem(&MXF_ITEM_K(SADMAudioMetadataSubDescriptor, SADMProfileLevelULBatch), value); +} diff --git a/deps/libMXFpp/libMXF++/metadata/base/SADMAudioMetadataSubDescriptorBase.h b/deps/libMXFpp/libMXF++/metadata/base/SADMAudioMetadataSubDescriptorBase.h new file mode 100644 index 00000000..6016249b --- /dev/null +++ b/deps/libMXFpp/libMXF++/metadata/base/SADMAudioMetadataSubDescriptorBase.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2023, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MXFPP_SADMAUDIOMETADATASUBDESCRIPTOR_BASE_H_ +#define MXFPP_SADMAUDIOMETADATASUBDESCRIPTOR_BASE_H_ + + + +#include + + +namespace mxfpp +{ + + +class SADMAudioMetadataSubDescriptorBase : public SubDescriptor +{ +public: + friend class MetadataSetFactory; + static const mxfKey setKey; + +public: + SADMAudioMetadataSubDescriptorBase(HeaderMetadata *headerMetadata); + virtual ~SADMAudioMetadataSubDescriptorBase(); + + + // getters + + mxfUUID getSADMMetadataSectionLinkID() const; + bool haveSADMProfileLevelULBatch() const; + std::vector getSADMProfileLevelULBatch() const; + + + // setters + + void setSADMMetadataSectionLinkID(mxfUUID value); + void setSADMProfileLevelULBatch(const std::vector &value); + void appendSADMProfileLevelULBatch(mxfUL value); + + +protected: + SADMAudioMetadataSubDescriptorBase(HeaderMetadata *headerMetadata, ::MXFMetadataSet *cMetadataSet); +}; + + +}; + + +#endif From cc741e762dfcf4d135ab70669ae5307c9d25155e Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Wed, 22 Nov 2023 12:44:11 +0000 Subject: [PATCH 09/65] libmxfpp: cmake: add ADM files to source and header lists --- .../libMXFpp/libMXF++/metadata/CMakeLists.txt | 20 +++++++++++++++++++ .../libMXF++/metadata/base/CMakeLists.txt | 20 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/deps/libMXFpp/libMXF++/metadata/CMakeLists.txt b/deps/libMXFpp/libMXF++/metadata/CMakeLists.txt index 98281fb3..b33776cb 100644 --- a/deps/libMXFpp/libMXF++/metadata/CMakeLists.txt +++ b/deps/libMXFpp/libMXF++/metadata/CMakeLists.txt @@ -1,4 +1,8 @@ list(APPEND MXFpp_sources + metadata/ADM_CHNASubDescriptor.cpp + metadata/ADMAudioMetadataSubDescriptor.cpp + metadata/ADMChannelMapping.cpp + metadata/ADMSoundfieldGroupLabelSubDescriptor.cpp metadata/AES3AudioDescriptor.cpp metadata/ANCDataDescriptor.cpp metadata/AVCSubDescriptor.cpp @@ -28,12 +32,18 @@ list(APPEND MXFpp_sources metadata/JPEG2000SubDescriptor.cpp metadata/Locator.cpp metadata/MCALabelSubDescriptor.cpp + metadata/MGAAudioMetadataSubDescriptor.cpp + metadata/MGASoundEssenceDescriptor.cpp + metadata/MGASoundfieldGroupLabelSubDescriptor.cpp metadata/MPEGVideoDescriptor.cpp metadata/MaterialPackage.cpp metadata/MultipleDescriptor.cpp metadata/NetworkLocator.cpp metadata/Preface.cpp metadata/RGBAEssenceDescriptor.cpp + metadata/RIFFChunkDefinitionSubDescriptor.cpp + metadata/RIFFChunkReferencesSubDescriptor.cpp + metadata/SADMAudioMetadataSubDescriptor.cpp metadata/Sequence.cpp metadata/SoundfieldGroupLabelSubDescriptor.cpp metadata/SourceClip.cpp @@ -54,6 +64,10 @@ list(APPEND MXFpp_sources ) list(APPEND MXFpp_headers + metadata/ADM_CHNASubDescriptor.h + metadata/ADMAudioMetadataSubDescriptor.h + metadata/ADMChannelMapping.h + metadata/ADMSoundfieldGroupLabelSubDescriptor.h metadata/AES3AudioDescriptor.h metadata/ANCDataDescriptor.h metadata/AVCSubDescriptor.h @@ -83,6 +97,9 @@ list(APPEND MXFpp_headers metadata/JPEG2000SubDescriptor.h metadata/Locator.h metadata/MCALabelSubDescriptor.h + metadata/MGAAudioMetadataSubDescriptor.h + metadata/MGASoundEssenceDescriptor.h + metadata/MGASoundfieldGroupLabelSubDescriptor.h metadata/MPEGVideoDescriptor.h metadata/MaterialPackage.h metadata/Metadata.h @@ -90,6 +107,9 @@ list(APPEND MXFpp_headers metadata/NetworkLocator.h metadata/Preface.h metadata/RGBAEssenceDescriptor.h + metadata/RIFFChunkDefinitionSubDescriptor.h + metadata/RIFFChunkReferencesSubDescriptor.h + metadata/SADMAudioMetadataSubDescriptor.h metadata/Sequence.h metadata/SoundfieldGroupLabelSubDescriptor.h metadata/SourceClip.h diff --git a/deps/libMXFpp/libMXF++/metadata/base/CMakeLists.txt b/deps/libMXFpp/libMXF++/metadata/base/CMakeLists.txt index 18598dc1..8ec7b08c 100644 --- a/deps/libMXFpp/libMXF++/metadata/base/CMakeLists.txt +++ b/deps/libMXFpp/libMXF++/metadata/base/CMakeLists.txt @@ -1,4 +1,8 @@ list(APPEND MXFpp_sources + metadata/base/ADM_CHNASubDescriptorBase.cpp + metadata/base/ADMAudioMetadataSubDescriptorBase.cpp + metadata/base/ADMChannelMappingBase.cpp + metadata/base/ADMSoundfieldGroupLabelSubDescriptorBase.cpp metadata/base/AES3AudioDescriptorBase.cpp metadata/base/ANCDataDescriptorBase.cpp metadata/base/AVCSubDescriptorBase.cpp @@ -28,12 +32,18 @@ list(APPEND MXFpp_sources metadata/base/JPEG2000SubDescriptorBase.cpp metadata/base/LocatorBase.cpp metadata/base/MCALabelSubDescriptorBase.cpp + metadata/base/MGAAudioMetadataSubDescriptorBase.cpp + metadata/base/MGASoundEssenceDescriptorBase.cpp + metadata/base/MGASoundfieldGroupLabelSubDescriptorBase.cpp metadata/base/MPEGVideoDescriptorBase.cpp metadata/base/MaterialPackageBase.cpp metadata/base/MultipleDescriptorBase.cpp metadata/base/NetworkLocatorBase.cpp metadata/base/PrefaceBase.cpp metadata/base/RGBAEssenceDescriptorBase.cpp + metadata/base/RIFFChunkDefinitionSubDescriptorBase.cpp + metadata/base/RIFFChunkReferencesSubDescriptorBase.cpp + metadata/base/SADMAudioMetadataSubDescriptorBase.cpp metadata/base/SequenceBase.cpp metadata/base/SoundfieldGroupLabelSubDescriptorBase.cpp metadata/base/SourceClipBase.cpp @@ -54,6 +64,10 @@ list(APPEND MXFpp_sources ) list(APPEND MXFpp_headers + metadata/base/ADM_CHNASubDescriptorBase.h + metadata/base/ADMAudioMetadataSubDescriptorBase.h + metadata/base/ADMChannelMappingBase.h + metadata/base/ADMSoundfieldGroupLabelSubDescriptorBase.h metadata/base/AES3AudioDescriptorBase.h metadata/base/ANCDataDescriptorBase.h metadata/base/AVCSubDescriptorBase.h @@ -83,12 +97,18 @@ list(APPEND MXFpp_headers metadata/base/JPEG2000SubDescriptorBase.h metadata/base/LocatorBase.h metadata/base/MCALabelSubDescriptorBase.h + metadata/base/MGAAudioMetadataSubDescriptorBase.h + metadata/base/MGASoundEssenceDescriptorBase.h + metadata/base/MGASoundfieldGroupLabelSubDescriptorBase.h metadata/base/MPEGVideoDescriptorBase.h metadata/base/MaterialPackageBase.h metadata/base/MultipleDescriptorBase.h metadata/base/NetworkLocatorBase.h metadata/base/PrefaceBase.h metadata/base/RGBAEssenceDescriptorBase.h + metadata/base/RIFFChunkDefinitionSubDescriptorBase.h + metadata/base/RIFFChunkReferencesSubDescriptorBase.h + metadata/base/SADMAudioMetadataSubDescriptorBase.h metadata/base/SequenceBase.h metadata/base/SoundfieldGroupLabelSubDescriptorBase.h metadata/base/SourceClipBase.h From d09e193f5eaea5951e6f73c23041accef326a198 Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Wed, 22 Nov 2023 09:52:34 +0000 Subject: [PATCH 10/65] Add ADM definitions to mxflib extensions dictionary --- meta/extensions_mxflib_dict.xml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/meta/extensions_mxflib_dict.xml b/meta/extensions_mxflib_dict.xml index 34263358..7bd26458 100644 --- a/meta/extensions_mxflib_dict.xml +++ b/meta/extensions_mxflib_dict.xml @@ -16,6 +16,7 @@ + @@ -148,6 +149,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + From 935d612b057fea458af81883d316677a24963338 Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Thu, 19 Jan 2023 09:09:00 +0000 Subject: [PATCH 11/65] Add GenericStreamReader class --- include/bmx/BMXIO.h | 69 ++++ include/bmx/mxf_reader/GenericStreamReader.h | 91 ++++++ include/bmx/mxf_reader/MXFTextObject.h | 2 + src/common/BMXIO.cpp | 173 ++++++++++ src/mxf_reader/GenericStreamReader.cpp | 318 +++++++++++++++++++ src/mxf_reader/MXFTextObject.cpp | 143 +-------- src/mxf_reader/MXFTimedTextTrackReader.cpp | 127 +------- 7 files changed, 681 insertions(+), 242 deletions(-) create mode 100644 include/bmx/BMXIO.h create mode 100644 include/bmx/mxf_reader/GenericStreamReader.h create mode 100644 src/common/BMXIO.cpp create mode 100644 src/mxf_reader/GenericStreamReader.cpp diff --git a/include/bmx/BMXIO.h b/include/bmx/BMXIO.h new file mode 100644 index 00000000..9099b2c5 --- /dev/null +++ b/include/bmx/BMXIO.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BMX_IO_H_ +#define BMX_IO_H_ + +#include + +#include + + +namespace bmx +{ + + +class BMXIO +{ +public: + BMXIO(); + virtual ~BMXIO(); + + virtual uint32_t Read(unsigned char *data, uint32_t size); + virtual void Read(FILE *file); + virtual void Read(BMXIO *bmx_io); + + virtual uint32_t Write(const unsigned char *data, uint32_t size); + virtual void Write(FILE *file); + virtual void Write(BMXIO *bmx_io); + + virtual bool Seek(int64_t offset, int whence); + + virtual int64_t Tell(); + virtual int64_t Size(); +}; + + +}; + + + +#endif diff --git a/include/bmx/mxf_reader/GenericStreamReader.h b/include/bmx/mxf_reader/GenericStreamReader.h new file mode 100644 index 00000000..91c8ec5d --- /dev/null +++ b/include/bmx/mxf_reader/GenericStreamReader.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BMX_GENERIC_STREAM_READER_H_ +#define BMX_GENERIC_STREAM_READER_H_ + +#include +#include + + +namespace bmx +{ + + +class GenericStreamReader : public BMXIO +{ +public: + GenericStreamReader(mxfpp::File *mxf_file, uint32_t stream_id, const std::vector &expected_stream_keys); + virtual ~GenericStreamReader(); + +public: + // From BMXIO + virtual uint32_t Read(unsigned char *data, uint32_t size); + virtual int64_t Tell(); + virtual int64_t Size(); + + virtual void Read(FILE *file); + virtual void Read(BMXIO *bmx_io); + +public: + void Read(unsigned char **data, size_t *size); + + const std::vector >& GetFileOffsetRanges(); + +public: + uint32_t GetStreamId() const { return mStreamId; } + + const mxfKey* GetStreamKey() const { return &mStreamKey; } + +private: + bool MatchesExpectedStreamKey(const mxfKey *key); + void Read(FILE *file, BMXIO *bmx_io, unsigned char **data, size_t *size); + +private: + mxfpp::File *mMXFFile; + uint32_t mStreamId; + std::vector mExpectedStreamKeys; + mxfKey mStreamKey; + + bool mHaveFileOffsetRanges; + std::vector > mFileOffsetRanges; + int64_t mSize; + int64_t mPosition; + size_t mRangeIndex; + int64_t mRangeOffset; +}; + + +}; + + + +#endif diff --git a/include/bmx/mxf_reader/MXFTextObject.h b/include/bmx/mxf_reader/MXFTextObject.h index 0b969113..eac63227 100644 --- a/include/bmx/mxf_reader/MXFTextObject.h +++ b/include/bmx/mxf_reader/MXFTextObject.h @@ -33,6 +33,7 @@ #define BMX_MXF_TEXT_OBJECT_H_ #include +#include #include @@ -87,6 +88,7 @@ class MXFTextObject uint16_t mComponentIndex; bool mIsXML; ByteOrder mGSByteOrder; + std::vector mExpectedStreamKeys; }; diff --git a/src/common/BMXIO.cpp b/src/common/BMXIO.cpp new file mode 100644 index 00000000..de00d4aa --- /dev/null +++ b/src/common/BMXIO.cpp @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include +#include +#include +#include + +using namespace std; +using namespace bmx; + + + +BMXIO::BMXIO() +{ +} + +BMXIO::~BMXIO() +{ +} + +uint32_t BMXIO::Read(unsigned char *data, uint32_t size) +{ + (void)data; + (void)size; + BMX_ASSERT(false); + return 0; +} + +void BMXIO::Read(FILE *file) +{ + ByteArray buffer; + buffer.Allocate(8192); + + while (true) { + uint32_t num_read = Read(buffer.GetBytesAvailable(), buffer.GetAllocatedSize()); + + if (num_read > 0) { + size_t num_write = fwrite(buffer.GetBytesAvailable(), 1, num_read, file); + if (num_write != num_read) { + BMX_EXCEPTION(("Failed to write to output file: %s", + bmx_strerror(errno).c_str())); + } + } + + if (num_read < buffer.GetAllocatedSize()) + break; + } +} + +void BMXIO::Read(BMXIO *bmx_io) +{ + ByteArray buffer; + buffer.Allocate(8192); + + while (true) { + uint32_t num_read = Read(buffer.GetBytesAvailable(), buffer.GetAllocatedSize()); + + if (num_read > 0) { + uint32_t num_write = bmx_io->Write(buffer.GetBytesAvailable(), num_read); + if (num_write != num_read) + BMX_EXCEPTION(("Failed to write to output file")); + } + + if (num_read < buffer.GetAllocatedSize()) + break; + } +} + +uint32_t BMXIO::Write(const unsigned char *data, uint32_t size) +{ + (void)data; + (void)size; + BMX_ASSERT(false); + return 0; +} + +void BMXIO::Write(FILE *file) +{ + ByteArray buffer; + buffer.Allocate(8192); + + while (true) { + size_t num_read = fread(buffer.GetBytesAvailable(), 1, buffer.GetAllocatedSize(), file); + if (ferror(file)) { + BMX_EXCEPTION(("Failed to read from input file: %s", + bmx_strerror(errno).c_str())); + } + + if (num_read > 0) { + uint32_t num_write = Write(buffer.GetBytesAvailable(), num_read); + if (num_write != num_read) + BMX_EXCEPTION(("Failed to write to output file")); + } + + if (num_read < buffer.GetAllocatedSize()) + break; + } +} + +void BMXIO::Write(BMXIO *bmx_io) +{ + ByteArray buffer; + buffer.Allocate(8192); + + while (true) { + uint32_t num_read = bmx_io->Read(buffer.GetBytesAvailable(), buffer.GetAllocatedSize()); + + if (num_read > 0) { + uint32_t num_write = Write(buffer.GetBytesAvailable(), num_read); + if (num_write != num_read) + BMX_EXCEPTION(("Failed to write to output file")); + } + + if (num_read < buffer.GetAllocatedSize()) + break; + } +} + +bool BMXIO::Seek(int64_t offset, int whence) +{ + (void)offset; + (void)whence; + BMX_ASSERT(false); + return 0; +} + +int64_t BMXIO::Tell() +{ + BMX_ASSERT(false); + return 0; +} + +int64_t BMXIO::Size() +{ + BMX_ASSERT(false); + return 0; +} diff --git a/src/mxf_reader/GenericStreamReader.cpp b/src/mxf_reader/GenericStreamReader.cpp new file mode 100644 index 00000000..0332f201 --- /dev/null +++ b/src/mxf_reader/GenericStreamReader.cpp @@ -0,0 +1,318 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define __STDC_LIMIT_MACROS +#define __STDC_FORMAT_MACROS + +#include +#include + +#include + +#include +#include +#include +#include +#include + +using namespace std; +using namespace bmx; +using namespace mxfpp; + + +GenericStreamReader::GenericStreamReader(mxfpp::File *mxf_file, uint32_t stream_id, const vector &expected_stream_keys) +: BMXIO() +{ + mMXFFile = mxf_file; + mStreamId = stream_id; + mExpectedStreamKeys = expected_stream_keys; + mHaveFileOffsetRanges = false; + mSize = 0; + mPosition = 0; + mRangeIndex = 0; + mRangeOffset = 0; +} + +GenericStreamReader::~GenericStreamReader() +{ +} + +uint32_t GenericStreamReader::Read(unsigned char *data, uint32_t size) +{ + if (!mHaveFileOffsetRanges) + GetFileOffsetRanges(); + + if (mPosition >= mSize) + return 0; + + int64_t read_size = mSize - mPosition; + if (read_size > (int64_t)size) + read_size = size; + + int64_t read_remainder = read_size; + while (read_remainder > 0) { + const pair &range = mFileOffsetRanges[mRangeIndex]; + + int64_t range_remainder = range.second - mRangeOffset; + if (range_remainder > 0) { + uint32_t to_read = (uint32_t)read_remainder; + if ((int64_t)to_read > range_remainder) + to_read = (uint32_t)range_remainder; + + if (mRangeOffset == 0) + mMXFFile->seek(range.first, SEEK_SET); + + uint32_t have_read = mMXFFile->read(&data[read_size - read_remainder], to_read); + + mPosition += have_read; + mRangeOffset += have_read; + read_remainder -= have_read; + + if (have_read < to_read) + break; + } + + if (mRangeOffset >= range.second) { + mRangeOffset = 0; + mRangeIndex += 1; + } + } + + return read_size - read_remainder; +} + +int64_t GenericStreamReader::Tell() +{ + return mPosition; +} + +int64_t GenericStreamReader::Size() +{ + if (!mHaveFileOffsetRanges) + GetFileOffsetRanges(); + + return mSize; +} + +void GenericStreamReader::Read(FILE *file) +{ + if (mHaveFileOffsetRanges) { + mPosition = 0; + mRangeIndex = 0; + mRangeOffset = 0; + + BMXIO::Read(file); + } else { + Read(file, 0, 0, 0); + } +} + +void GenericStreamReader::Read(BMXIO *bmx_io) +{ + if (mHaveFileOffsetRanges) { + mPosition = 0; + mRangeIndex = 0; + mRangeOffset = 0; + + BMXIO::Read(bmx_io); + } else { + Read(0, bmx_io, 0, 0); + } +} + +void GenericStreamReader::Read(unsigned char **data, size_t *size) +{ + Read(0, 0, data, size); +} + +const std::vector >& GenericStreamReader::GetFileOffsetRanges() +{ + if (!mHaveFileOffsetRanges) { + Read(0, 0, 0, 0); + + mSize = 0; + size_t i; + for (i = 0; i < mFileOffsetRanges.size(); i++) + mSize += mFileOffsetRanges[i].second; + + mHaveFileOffsetRanges = true; + } + + return mFileOffsetRanges; +} + +bool GenericStreamReader::MatchesExpectedStreamKey(const mxfKey *key) +{ + if (mExpectedStreamKeys.empty()) + return mxf_is_gs_data_element(key); + + size_t i; + for (i = 0; i < mExpectedStreamKeys.size(); i++) { + if (mxf_equals_key_mod_regver(key, &mExpectedStreamKeys[i])) + return true; + } + + return false; +} + +void GenericStreamReader::Read(FILE *file, BMXIO *bmx_io, unsigned char **data, size_t *size) +{ + mStreamKey = g_Null_Key; + mFileOffsetRanges.clear(); + + int64_t original_file_pos = mMXFFile->tell(); + try + { + uint64_t body_size = 0; + bmx::ByteArray buffer; + mxfKey key; + uint8_t llen; + uint64_t len; + const vector &partitions = mMXFFile->getPartitions(); + size_t i; + for (i = 0; i < partitions.size(); i++) { + if (partitions[i]->getBodySID() != mStreamId) + continue; + + if (partitions[i]->getBodyOffset() > body_size) { + log_warn("Ignoring potential missing stream data; " + "partition pack's BodyOffset 0x%" PRIx64 " > expected offset 0x" PRIx64 "\n", + partitions[i]->getBodyOffset(), body_size); + continue; + } else if (partitions[i]->getBodyOffset() < body_size) { + log_warn("Ignoring overlapping or repeated stream data; " + "partition pack's BodyOffset 0x%" PRIx64 " < expected offset 0x" PRIx64 "\n", + partitions[i]->getBodyOffset(), body_size); + continue; + } + + mMXFFile->seek(partitions[i]->getThisPartition(), SEEK_SET); + mMXFFile->readKL(&key, &llen, &len); + mMXFFile->skip(len); + + bool have_stream_key = false; + while (!mMXFFile->eof()) + { + mMXFFile->readNextNonFillerKL(&key, &llen, &len); + + if (mxf_is_partition_pack(&key)) { + break; + } else if (mxf_is_header_metadata(&key)) { + if (partitions[i]->getHeaderByteCount() > mxfKey_extlen + llen + len) + mMXFFile->skip(partitions[i]->getHeaderByteCount() - (mxfKey_extlen + llen)); + else + mMXFFile->skip(len); + } else if (mxf_is_index_table_segment(&key)) { + if (partitions[i]->getIndexByteCount() > mxfKey_extlen + llen + len) + mMXFFile->skip(partitions[i]->getIndexByteCount() - (mxfKey_extlen + llen)); + else + mMXFFile->skip(len); + } else if (MatchesExpectedStreamKey(&key)) { + if (body_size == 0) + mStreamKey = key; + else if (mStreamKey != key) + mStreamKey = g_Null_Key; // stream key is not fixed + + if (data) { + if (len > UINT32_MAX || (uint64_t)buffer.GetAllocatedSize() + len > UINT32_MAX) + BMX_EXCEPTION(("Stream data size exceeds maximum supported in-memory size")); + buffer.Grow((uint32_t)len); + } else if (file || bmx_io) { + buffer.Allocate(8192); + } + + if (data || file || bmx_io) { + uint64_t rem_len = len; + while (rem_len > 0) { + uint32_t count = 8192; + if (count > rem_len) + count = (uint32_t)rem_len; + uint32_t num_read = mMXFFile->read(buffer.GetBytesAvailable(), count); + if (num_read != count) + BMX_EXCEPTION(("Failed to read data from generic stream")); + + if (file) { + size_t num_write = fwrite(buffer.GetBytesAvailable(), 1, num_read, file); + if (num_write != num_read) { + BMX_EXCEPTION(("Failed to write generic stream data to file: %s", + bmx_strerror(errno).c_str())); + } + } else if (bmx_io) { + uint32_t num_write = bmx_io->Write(buffer.GetBytesAvailable(), num_read); + if (num_write != num_read) { + BMX_EXCEPTION(("Failed to write generic stream data to BMX IO")); + } + } else if (data) { + buffer.IncrementSize(num_read); + } + + rem_len -= num_read; + } + } else { + if (len > 0) { + mFileOffsetRanges.push_back(make_pair(mMXFFile->tell(), len)); + mMXFFile->skip(len); + } + } + + have_stream_key = true; + body_size += mxfKey_extlen + llen + len; + } else { + mMXFFile->skip(len); + if (have_stream_key) + body_size += mxfKey_extlen + llen + len; + } + } + } + + if (data) { + if (buffer.GetSize() > 0) { + *data = buffer.GetBytes(); + *size = buffer.GetSize(); + buffer.TakeBytes(); + } else { + *data = 0; + *size = 0; + } + } + + mMXFFile->seek(original_file_pos, SEEK_SET); + } + catch (...) + { + mMXFFile->seek(original_file_pos, SEEK_SET); + throw; + } +} diff --git a/src/mxf_reader/MXFTextObject.cpp b/src/mxf_reader/MXFTextObject.cpp index 7cf3d10e..8a09384b 100644 --- a/src/mxf_reader/MXFTextObject.cpp +++ b/src/mxf_reader/MXFTextObject.cpp @@ -33,17 +33,14 @@ #include "config.h" #endif -#define __STDC_LIMIT_MACROS -#define __STDC_FORMAT_MACROS - #include #include -#include #include #include #include +#include #include #include #include @@ -63,6 +60,10 @@ MXFTextObject::MXFTextObject(MXFFileReader *file_reader, TextBasedObject *text_o mComponentIndex = component_index; mIsXML = CheckIsXML(); mGSByteOrder = UNKNOWN_BYTE_ORDER; + + mExpectedStreamKeys.push_back(MXF_EE_K(RP2057_LE)); + mExpectedStreamKeys.push_back(MXF_EE_K(RP2057_BE)); // == MXF_EE_K(RP2057_BYTES) + mExpectedStreamKeys.push_back(MXF_EE_K(RP2057_ENDIAN_UNK)); } MXFTextObject::~MXFTextObject() @@ -198,128 +199,18 @@ bool MXFTextObject::CheckIsXML() void MXFTextObject::ReadGenericStream(FILE *text_file_out, unsigned char **data_out, size_t *data_out_size) { - mxfpp::File *mxf_file = mFileReader->mFile; - int64_t original_file_pos = mxf_file->tell(); - try - { - GenericStreamTextBasedSet *gs_text = dynamic_cast(mTextObject); - - uint64_t body_size = 0; - ByteArray buffer; - mxfKey key; - uint8_t llen; - uint64_t len; - const vector &partitions = mFileReader->mFile->getPartitions(); - size_t i; - for (i = 0; i < partitions.size(); i++) { - if (partitions[i]->getBodySID() != gs_text->getGenericStreamSID()) - continue; - - if (partitions[i]->getBodyOffset() > body_size) { - log_warn("Ignoring potential missing text object generic stream data; " - "partition pack's BodyOffset 0x%" PRIx64 " > expected offset 0x" PRIx64 "\n", - partitions[i]->getBodyOffset(), body_size); - continue; - } else if (partitions[i]->getBodyOffset() < body_size) { - log_warn("Ignoring overlapping or repeated text object generic stream data; " - "partition pack's BodyOffset 0x%" PRIx64 " < expected offset 0x" PRIx64 "\n", - partitions[i]->getBodyOffset(), body_size); - continue; - } - - mxf_file->seek(partitions[i]->getThisPartition(), SEEK_SET); - mxf_file->readKL(&key, &llen, &len); - mxf_file->skip(len); - - bool have_gs_key = false; - while (!mxf_file->eof()) - { - mxf_file->readNextNonFillerKL(&key, &llen, &len); - - if (mxf_is_partition_pack(&key)) { - break; - } else if (mxf_is_header_metadata(&key)) { - if (partitions[i]->getHeaderByteCount() > mxfKey_extlen + llen + len) - mxf_file->skip(partitions[i]->getHeaderByteCount() - (mxfKey_extlen + llen)); - else - mxf_file->skip(len); - } else if (mxf_is_index_table_segment(&key)) { - if (partitions[i]->getIndexByteCount() > mxfKey_extlen + llen + len) - mxf_file->skip(partitions[i]->getIndexByteCount() - (mxfKey_extlen + llen)); - else - mxf_file->skip(len); - } else if (mxf_is_gs_data_element(&key)) { - if (key != MXF_EE_K(RP2057_LE) && - key != MXF_EE_K(RP2057_BE) && // == MXF_EE_K(RP2057_BYTES) - key != MXF_EE_K(RP2057_ENDIAN_UNK)) - { - BMX_EXCEPTION(("Generic stream essence element key is not a RP 2057 key")); - } - if (body_size == 0 || mGSByteOrder != UNKNOWN_BYTE_ORDER) { - ByteOrder byte_order = UNKNOWN_BYTE_ORDER; - if (key == MXF_EE_K(RP2057_LE)) - byte_order = BMX_LITTLE_ENDIAN; - else if (key == MXF_EE_K(RP2057_BE)) // == MXF_EE_K(RP2057_BYTES) - byte_order = BMX_BIG_ENDIAN; - if (body_size == 0) - mGSByteOrder = byte_order; - else if (mGSByteOrder != byte_order) - mGSByteOrder = UNKNOWN_BYTE_ORDER; - } - - if (data_out) { - if (len > UINT32_MAX || (uint64_t)buffer.GetAllocatedSize() + len > UINT32_MAX) - BMX_EXCEPTION(("Text object in generic stream exceeds maximum supported in-memory size")); - buffer.Grow((uint32_t)len); - } else { - buffer.Allocate(8192); - } - uint64_t rem_len = len; - while (rem_len > 0) { - uint32_t count = 8192; - if (count > rem_len) - count = (uint32_t)rem_len; - uint32_t num_read = mxf_file->read(buffer.GetBytesAvailable(), count); - if (num_read != count) - BMX_EXCEPTION(("Failed to read text object data from generic stream")); - if (text_file_out) { - size_t num_write = fwrite(buffer.GetBytesAvailable(), 1, num_read, text_file_out); - if (num_write != num_read) { - BMX_EXCEPTION(("Failed to write text object to file: %s", - bmx_strerror(errno).c_str())); - } - } else { - buffer.IncrementSize(num_read); - } - rem_len -= num_read; - } - - have_gs_key = true; - body_size += mxfKey_extlen + llen + len; - } else { - mxf_file->skip(len); - if (have_gs_key) - body_size += mxfKey_extlen + llen + len; - } - } - } + GenericStreamTextBasedSet *gs_text = dynamic_cast(mTextObject); - if (data_out) { - if (buffer.GetSize() > 0) { - *data_out = buffer.GetBytes(); - *data_out_size = buffer.GetSize(); - buffer.TakeBytes(); - } else { - *data_out = 0; - *data_out_size = 0; - } - } + GenericStreamReader stream_reader(mFileReader->mFile, gs_text->getGenericStreamSID(), mExpectedStreamKeys); + if (text_file_out) + stream_reader.Read(text_file_out); + else + stream_reader.Read(data_out, data_out_size); - mxf_file->seek(original_file_pos, SEEK_SET); - } - catch (...) - { - mxf_file->seek(original_file_pos, SEEK_SET); - throw; - } + if (*stream_reader.GetStreamKey() == MXF_EE_K(RP2057_LE)) + mGSByteOrder = BMX_LITTLE_ENDIAN; + else if (*stream_reader.GetStreamKey() == MXF_EE_K(RP2057_BE)) + mGSByteOrder = BMX_BIG_ENDIAN; + else + mGSByteOrder = UNKNOWN_BYTE_ORDER; } diff --git a/src/mxf_reader/MXFTimedTextTrackReader.cpp b/src/mxf_reader/MXFTimedTextTrackReader.cpp index a6823904..efcc5a58 100644 --- a/src/mxf_reader/MXFTimedTextTrackReader.cpp +++ b/src/mxf_reader/MXFTimedTextTrackReader.cpp @@ -31,16 +31,12 @@ #include "config.h" #endif -#define __STDC_LIMIT_MACROS -#define __STDC_FORMAT_MACROS - #include #include -#include -#include #include +#include #include #include #include @@ -178,115 +174,14 @@ void MXFTimedTextTrackReader::ReadStream(uint32_t stream_id, const mxfKey *strea unsigned char **data_out, size_t *data_out_size, std::vector > *ranges_out) { - mxfpp::File *mxf_file = GetFileReader()->mFile; - int64_t original_file_pos = mxf_file->tell(); - try - { - uint64_t body_size = 0; - ByteArray buffer; - mxfKey key; - uint8_t llen; - uint64_t len; - const vector &partitions = mxf_file->getPartitions(); - size_t i; - for (i = 0; i < partitions.size(); i++) { - if (partitions[i]->getBodySID() != stream_id) - continue; - - if (partitions[i]->getBodyOffset() > body_size) { - log_warn("Ignoring potential missing stream data; " - "partition pack's BodyOffset 0x%" PRIx64 " > expected offset 0x" PRIx64 "\n", - partitions[i]->getBodyOffset(), body_size); - continue; - } else if (partitions[i]->getBodyOffset() < body_size) { - log_warn("Ignoring overlapping or repeated stream data; " - "partition pack's BodyOffset 0x%" PRIx64 " < expected offset 0x" PRIx64 "\n", - partitions[i]->getBodyOffset(), body_size); - continue; - } - - mxf_file->seek(partitions[i]->getThisPartition(), SEEK_SET); - mxf_file->readKL(&key, &llen, &len); - mxf_file->skip(len); - - bool have_stream_key = false; - while (!mxf_file->eof()) - { - mxf_file->readNextNonFillerKL(&key, &llen, &len); - - if (mxf_is_partition_pack(&key)) { - break; - } else if (mxf_is_header_metadata(&key)) { - if (partitions[i]->getHeaderByteCount() > mxfKey_extlen + llen + len) - mxf_file->skip(partitions[i]->getHeaderByteCount() - (mxfKey_extlen + llen)); - else - mxf_file->skip(len); - } else if (mxf_is_index_table_segment(&key)) { - if (partitions[i]->getIndexByteCount() > mxfKey_extlen + llen + len) - mxf_file->skip(partitions[i]->getIndexByteCount() - (mxfKey_extlen + llen)); - else - mxf_file->skip(len); - } else if (mxf_equals_key_mod_regver(&key, stream_key)) { - if (data_out) { - if (len > UINT32_MAX || (uint64_t)buffer.GetAllocatedSize() + len > UINT32_MAX) - BMX_EXCEPTION(("Stream data size exceeds maximum supported in-memory size")); - buffer.Grow((uint32_t)len); - } else if (file_out) { - buffer.Allocate(8192); - } - if (data_out || file_out) { - uint64_t rem_len = len; - while (rem_len > 0) { - uint32_t count = 8192; - if (count > rem_len) - count = (uint32_t)rem_len; - uint32_t num_read = mxf_file->read(buffer.GetBytesAvailable(), count); - if (num_read != count) - BMX_EXCEPTION(("Failed to read text object data from generic stream")); - if (file_out) { - size_t num_write = fwrite(buffer.GetBytesAvailable(), 1, num_read, file_out); - if (num_write != num_read) { - BMX_EXCEPTION(("Failed to write text object to file: %s", - bmx_strerror(errno).c_str())); - } - } else if (data_out) { - buffer.IncrementSize(num_read); - } - rem_len -= num_read; - } - } else { - if (len > 0) { - ranges_out->push_back(make_pair(mxf_file->tell(), len)); - mxf_file->skip(len); - } - } - - have_stream_key = true; - body_size += mxfKey_extlen + llen + len; - } else { - mxf_file->skip(len); - if (have_stream_key) - body_size += mxfKey_extlen + llen + len; - } - } - } - - if (data_out) { - if (buffer.GetSize() > 0) { - *data_out = buffer.GetBytes(); - *data_out_size = buffer.GetSize(); - buffer.TakeBytes(); - } else { - *data_out = 0; - *data_out_size = 0; - } - } - - mxf_file->seek(original_file_pos, SEEK_SET); - } - catch (...) - { - mxf_file->seek(original_file_pos, SEEK_SET); - throw; - } + vector expected_stream_keys; + expected_stream_keys.push_back(*stream_key); + + GenericStreamReader stream_reader(GetFileReader()->mFile, stream_id, expected_stream_keys); + if (file_out) + stream_reader.Read(file_out); + else if (data_out && data_out_size) + stream_reader.Read(data_out, data_out_size); + else if (ranges_out) + *ranges_out = stream_reader.GetFileOffsetRanges(); } From 5862a41dc1d96033b4df4e1f176d1659b748de3e Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Thu, 19 Jan 2023 09:11:30 +0000 Subject: [PATCH 12/65] Add initial support for Wave ADM Support Wave -> MXF in raw2bmx Support MXF -> Wave in bmxtranswrap --- apps/bmxtranswrap/bmxtranswrap.cpp | 69 +++++++ apps/raw2bmx/raw2bmx.cpp | 116 ++++++++++++ apps/writers/OutputTrack.h | 16 +- include/bmx/BMXMXFIO.h | 67 +++++++ include/bmx/clip_writer/ClipWriter.h | 2 + include/bmx/clip_writer/ClipWriterTrack.h | 4 + .../mxf_helper/ADMCHNAMXFDescriptorHelper.h | 48 +++++ include/bmx/mxf_op1a/OP1AFile.h | 9 + include/bmx/mxf_op1a/OP1APCMTrack.h | 6 + include/bmx/mxf_reader/MXFFileTrackReader.h | 13 ++ include/bmx/mxf_reader/MXFTrackReader.h | 12 ++ include/bmx/mxf_reader/MXFWaveChunk.h | 70 +++++++ include/bmx/wave/WaveBEXT.h | 1 + include/bmx/wave/WaveCHNA.h | 90 +++++++++ include/bmx/wave/WaveChunk.h | 90 +++++++++ include/bmx/wave/WaveFileChunk.h | 64 +++++++ include/bmx/wave/WaveIO.h | 17 +- include/bmx/wave/WaveReader.h | 16 +- include/bmx/wave/WaveTrackWriter.h | 1 + include/bmx/wave/WaveWriter.h | 16 +- src/clip_writer/ClipWriter.cpp | 23 +++ src/clip_writer/ClipWriterTrack.cpp | 46 +++++ src/common/BMXMXFIO.cpp | 87 +++++++++ src/mxf_helper/ADMCHNAMXFDescriptorHelper.cpp | 106 +++++++++++ src/mxf_op1a/OP1AFile.cpp | 54 +++++- src/mxf_op1a/OP1APCMTrack.cpp | 41 +++++ src/mxf_reader/MXFFileTrackReader.cpp | 86 +++++++++ src/mxf_reader/MXFTrackReader.cpp | 75 ++++++++ src/mxf_reader/MXFWaveChunk.cpp | 78 ++++++++ src/wave/WaveBEXT.cpp | 4 + src/wave/WaveCHNA.cpp | 151 +++++++++++++++ src/wave/WaveChunk.cpp | 87 +++++++++ src/wave/WaveFileChunk.cpp | 73 ++++++++ src/wave/WaveIO.cpp | 19 +- src/wave/WaveReader.cpp | 89 +++++---- src/wave/WaveTrackWriter.cpp | 2 +- src/wave/WaveWriter.cpp | 172 ++++++++++++++---- 37 files changed, 1829 insertions(+), 91 deletions(-) create mode 100644 include/bmx/BMXMXFIO.h create mode 100644 include/bmx/mxf_helper/ADMCHNAMXFDescriptorHelper.h create mode 100644 include/bmx/mxf_reader/MXFWaveChunk.h create mode 100644 include/bmx/wave/WaveCHNA.h create mode 100644 include/bmx/wave/WaveChunk.h create mode 100644 include/bmx/wave/WaveFileChunk.h create mode 100644 src/common/BMXMXFIO.cpp create mode 100644 src/mxf_helper/ADMCHNAMXFDescriptorHelper.cpp create mode 100644 src/mxf_reader/MXFTrackReader.cpp create mode 100644 src/mxf_reader/MXFWaveChunk.cpp create mode 100644 src/wave/WaveCHNA.cpp create mode 100644 src/wave/WaveChunk.cpp create mode 100644 src/wave/WaveFileChunk.cpp diff --git a/apps/bmxtranswrap/bmxtranswrap.cpp b/apps/bmxtranswrap/bmxtranswrap.cpp index 23984166..79f21e03 100644 --- a/apps/bmxtranswrap/bmxtranswrap.cpp +++ b/apps/bmxtranswrap/bmxtranswrap.cpp @@ -4384,6 +4384,75 @@ int main(int argc, const char** argv) } + // Add ADM Wave chunks and references + + if (clip_type == CW_WAVE_CLIP_TYPE) { + WaveWriter *wave_clip = clip->GetWaveClip(); + + // Ensure that the start channels are up-to-date for each track + wave_clip->UpdateChannelCounts(); + + // Use the generic stream identifier to ensure chunks are included only once + set unique_stream_ids; + + // Loop over the Wave output tracks and add referenced chunks to the Wave file. + // Construct the output chna chunk based on the track mapping + WaveCHNA *output_chna = 0; + size_t i; + for (i = 0; i < output_tracks.size(); i++) { + OutputTrack *output_track = output_tracks[i]; + + WaveTrackWriter *wave_track = output_track->GetClipTrack()->GetWaveTrack(); + + // Loop over the output track channels, each mapped from an input track channel + const map &input_maps = output_track->GetInputMaps(); + map::const_iterator iter; + for (iter = input_maps.begin(); iter != input_maps.end(); iter++) { + uint32_t output_channel_index = iter->first; + uint32_t input_channel_index = iter->second.input_channel_index; + + InputTrack *input_track = iter->second.input_track; + const MXFTrackReader *input_track_reader = dynamic_cast(input_track)->GetTrackReader(); + + // Only continue if the input track channel has a chna audio ID + vector audio_ids = input_track_reader->GetCHNAAudioIDs(input_channel_index); + if (audio_ids.empty()) + continue; + + // Add all ADM chunks if not already present + size_t k; + for (k = 0; k < input_track_reader->GetNumWaveChunks(); k++) { + MXFWaveChunk *wave_chunk = input_track_reader->GetWaveChunk(k); + + if (!unique_stream_ids.count(wave_chunk->GetStreamId()) && + (wave_chunk->Tag() == WAVE_CHUNK_TAG("axml") || + wave_chunk->Tag() == WAVE_CHUNK_TAG("bxml") || + wave_chunk->Tag() == WAVE_CHUNK_TAG("sxml"))) + { + wave_clip->AddChunk(wave_chunk, false); + unique_stream_ids.insert(wave_chunk->GetStreamId()); + } + } + + // Change the input channel track_index to the output channel track_index and add to the chna + for (k = 0; k < audio_ids.size(); k++) { + WaveCHNA::AudioID &audio_id = audio_ids[k]; + + if (!output_chna) + output_chna = new WaveCHNA(); + + // + 1 because the chna track_index starts at 1 + audio_id.track_index = wave_track->GetStartChannel() + output_channel_index + 1; + output_chna->AppendAudioID(audio_id); + } + } + } + + if (output_chna) + wave_clip->AddCHNA(output_chna, true); + } + + // prepare the clip's header metadata and update file descriptors from input where supported clip->PrepareHeaderMetadata(); diff --git a/apps/raw2bmx/raw2bmx.cpp b/apps/raw2bmx/raw2bmx.cpp index 827de724..461a4fd4 100644 --- a/apps/raw2bmx/raw2bmx.cpp +++ b/apps/raw2bmx/raw2bmx.cpp @@ -5729,6 +5729,122 @@ int main(int argc, const char** argv) } + // Add ADM Wave chunks and references + + if (clip_type == CW_OP1A_CLIP_TYPE) { + // Get the output tracks and referenced Wave file inputs that contain ADM chunks + // Only allow a single Wave with ADM for each output track to ensure that references between + // the ADM chunks and channels remain unambiguous + vector > output_tracks_using_adm; + set wave_adm_inputs; + bool done = false; + for (i = 0; i < output_tracks.size() && !done; i++) { + OutputTrack *output_track = output_tracks[i]; + if (!output_track->HaveInputTrack()) + continue; + + // Loop over the input track channels and add input if the channel has a chna audio ID + // and there exist ADM chunks + RawInput *output_track_wave_adm_input = 0; + const map &input_maps = output_track->GetInputMaps(); + map::const_iterator iter; + for (iter = input_maps.begin(); iter != input_maps.end(); iter++) { + RawInput *input = dynamic_cast(iter->second.input_track)->GetRawInput(); + if (input->essence_type != WAVE_PCM || !input->wave_reader) + continue; + + // Check that the input channel has a chna audio ID + WaveCHNA *chna = input->wave_reader->GetCHNA(); + if (!chna) + continue; + + // + 1 below because ADM track (channel) indexes start at 1 + uint32_t input_channel_index = iter->second.input_channel_index; + vector audio_ids = chna->GetAudioIDs(input_channel_index + 1); + if (audio_ids.empty()) + continue; + + // Require at least a axml, bxml or sxml chunk + WaveFileChunk *axml = input->wave_reader->GetAdditionalChunk(WAVE_CHUNK_TAG("axml")); + WaveFileChunk *bxml = input->wave_reader->GetAdditionalChunk(WAVE_CHUNK_TAG("bxml")); + WaveFileChunk *sxml = input->wave_reader->GetAdditionalChunk(WAVE_CHUNK_TAG("sxml")); + if (axml || bxml || sxml) { + if (output_track_wave_adm_input) { + if (input != output_track_wave_adm_input) { + log_warn("MXF output track references multiple WAVE input files with ADM\n"); + // This wrap is not supported; decide to not include any ADM in the output + output_tracks_using_adm.clear(); + done = true; + break; + } + } else { + output_tracks_using_adm.push_back(make_pair(output_track, input)); + output_track_wave_adm_input = input; + wave_adm_inputs.insert(input); + } + } + } + } + + if (!output_tracks_using_adm.empty()) { + // Add ADM chunks to the clip + map > input_chunk_refs; + set::const_iterator iter; + for (iter = wave_adm_inputs.begin(); iter != wave_adm_inputs.end(); iter++) { + RawInput *input = *iter; + WaveReader *wave_reader = input->wave_reader; + + WaveFileChunk *axml = wave_reader->GetAdditionalChunk(WAVE_CHUNK_TAG("axml")); + if (axml) + input_chunk_refs[input].push_back(clip->AddWaveChunk(axml, false)); + WaveFileChunk *bxml = wave_reader->GetAdditionalChunk(WAVE_CHUNK_TAG("bxml")); + if (bxml) + input_chunk_refs[input].push_back(clip->AddWaveChunk(bxml, false)); + WaveFileChunk *sxml = wave_reader->GetAdditionalChunk(WAVE_CHUNK_TAG("sxml")); + if (sxml) + input_chunk_refs[input].push_back(clip->AddWaveChunk(sxml, false)); + } + + // Add references to the ADM chunks and chna audio IDs to the clip tracks + for (i = 0; i < output_tracks_using_adm.size(); i++) { + OutputTrack *output_track = output_tracks_using_adm[i].first; + RawInput *wave_adm_input = output_tracks_using_adm[i].second; + + ClipWriterTrack *clip_track = output_track->GetClipTrack(); + + // Add generic stream ID references to the chunks to the clip track + const vector &chunk_refs = input_chunk_refs[wave_adm_input]; + size_t k; + for (k = 0; k < chunk_refs.size(); k++) + clip_track->AddWaveChunkReference(chunk_refs[k]); + + // Add chna AudioIDs to the clip track. + // Use the input to output channel mapping to set the chna track_index + WaveCHNA *input_chna = wave_adm_input->wave_reader->GetCHNA(); + const map &input_maps = output_track->GetInputMaps(); + map::const_iterator iter; + for (iter = input_maps.begin(); iter != input_maps.end(); iter++) { + RawInput *input = dynamic_cast(iter->second.input_track)->GetRawInput(); + if (input != wave_adm_input) + continue; + + // + 1 below because ADM track (channel) indexes start at 1 + uint32_t input_channel_index = iter->second.input_channel_index; + vector audio_ids = input_chna->GetAudioIDs(input_channel_index + 1); + for (k = 0; k < audio_ids.size(); k++) { + WaveCHNA::AudioID &audio_id = audio_ids[k]; + + // + 1 below because ADM track (channel) indexes start at 1 + uint32_t output_channel_index = iter->first; + audio_id.track_index = output_channel_index + 1; + clip_track->AddADMAudioID(audio_id); + } + } + } + } + } + + // prepare the clip's header metadata clip->PrepareHeaderMetadata(); diff --git a/apps/writers/OutputTrack.h b/apps/writers/OutputTrack.h index 85243798..1393bcae 100644 --- a/apps/writers/OutputTrack.h +++ b/apps/writers/OutputTrack.h @@ -87,6 +87,14 @@ class OutputTrack void SkipPrecharge(int64_t num_read); +public: + typedef struct + { + InputTrack *input_track; + uint32_t input_channel_index; + bool have_sample_data; + } InputMap; + public: ClipWriterTrack* GetClipTrack() { return mClipWriterTrack; } uint32_t GetPhysSrcTrackIndex() { return mPhysSrcTrackIndex; } @@ -97,13 +105,7 @@ class OutputTrack OutputTrackSoundInfo* GetSoundInfo(); InputTrack* GetFirstInputTrack(); -private: - typedef struct - { - InputTrack *input_track; - uint32_t input_channel_index; - bool have_sample_data; - } InputMap; + const std::map& GetInputMaps() const { return mInputMaps; } private: ClipWriterTrack *mClipWriterTrack; diff --git a/include/bmx/BMXMXFIO.h b/include/bmx/BMXMXFIO.h new file mode 100644 index 00000000..3156d969 --- /dev/null +++ b/include/bmx/BMXMXFIO.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BMX_MXF_IO_H_ +#define BMX_MXF_IO_H_ + +#include + +#include + + +namespace bmx +{ + + +class BMXMXFIO: public BMXIO +{ +public: + BMXMXFIO(mxfpp::File *mxf_file); + virtual ~BMXMXFIO(); + + virtual uint32_t Read(unsigned char *data, uint32_t size); + + virtual uint32_t Write(const unsigned char *data, uint32_t size); + + virtual bool Seek(int64_t offset, int whence); + + virtual int64_t Tell(); + virtual int64_t Size(); + +private: + mxfpp::File *mFile; +}; + + +}; + + +#endif diff --git a/include/bmx/clip_writer/ClipWriter.h b/include/bmx/clip_writer/ClipWriter.h index adfb28f1..494d1c14 100644 --- a/include/bmx/clip_writer/ClipWriter.h +++ b/include/bmx/clip_writer/ClipWriter.h @@ -77,6 +77,8 @@ class ClipWriter void ReserveHeaderMetadataSpace(uint32_t min_bytes); void ForceWriteCBEDuration0(bool enable); + uint32_t AddWaveChunk(WaveChunk *chunk, bool take_ownership); + public: ClipWriterTrack* CreateTrack(EssenceType essence_type, std::string track_filename = ""); ClipWriterTrack* CreateXMLTrack(); diff --git a/include/bmx/clip_writer/ClipWriterTrack.h b/include/bmx/clip_writer/ClipWriterTrack.h index 846b4df6..6df2e11a 100644 --- a/include/bmx/clip_writer/ClipWriterTrack.h +++ b/include/bmx/clip_writer/ClipWriterTrack.h @@ -47,6 +47,7 @@ #include #include #include +#include @@ -104,6 +105,9 @@ class ClipWriterTrack mxfpp::GroupOfSoundfieldGroupsLabelSubDescriptor* AddGroupOfSoundfieldGroupLabel( mxfpp::GroupOfSoundfieldGroupsLabelSubDescriptor *copy_from = 0); + void AddWaveChunkReference(uint32_t stream_id); + void AddADMAudioID(const WaveCHNA::AudioID &audio_id); + // Data properties void SetConstantDataSize(uint32_t size); void SetMaxDataSize(uint32_t size); diff --git a/include/bmx/mxf_helper/ADMCHNAMXFDescriptorHelper.h b/include/bmx/mxf_helper/ADMCHNAMXFDescriptorHelper.h new file mode 100644 index 00000000..d77f67fb --- /dev/null +++ b/include/bmx/mxf_helper/ADMCHNAMXFDescriptorHelper.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BMX_ADM_CHNA_MXF_DESCRIPTOR_HELPER_H_ +#define BMX_ADM_CHNA_MXF_DESCRIPTOR_HELPER_H_ + +#include +#include + + +namespace bmx +{ + +WaveCHNA* convert_adm_chna_descriptor_to_chunk(const mxfpp::ADM_CHNASubDescriptor *descriptor); + +mxfpp::ADM_CHNASubDescriptor* convert_chunk_to_adm_chna_descriptor(mxfpp::HeaderMetadata *header_metadata, const WaveCHNA *chunk); + + +}; + + +#endif diff --git a/include/bmx/mxf_op1a/OP1AFile.h b/include/bmx/mxf_op1a/OP1AFile.h index 4f7d05a1..d95c950c 100644 --- a/include/bmx/mxf_op1a/OP1AFile.h +++ b/include/bmx/mxf_op1a/OP1AFile.h @@ -42,7 +42,10 @@ #include #include #include +#include #include +#include +#include #include #include @@ -74,6 +77,7 @@ class OP1AFile friend class OP1ATrack; friend class OP1AMPEG2LGTrack; friend class OP1ATimedTextTrack; + friend class OP1APCMTrack; public: static mxfUMID CreatePackageUID(); @@ -103,6 +107,8 @@ class OP1AFile void SetIndexFollowsEssence(bool enable); // default false. If true then place index partition after the essence it indexes, even for CBE void SetSignalST3792(bool enable); // default false. If true then signal ST 379-2 compliance using sub-descriptor + uint32_t AddWaveChunk(WaveChunk *chunk, bool take_ownership); + public: void SetOutputStartOffset(int64_t offset); void SetOutputEndOffset(int64_t offset); @@ -233,6 +239,9 @@ class OP1AFile UniqueIdHelper mTrackIdHelper; UniqueIdHelper mStreamIdHelper; + + std::map mWaveChunks; + std::vector mOwnedWaveChunks; }; diff --git a/include/bmx/mxf_op1a/OP1APCMTrack.h b/include/bmx/mxf_op1a/OP1APCMTrack.h index 03dd8170..78b640ca 100644 --- a/include/bmx/mxf_op1a/OP1APCMTrack.h +++ b/include/bmx/mxf_op1a/OP1APCMTrack.h @@ -34,6 +34,7 @@ #include #include +#include @@ -58,6 +59,9 @@ class OP1APCMTrack : public OP1ATrack void SetSequenceOffset(uint8_t offset); // default not set void SetChannelAssignment(UL label); // default not set + void AddADMAudioID(const WaveCHNA::AudioID &audio_id); + void AddWaveChunkReference(uint32_t stream_id); + mxfpp::AudioChannelLabelSubDescriptor* AddAudioChannelLabel( mxfpp::AudioChannelLabelSubDescriptor *copy_from = 0); mxfpp::SoundfieldGroupLabelSubDescriptor* AddSoundfieldGroupLabel( @@ -88,6 +92,8 @@ class OP1APCMTrack : public OP1ATrack WaveMXFDescriptorHelper *mWaveDescriptorHelper; std::vector mSampleSequence; std::vector mMCALabels; + WaveCHNA *mCHNAChunk; + std::set mWaveChunkReferences; }; diff --git a/include/bmx/mxf_reader/MXFFileTrackReader.h b/include/bmx/mxf_reader/MXFFileTrackReader.h index 191fbdea..0001da68 100644 --- a/include/bmx/mxf_reader/MXFFileTrackReader.h +++ b/include/bmx/mxf_reader/MXFFileTrackReader.h @@ -91,6 +91,16 @@ class MXFFileTrackReader : public MXFTrackReader void SetAVCIHeader(const unsigned char *frame_data, uint32_t frame_data_size); +public: + virtual std::vector GetCHNAAudioIDs(uint32_t channel_index) const; + + virtual size_t GetNumWaveChunks() const { return mWaveChunks.size(); } + virtual MXFWaveChunk* GetWaveChunk(size_t index) const; + + virtual MXFWaveChunk* GetWaveChunk(WaveChunkTag tag) const; + + virtual WaveCHNA* GetWaveCHNA() const { return mWaveCHNA; } + public: virtual bool IsEnabled() const { return mIsEnabled; } virtual FrameBuffer* GetFrameBuffer() { return &mFrameBuffer; } @@ -111,6 +121,9 @@ class MXFFileTrackReader : public MXFTrackReader MXFFrameBuffer mFrameBuffer; unsigned char *mAVCIHeader; + + std::vector mWaveChunks; + WaveCHNA *mWaveCHNA; }; diff --git a/include/bmx/mxf_reader/MXFTrackReader.h b/include/bmx/mxf_reader/MXFTrackReader.h index 1a9e088b..819eff67 100644 --- a/include/bmx/mxf_reader/MXFTrackReader.h +++ b/include/bmx/mxf_reader/MXFTrackReader.h @@ -36,9 +36,11 @@ #include +#include #include #include #include +#include #define CURRENT_POSITION_VALUE (int64_t)(((uint64_t)1)<<63) @@ -100,6 +102,16 @@ class MXFTrackReader virtual bool HaveAVCIHeader() const = 0; virtual const unsigned char* GetAVCIHeader() const = 0; +public: + virtual std::vector GetCHNAAudioIDs(uint32_t channel_index) const; + + virtual size_t GetNumWaveChunks() const; + virtual MXFWaveChunk* GetWaveChunk(size_t index) const; + + virtual MXFWaveChunk* GetWaveChunk(WaveChunkTag tag) const; + + virtual WaveCHNA* GetWaveCHNA() const; + public: virtual bool IsEnabled() const = 0; virtual FrameBuffer* GetFrameBuffer() = 0; diff --git a/include/bmx/mxf_reader/MXFWaveChunk.h b/include/bmx/mxf_reader/MXFWaveChunk.h new file mode 100644 index 00000000..4992e4ed --- /dev/null +++ b/include/bmx/mxf_reader/MXFWaveChunk.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BMX_MXF_WAVE_CHUNK_H_ +#define BMX_MXF_WAVE_CHUNK_H_ + +#include +#include + +#include + +#include +#include +#include + + +namespace bmx +{ + + +class MXFWaveChunk : public WaveChunk +{ +public: + MXFWaveChunk(mxfpp::File *mxf_file, const mxfpp::RIFFChunkDefinitionSubDescriptor *riff_chunk_descriptor); + virtual ~MXFWaveChunk(); + + virtual uint32_t Read(unsigned char *data, uint32_t size); + virtual int64_t Tell(); + virtual int64_t Size(); + +public: + uint32_t GetStreamId() const { return mGSReader->GetStreamId(); } + +private: + GenericStreamReader *mGSReader; +}; + + +}; + + +#endif diff --git a/include/bmx/wave/WaveBEXT.h b/include/bmx/wave/WaveBEXT.h index 5c1d0200..a5d64e45 100644 --- a/include/bmx/wave/WaveBEXT.h +++ b/include/bmx/wave/WaveBEXT.h @@ -68,6 +68,7 @@ class WaveBEXT void AppendCodingHistory(std::vector > line); uint32_t GetSize(); + uint32_t GetAlignedSize() { return GetSize() + (GetSize() & 1); } bool WasUpdated() { return mWasUpdated; } void Write(WaveIO *output); diff --git a/include/bmx/wave/WaveCHNA.h b/include/bmx/wave/WaveCHNA.h new file mode 100644 index 00000000..f96d0812 --- /dev/null +++ b/include/bmx/wave/WaveCHNA.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BMX_WAVE_CHNA_H_ +#define BMX_WAVE_CHNA_H_ + + +#include + +#include +#include + + + +namespace bmx +{ + + +class WaveCHNA +{ +public: + WaveCHNA(); + ~WaveCHNA(); + +public: + typedef struct { + uint16_t track_index; + uint8_t uid[12]; + uint8_t track_ref[14]; + uint8_t pack_ref[11]; + } AudioID; + +public: + void AppendAudioID(const AudioID &audio_id); + + uint32_t GetSize(); + uint32_t GetAlignedSize() { return GetSize(); } + + void Write(WaveIO *output); + +public: + uint16_t GetNumTracks() const { return mNumTracks; } + uint16_t GetNumUIDs() const { return mNumUIDs; } + const std::vector& GetAudioIDs() const { return mAudioIDs; } + + std::vector GetAudioIDs(uint16_t track_index) const; + + void Read(WaveIO *input, uint32_t size); + +private: + uint16_t mNumTracks; + uint16_t mNumUIDs; + std::vector mAudioIDs; +}; + + +}; + + + +#endif + diff --git a/include/bmx/wave/WaveChunk.h b/include/bmx/wave/WaveChunk.h new file mode 100644 index 00000000..42a8a311 --- /dev/null +++ b/include/bmx/wave/WaveChunk.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BMX_WAVE_CHUNK_H_ +#define BMX_WAVE_CHUNK_H_ + +#include + +#include +#include + + +namespace bmx +{ + + +typedef mxfRIFFChunkIDType WaveChunkTag; + +#define WAVE_CHUNK_TAG(cstr) (WaveChunkTag){(cstr)[0], (cstr)[1], (cstr)[2], (cstr)[3]} + +std::string get_wave_chunk_tag_str(WaveChunkTag tag); + + +}; + + +bool operator==(const bmx::WaveChunkTag &left, const bmx::WaveChunkTag &right); +bool operator!=(const bmx::WaveChunkTag &left, const bmx::WaveChunkTag &right); +bool operator<(const bmx::WaveChunkTag &left, const bmx::WaveChunkTag &right); + +bool operator==(const bmx::WaveChunkTag &left, const char *right); +bool operator!=(const bmx::WaveChunkTag &left, const char *right); + + +namespace bmx +{ + + +class WaveChunk : public BMXIO +{ +public: + WaveChunk(WaveChunkTag tag); + virtual ~WaveChunk(); + + WaveChunkTag Tag() const { return mTag; } + + virtual uint32_t Read(unsigned char *data, uint32_t size) = 0; + virtual int64_t Tell() = 0; + virtual int64_t Size() = 0; + +public: + int64_t AlignedSize() { return Size() + (Size() & 1); } + +protected: + WaveChunkTag mTag; +}; + + +}; + + +#endif diff --git a/include/bmx/wave/WaveFileChunk.h b/include/bmx/wave/WaveFileChunk.h new file mode 100644 index 00000000..b1a66a4b --- /dev/null +++ b/include/bmx/wave/WaveFileChunk.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BMX_WAVE_FILE_CHUNK_H_ +#define BMX_WAVE_FILE_CHUNK_H_ + +#include + + +namespace bmx +{ + + +class WaveFileChunk : public WaveChunk +{ +public: + WaveFileChunk(WaveChunkTag tag, BMXIO *file, int64_t offset, uint32_t size); + virtual ~WaveFileChunk(); + + virtual uint32_t Read(unsigned char *data, uint32_t size); + + virtual int64_t Tell() { return mPosition; } + virtual int64_t Size() { return mSize; } + +private: + BMXIO *mFile; + int64_t mOffset; + uint32_t mSize; + uint32_t mPosition; +}; + + +}; + + +#endif diff --git a/include/bmx/wave/WaveIO.h b/include/bmx/wave/WaveIO.h index 0e6a48e8..2f0b5e14 100644 --- a/include/bmx/wave/WaveIO.h +++ b/include/bmx/wave/WaveIO.h @@ -36,6 +36,8 @@ #include #include +#include +#include @@ -43,25 +45,25 @@ namespace bmx { -class WaveIO +class WaveIO : public BMXIO { public: WaveIO(); virtual ~WaveIO(); virtual uint32_t Read(unsigned char *data, uint32_t size) = 0; - virtual int GetChar() = 0; - virtual uint32_t Write(const unsigned char *data, uint32_t size) = 0; - virtual int PutChar(int c) = 0; - virtual bool Seek(int64_t offset, int whence) = 0; - virtual int64_t Tell() = 0; virtual int64_t Size() = 0; +public: + virtual int GetChar() = 0; + virtual int PutChar(int c) = 0; + public: void WriteTag(const char *tag); + void WriteTag(WaveChunkTag tag); void WriteSize(uint32_t size) { WriteUInt32(size); } void WriteZeros(uint32_t size); void WriteString(const char *value, uint32_t len, uint32_t fixed_size); @@ -73,9 +75,10 @@ class WaveIO void WriteInt16(int16_t value); void WriteInt32(int32_t value); void WriteInt64(int64_t value); + void WriteChunk(WaveChunk *chunk); void Skip(int64_t offset) { Seek(offset, SEEK_CUR); } - bool ReadTag(char *tag); + bool ReadTag(WaveChunkTag *tag); uint32_t ReadSize() { return ReadUInt32(); } void ReadString(char *value, uint32_t fixed_size); uint8_t ReadUInt8(); diff --git a/include/bmx/wave/WaveReader.h b/include/bmx/wave/WaveReader.h index 165d6d67..d28633f6 100644 --- a/include/bmx/wave/WaveReader.h +++ b/include/bmx/wave/WaveReader.h @@ -39,7 +39,9 @@ #include #include #include +#include #include +#include @@ -74,16 +76,23 @@ class WaveReader uint16_t GetChannelBlockAlign() const { return mChannelBlockAlign; } uint16_t GetBlockAlign() const { return mBlockAlign; } WaveBEXT* GetBEXT() const { return mBEXT; } + WaveCHNA* GetCHNA() const { return mCHNA; } uint32_t GetNumTracks() const { return (uint32_t)mTracks.size(); } WaveTrackReader* GetTrack(uint32_t track_index) const; bool IsEnabled() const; +public: + uint32_t GetNumAdditionalChunks() const { return mChunks.size(); } + WaveFileChunk* GetAdditionalChunk(uint32_t index) const; + + WaveFileChunk* GetAdditionalChunk(WaveChunkTag tag) const; + private: - WaveReader(WaveIO *input, bool take_ownership, bool is_rf64, uint32_t riff_size); + WaveReader(WaveIO *input, bool take_ownership, bool require_ds64, uint32_t riff_size); - void ReadChunks(bool is_rf64, uint32_t riff_size); + void ReadChunks(bool require_ds64, uint32_t riff_size); private: WaveIO *mInput; @@ -95,6 +104,7 @@ class WaveReader uint16_t mChannelBlockAlign; uint16_t mBlockAlign; WaveBEXT *mBEXT; + WaveCHNA *mCHNA; int64_t mSampleCount; std::vector mTracks; @@ -105,6 +115,8 @@ class WaveReader int64_t mDataStartFilePosition; int64_t mPosition; ByteArray mReadBuffer; + + std::vector mChunks; }; diff --git a/include/bmx/wave/WaveTrackWriter.h b/include/bmx/wave/WaveTrackWriter.h index bdd31d52..78c217be 100644 --- a/include/bmx/wave/WaveTrackWriter.h +++ b/include/bmx/wave/WaveTrackWriter.h @@ -62,6 +62,7 @@ class WaveTrackWriter uint32_t GetSampleSize() const; Rational GetSamplingRate() const; uint16_t GetChannelCount() const { return mChannelCount; } + uint16_t GetStartChannel() const { return mStartChannel; } int64_t GetDuration() const; diff --git a/include/bmx/wave/WaveWriter.h b/include/bmx/wave/WaveWriter.h index f8cc41b3..8a0a359b 100644 --- a/include/bmx/wave/WaveWriter.h +++ b/include/bmx/wave/WaveWriter.h @@ -39,8 +39,9 @@ #include #include #include +#include #include - +#include namespace bmx @@ -58,12 +59,18 @@ class WaveWriter void SetStartTimecode(Timecode start_timecode); // sets time_reference in bext void SetSampleCount(int64_t count); // metadata and sizes are calculated and set + WaveBEXT* GetBroadcastAudioExtension() { return mBEXT; } + void AddCHNA(WaveCHNA *chna, bool take_ownership); + void AddChunk(WaveChunk *chunk, bool take_ownership); + public: WaveTrackWriter* CreateTrack(); public: + void UpdateChannelCounts(); + void PrepareWrite(); void WriteSamples(uint32_t track_index, const unsigned char *data, uint32_t size, uint32_t num_samples); void CompleteWrite(); @@ -86,6 +93,10 @@ class WaveWriter bool mStartTimecodeSet; int64_t mSetSampleCount; WaveBEXT *mBEXT; + WaveCHNA *mCHNA; + bool mOwnCHNA; + std::vector mAdditionalChunks; + std::vector mOwnedAdditionalChunks; Rational mSamplingRate; bool mSamplingRateSet; @@ -114,7 +125,8 @@ class WaveWriter int64_t mDataChunkFilePosition; int64_t mFactChunkFilePosition; - bool mUseRF64; + bool mRequire64Bit; + bool mWriteBW64; int64_t mSetSize; int64_t mSetDataSize; }; diff --git a/src/clip_writer/ClipWriter.cpp b/src/clip_writer/ClipWriter.cpp index 1678bc13..f3da9450 100644 --- a/src/clip_writer/ClipWriter.cpp +++ b/src/clip_writer/ClipWriter.cpp @@ -330,6 +330,29 @@ void ClipWriter::ForceWriteCBEDuration0(bool enable) } } +uint32_t ClipWriter::AddWaveChunk(WaveChunk *chunk, bool take_ownership) +{ + uint32_t stream_id = 0; + + switch (mType) + { + case CW_OP1A_CLIP_TYPE: + stream_id = mOP1AClip->AddWaveChunk(chunk, take_ownership); + break; + case CW_D10_CLIP_TYPE: + case CW_RDD9_CLIP_TYPE: + case CW_AS02_CLIP_TYPE: + case CW_AVID_CLIP_TYPE: + case CW_WAVE_CLIP_TYPE: + break; + case CW_UNKNOWN_CLIP_TYPE: + BMX_ASSERT(false); + break; + } + + return stream_id; +} + ClipWriterTrack* ClipWriter::CreateTrack(EssenceType essence_type, string track_filename) { ClipWriterTrack *track = 0; diff --git a/src/clip_writer/ClipWriterTrack.cpp b/src/clip_writer/ClipWriterTrack.cpp index 6a363d09..0891b579 100644 --- a/src/clip_writer/ClipWriterTrack.cpp +++ b/src/clip_writer/ClipWriterTrack.cpp @@ -1147,6 +1147,52 @@ GroupOfSoundfieldGroupsLabelSubDescriptor* ClipWriterTrack::AddGroupOfSoundfield return 0; } +void ClipWriterTrack::AddADMAudioID(const WaveCHNA::AudioID &audio_id) +{ + switch (mClipType) + { + case CW_OP1A_CLIP_TYPE: + { + OP1APCMTrack *pcm_track = dynamic_cast(mOP1ATrack); + if (pcm_track) + pcm_track->AddADMAudioID(audio_id); + break; + } + case CW_D10_CLIP_TYPE: + case CW_RDD9_CLIP_TYPE: + case CW_AS02_CLIP_TYPE: + case CW_AVID_CLIP_TYPE: + case CW_WAVE_CLIP_TYPE: + break; + case CW_UNKNOWN_CLIP_TYPE: + BMX_ASSERT(false); + break; + } +} + +void ClipWriterTrack::AddWaveChunkReference(uint32_t stream_id) +{ + switch (mClipType) + { + case CW_OP1A_CLIP_TYPE: + { + OP1APCMTrack *pcm_track = dynamic_cast(mOP1ATrack); + if (pcm_track) + pcm_track->AddWaveChunkReference(stream_id); + break; + } + case CW_D10_CLIP_TYPE: + case CW_RDD9_CLIP_TYPE: + case CW_AS02_CLIP_TYPE: + case CW_AVID_CLIP_TYPE: + case CW_WAVE_CLIP_TYPE: + break; + case CW_UNKNOWN_CLIP_TYPE: + BMX_ASSERT(false); + break; + } +} + void ClipWriterTrack::SetConstantDataSize(uint32_t size) { switch (mClipType) diff --git a/src/common/BMXMXFIO.cpp b/src/common/BMXMXFIO.cpp new file mode 100644 index 00000000..1c5a9de4 --- /dev/null +++ b/src/common/BMXMXFIO.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include +#include + +using namespace std; +using namespace bmx; +using namespace mxfpp; + + + +BMXMXFIO::BMXMXFIO(File *mxf_file) +: BMXIO() +{ + mFile = mxf_file; +} + +BMXMXFIO::~BMXMXFIO() +{ + // mFile is not owned +} + +uint32_t BMXMXFIO::Read(unsigned char *data, uint32_t size) +{ + return mFile->read(data, size); +} + +uint32_t BMXMXFIO::Write(const unsigned char *data, uint32_t size) +{ + return mFile->write(data, size); +} + +bool BMXMXFIO::Seek(int64_t offset, int whence) +{ + try { + mFile->seek(offset, whence); + return true; + } catch (...) { + return false; + } +} + +int64_t BMXMXFIO::Tell() +{ + return mFile->tell(); +} + +int64_t BMXMXFIO::Size() +{ + return mFile->size(); +} diff --git a/src/mxf_helper/ADMCHNAMXFDescriptorHelper.cpp b/src/mxf_helper/ADMCHNAMXFDescriptorHelper.cpp new file mode 100644 index 00000000..96e81056 --- /dev/null +++ b/src/mxf_helper/ADMCHNAMXFDescriptorHelper.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include +#include +#include + +using namespace std; +using namespace bmx; +using namespace mxfpp; + + +WaveCHNA* bmx::convert_adm_chna_descriptor_to_chunk(const ADM_CHNASubDescriptor *descriptor) +{ + WaveCHNA *chunk = new WaveCHNA(); + + vector channel_mappings = descriptor->getADMChannelMappingsArray(); + size_t i; + for (i = 0; i < channel_mappings.size(); i++) { + ADMChannelMapping *mapping = channel_mappings[i]; + + WaveCHNA::AudioID audio_id; + audio_id.track_index = mapping->getLocalChannelID(); + + string uid_str = mapping->getADMAudioTrackUID(); + uid_str.resize(sizeof(audio_id.uid)); + memcpy(audio_id.uid, uid_str.c_str(), sizeof(audio_id.uid)); + + string track_ref_str = mapping->getADMAudioTrackChannelFormatID(); + track_ref_str.resize(sizeof(audio_id.track_ref)); + memcpy(audio_id.track_ref, track_ref_str.c_str(), sizeof(audio_id.track_ref)); + + if (mapping->haveADMAudioPackFormatID()) { + string pack_ref_str = mapping->getADMAudioPackFormatID(); + pack_ref_str.resize(sizeof(audio_id.pack_ref)); + memcpy(audio_id.pack_ref, pack_ref_str.c_str(), sizeof(audio_id.pack_ref)); + } else { + memset(audio_id.pack_ref, 0, sizeof(audio_id.pack_ref)); + } + + chunk->AppendAudioID(audio_id); + } + + return chunk; +} + +ADM_CHNASubDescriptor* bmx::convert_chunk_to_adm_chna_descriptor(HeaderMetadata *header_metadata, const WaveCHNA *chunk) +{ + ADM_CHNASubDescriptor *descriptor = new ADM_CHNASubDescriptor(header_metadata); + descriptor->setNumLocalChannels(chunk->GetNumTracks()); + descriptor->setNumADMAudioTrackUIDs(chunk->GetNumUIDs()); + + const vector &audio_ids = chunk->GetAudioIDs(); + size_t i; + for (i = 0; i < audio_ids.size(); i++) { + const WaveCHNA::AudioID &audio_id = audio_ids[i]; + + ADMChannelMapping *mapping = new ADMChannelMapping(header_metadata); + mapping->setLocalChannelID(audio_id.track_index); + mapping->setADMAudioTrackUID(string((const char*)audio_id.uid, sizeof(audio_id.uid))); + mapping->setADMAudioTrackChannelFormatID(string((const char*)audio_id.track_ref, sizeof(audio_id.track_ref))); + + string pack_ref_str = string((const char*)audio_id.pack_ref, sizeof(audio_id.pack_ref)); + if (!pack_ref_str.empty()) + mapping->setADMAudioPackFormatID(pack_ref_str); + + descriptor->appendADMChannelMappingsArray(mapping); + } + + return descriptor; +} diff --git a/src/mxf_op1a/OP1AFile.cpp b/src/mxf_op1a/OP1AFile.cpp index 42f5cafa..5f25e1b4 100644 --- a/src/mxf_op1a/OP1AFile.cpp +++ b/src/mxf_op1a/OP1AFile.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -176,6 +177,8 @@ OP1AFile::~OP1AFile() delete mTracks[i]; for (i = 0; i < mXMLTracks.size(); i++) delete mXMLTracks[i]; + for (i = 0; i < mOwnedWaveChunks.size(); i++) + delete mOwnedWaveChunks[i]; delete mMXFFile; delete mDataModel; @@ -290,6 +293,17 @@ void OP1AFile::SetSignalST3792(bool enable) mSignalST3792 = enable; } +uint32_t OP1AFile::AddWaveChunk(WaveChunk *chunk, bool take_ownership) +{ + uint32_t stream_id = mStreamIdHelper.GetNextId(STREAM_TYPE); + mWaveChunks[stream_id] = chunk; + + if (take_ownership) + mOwnedWaveChunks.push_back(chunk); + + return stream_id; +} + void OP1AFile::SetOutputStartOffset(int64_t offset) { BMX_CHECK(offset >= 0); @@ -894,6 +908,15 @@ void OP1AFile::CreateHeaderMetadata() mult_descriptor->setEssenceContainer(MXF_EC_L(MultipleWrappings)); if (mSupportCompleteSinglePass) mult_descriptor->setContainerDuration(mInputDuration); + + // Preface - ContentStorage - SourcePackage - (Multiple) File Descriptor - Wave Chunk sub-descriptors + map::const_iterator iter; + for (iter = mWaveChunks.begin(); iter != mWaveChunks.end(); iter++) { + RIFFChunkDefinitionSubDescriptor *wave_chunk_subdesc = new RIFFChunkDefinitionSubDescriptor(mHeaderMetadata); + mult_descriptor->appendSubDescriptors(wave_chunk_subdesc); + wave_chunk_subdesc->setRIFFChunkStreamID(iter->first); + wave_chunk_subdesc->setRIFFChunkID(iter->second->Tag()); + } } } @@ -997,7 +1020,7 @@ void OP1AFile::CreateFile() mHeaderMetadataEndPos = mMXFFile->tell(); // need this position when we re-write the header metadata - // write generic stream partitions + // write XML generic stream partitions size_t i; for (i = 0; i < mXMLTracks.size(); i++) { @@ -1021,6 +1044,35 @@ void OP1AFile::CreateFile() } + // write Wave chunk generic stream partitions + + map::const_iterator wave_chunk_iter; + for (wave_chunk_iter = mWaveChunks.begin(); wave_chunk_iter != mWaveChunks.end(); wave_chunk_iter++) { + if (header_partition.getIndexSID() || header_partition.getBodySID()) + BMX_EXCEPTION(("Wave chunk's Generic Stream partition is currently incompatible with minimal partitions flavour")); + if (mSupportCompleteSinglePass) + BMX_EXCEPTION(("Wave chunk's Generic Stream partition is currently incompatible with single pass flavour")); + + if (mMXFFile->isMemoryFileOpen()) + mMXFFile->closeMemoryFile(); + + Partition &stream_partition = mMXFFile->createPartition(); + stream_partition.setKey(&MXF_GS_PP_K(GenericStream)); + stream_partition.setBodySID(wave_chunk_iter->first); + stream_partition.write(mMXFFile); + + uint8_t llen = mxf_get_llen(mMXFFile->getCFile(), wave_chunk_iter->second->Size()); + if (llen < 4) + llen = 4; + mMXFFile->writeFixedKL(&MXF_EE_K(WaveChunk), llen, wave_chunk_iter->second->Size()); + + BMXMXFIO bmx_mxf_io(mMXFFile); + dynamic_cast(&bmx_mxf_io)->Write(wave_chunk_iter->second); + + stream_partition.fillToKag(mMXFFile); + } + + // write timed text track index and essence container for (i = 0; i < mTracks.size(); i++) { diff --git a/src/mxf_op1a/OP1APCMTrack.cpp b/src/mxf_op1a/OP1APCMTrack.cpp index e8e0fe84..6db02636 100644 --- a/src/mxf_op1a/OP1APCMTrack.cpp +++ b/src/mxf_op1a/OP1APCMTrack.cpp @@ -35,6 +35,7 @@ #include #include +#include #include #include #include @@ -58,6 +59,8 @@ OP1APCMTrack::OP1APCMTrack(OP1AFile *file, uint32_t track_index, uint32_t track_ mxfRational frame_rate, EssenceType essence_type) : OP1ATrack(file, track_index, track_id, track_type_number, frame_rate, essence_type) { + mCHNAChunk = 0; + BMX_ASSERT(essence_type == WAVE_PCM); mWaveDescriptorHelper = dynamic_cast(mDescriptorHelper); @@ -89,6 +92,7 @@ OP1APCMTrack::OP1APCMTrack(OP1AFile *file, uint32_t track_index, uint32_t track_ OP1APCMTrack::~OP1APCMTrack() { + delete mCHNAChunk; } void OP1APCMTrack::SetAES3Mapping(bool enable) @@ -167,6 +171,19 @@ void OP1APCMTrack::SetChannelAssignment(UL label) mWaveDescriptorHelper->SetChannelAssignment(label); } +void OP1APCMTrack::AddADMAudioID(const WaveCHNA::AudioID &audio_id) +{ + if (!mCHNAChunk) + mCHNAChunk = new WaveCHNA(); + + mCHNAChunk->AppendAudioID(audio_id); +} + +void OP1APCMTrack::AddWaveChunkReference(uint32_t stream_id) +{ + mWaveChunkReferences.insert(stream_id); +} + AudioChannelLabelSubDescriptor* OP1APCMTrack::AddAudioChannelLabel(AudioChannelLabelSubDescriptor *copy_from) { AudioChannelLabelSubDescriptor *desc; @@ -255,12 +272,36 @@ void OP1APCMTrack::AddHeaderMetadata(HeaderMetadata *header_metadata, MaterialPa } } + set::const_iterator iter; + for (iter = mWaveChunkReferences.begin(); iter != mWaveChunkReferences.end(); iter++) { + try { + mOP1AFile->mWaveChunks.at(*iter); + } catch (...) { + BMX_EXCEPTION(("Wave chunk with stream ID %u has not been registered with OP1AFile", *iter)); + } + } + OP1ATrack::AddHeaderMetadata(header_metadata, material_package, file_source_package); for (i = 0; i < mMCALabels.size(); i++) { header_metadata->moveToEnd(mMCALabels[i]); // so that they appear after the descriptor in the file mDescriptorHelper->GetFileDescriptor()->appendSubDescriptors(mMCALabels[i]); } + + if (mCHNAChunk) { + ADM_CHNASubDescriptor *chna_subdesc = convert_chunk_to_adm_chna_descriptor(header_metadata, mCHNAChunk); + + header_metadata->moveToEnd(chna_subdesc); // so that they appear after the descriptor in the file + mDescriptorHelper->GetFileDescriptor()->appendSubDescriptors(chna_subdesc); + } + + if (!mWaveChunkReferences.empty()) { + RIFFChunkReferencesSubDescriptor *chunk_ref_subdesc = new RIFFChunkReferencesSubDescriptor(mOP1AFile->GetHeaderMetadata()); + chunk_ref_subdesc->setRIFFChunkStreamIDsArray(vector(mWaveChunkReferences.begin(), mWaveChunkReferences.end())); + + header_metadata->moveToEnd(chunk_ref_subdesc); // so that they appear after the descriptor in the file + mDescriptorHelper->GetFileDescriptor()->appendSubDescriptors(chunk_ref_subdesc); + } } void OP1APCMTrack::PrepareWrite(uint8_t track_count) diff --git a/src/mxf_reader/MXFFileTrackReader.cpp b/src/mxf_reader/MXFFileTrackReader.cpp index 3d57a266..7070a463 100644 --- a/src/mxf_reader/MXFFileTrackReader.cpp +++ b/src/mxf_reader/MXFFileTrackReader.cpp @@ -34,9 +34,13 @@ #endif #include +#include +#include #include #include +#include +#include #include #include #include @@ -60,12 +64,69 @@ MXFFileTrackReader::MXFFileTrackReader(MXFFileReader *file_reader, size_t track_ mFrameBuffer.SetTargetBuffer(new DefaultFrameBuffer(), true); mAVCIHeader = 0; + mWaveCHNA = 0; + + // get MXFWaveChunks for each RIFFChunkReferenceSubDescriptor sub-descriptor reference + // get a WaveCHNA from a ADM_CHNASubDescriptor + WaveAudioDescriptor *wave_descriptor = dynamic_cast(file_descriptor); + if (file_source_package->getDescriptor()->haveSubDescriptors() && + wave_descriptor && wave_descriptor->haveSubDescriptors()) + { + vector sub_descriptors = wave_descriptor->getSubDescriptors(); + size_t i; + for (i = 0; i < sub_descriptors.size(); i++) { + RIFFChunkReferencesSubDescriptor *chunk_ref_descriptor = + dynamic_cast(sub_descriptors[i]); + + if (chunk_ref_descriptor) { + // Get the chunk descriptors associated with the File Source Package descriptor + map chunk_descriptors; + MultipleDescriptor *multi_descriptor = dynamic_cast(file_source_package->getDescriptor()); + if (multi_descriptor) { + vector fsp_sub_descriptors = multi_descriptor->getSubDescriptors(); + size_t k; + for (k = 0; k < fsp_sub_descriptors.size(); k++) { + RIFFChunkDefinitionSubDescriptor *chunk_descriptor = + dynamic_cast(fsp_sub_descriptors[k]); + if (chunk_descriptor) + chunk_descriptors[chunk_descriptor->getRIFFChunkStreamID()] = chunk_descriptor; + } + + // Create a MXFWaveChunk for each chunk referenced + vector stream_ids = chunk_ref_descriptor->getRIFFChunkStreamIDsArray(); + set unique_stream_ids(stream_ids.begin(), stream_ids.end()); + set::const_iterator iter; + for (iter = unique_stream_ids.begin(); iter != unique_stream_ids.end(); iter++) { + const RIFFChunkDefinitionSubDescriptor *chunk_descriptor = 0; + try { + chunk_descriptor = chunk_descriptors.at(*iter); + } catch (...) { + log_warn("Referenced chunk descriptor with stream id %u does not exist in package descriptor\n", *iter); + continue; + } + + mWaveChunks.push_back(new MXFWaveChunk(file_reader->mFile, chunk_descriptor)); + } + } + } else { + ADM_CHNASubDescriptor *chna_descriptor = + dynamic_cast(sub_descriptors[i]); + if (chna_descriptor) + mWaveCHNA = convert_adm_chna_descriptor_to_chunk(chna_descriptor); + } + } + } } MXFFileTrackReader::~MXFFileTrackReader() { delete mTrackInfo; delete [] mAVCIHeader; + + size_t i; + for (i = 0; i < mWaveChunks.size(); i++) + delete mWaveChunks[i]; + delete mWaveCHNA; } void MXFFileTrackReader::SetEmptyFrames(bool enable) @@ -203,3 +264,28 @@ void MXFFileTrackReader::SetAVCIHeader(const unsigned char *frame_data, uint32_t memcpy(mAVCIHeader, frame_data, AVCI_HEADER_SIZE); } +vector MXFFileTrackReader::GetCHNAAudioIDs(uint32_t channel_index) const +{ + if (!mWaveCHNA) + return vector(); + + // + 1 because chna track_index starts from 1 + return mWaveCHNA->GetAudioIDs(channel_index + 1); +} + +MXFWaveChunk* MXFFileTrackReader::GetWaveChunk(size_t index) const +{ + BMX_CHECK(index < mWaveChunks.size()); + return mWaveChunks[index]; +} + +MXFWaveChunk* MXFFileTrackReader::GetWaveChunk(WaveChunkTag tag) const +{ + size_t i; + for (i = 0; i < mWaveChunks.size(); i++) { + if (tag == mWaveChunks[i]->Tag()) + return mWaveChunks[i]; + } + + return 0; +} diff --git a/src/mxf_reader/MXFTrackReader.cpp b/src/mxf_reader/MXFTrackReader.cpp new file mode 100644 index 00000000..472bfefd --- /dev/null +++ b/src/mxf_reader/MXFTrackReader.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +using namespace std; +using namespace bmx; + + +vector MXFTrackReader::GetCHNAAudioIDs(uint32_t channel_index) const +{ + // Not yet implemented in all sub-classes + (void)channel_index; + return vector(); +} + +size_t MXFTrackReader::GetNumWaveChunks() const +{ + // Not yet implemented in all sub-classes + return 0; +} + +MXFWaveChunk* MXFTrackReader::GetWaveChunk(size_t index) const +{ + // Not yet implemented in all sub-classes + (void)index; + return 0; +} + +MXFWaveChunk* MXFTrackReader::GetWaveChunk(WaveChunkTag tag) const +{ + // Not yet implemented in all sub-classes + (void)tag; + return 0; +} + +WaveCHNA* MXFTrackReader::GetWaveCHNA() const +{ + // Not yet implemented in all sub-classes + return 0; +} diff --git a/src/mxf_reader/MXFWaveChunk.cpp b/src/mxf_reader/MXFWaveChunk.cpp new file mode 100644 index 00000000..91f80a26 --- /dev/null +++ b/src/mxf_reader/MXFWaveChunk.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define __STDC_LIMIT_MACROS + +#include + +#include +#include +#include + +using namespace std; +using namespace bmx; +using namespace mxfpp; + + +MXFWaveChunk::MXFWaveChunk(File *mxf_file, const RIFFChunkDefinitionSubDescriptor *riff_chunk_descriptor) +: WaveChunk(riff_chunk_descriptor->getRIFFChunkID()) +{ + mGSReader = new GenericStreamReader(mxf_file, riff_chunk_descriptor->getRIFFChunkStreamID(), vector()); +} + +MXFWaveChunk::~MXFWaveChunk() +{ + delete mGSReader; +} + +uint32_t MXFWaveChunk::Read(unsigned char *data, uint32_t size) +{ + return mGSReader->Read(data, size); +} + +int64_t MXFWaveChunk::Tell() +{ + return mGSReader->Tell(); +} + +int64_t MXFWaveChunk::Size() +{ + int64_t size = mGSReader->Size(); + + if (size > (int64_t)UINT32_MAX) + BMX_EXCEPTION(("Chunk data size in MXF exceeds size that can be represented in a Wave file")); + + return size; +} diff --git a/src/wave/WaveBEXT.cpp b/src/wave/WaveBEXT.cpp index 6d4b6111..7afe1d77 100644 --- a/src/wave/WaveBEXT.cpp +++ b/src/wave/WaveBEXT.cpp @@ -284,6 +284,10 @@ void WaveBEXT::Write(WaveIO *output) if (!mCodingHistory.empty()) output->Write((const unsigned char*)mCodingHistory.c_str(), coding_history_size); + // WORD alignment byte + if ((size & 1)) + output->PutChar(0); + mWasUpdated = false; mWrittenSize = size; } diff --git a/src/wave/WaveCHNA.cpp b/src/wave/WaveCHNA.cpp new file mode 100644 index 00000000..82a6e7c0 --- /dev/null +++ b/src/wave/WaveCHNA.cpp @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include +#include +#include +#include + +using namespace std; +using namespace bmx; + + +WaveCHNA::WaveCHNA() +{ + mNumTracks = 0; + mNumUIDs = 0; +} + +WaveCHNA::~WaveCHNA() +{ + +} + +void WaveCHNA::AppendAudioID(const AudioID &audio_id) +{ + // Recalculate num tracks and UIDs and check the new audio_id isn't a duplicate track_index + UID + uint16_t num_uids = 0; + set track_indexes; + size_t i; + for (i = 0; i < mAudioIDs.size(); i++) { + const AudioID &existing_audio_id = mAudioIDs[i]; + // Tracks indexes start from 1 and so a 0 is a null AudioID + if (existing_audio_id.track_index == 0) + continue; + + if (audio_id.track_index == existing_audio_id.track_index && + memcmp(audio_id.uid, existing_audio_id.uid, sizeof(existing_audio_id.uid)) == 0) + { + log_warn("Ignoring duplicate audio ID with track index %u in CHNA chunk\n", audio_id.track_index); + return; + } + + track_indexes.insert(existing_audio_id.track_index); + num_uids++; + } + + mAudioIDs.push_back(audio_id); + if (audio_id.track_index != 0) { + track_indexes.insert(audio_id.track_index); + num_uids++; + } + + mNumUIDs = num_uids; + mNumTracks = (uint16_t)track_indexes.size(); +} + +uint32_t WaveCHNA::GetSize() +{ + return 4 + mAudioIDs.size() * 40; +} + +vector WaveCHNA::GetAudioIDs(uint16_t track_index) const +{ + vector track_audio_ids; + + size_t i; + for (i = 0; i < mAudioIDs.size(); i++) { + const AudioID &audio_id = mAudioIDs[i]; + if (audio_id.track_index == track_index) + track_audio_ids.push_back(audio_id); + } + + return track_audio_ids; +} + +void WaveCHNA::Write(WaveIO *output) +{ + uint32_t size = GetSize(); + + output->WriteTag("chna"); + output->WriteSize(size); + + output->WriteUInt16(mNumTracks); + output->WriteUInt16(mNumUIDs); + + size_t i; + for (i = 0; i < mAudioIDs.size(); i++) { + const AudioID &audio_id = mAudioIDs[i]; + + output->WriteUInt16(audio_id.track_index); + output->Write(audio_id.uid, sizeof(audio_id.uid)); + output->Write(audio_id.track_ref, sizeof(audio_id.track_ref)); + output->Write(audio_id.pack_ref, sizeof(audio_id.pack_ref)); + output->WriteUInt8(0); // pad byte + } +} + +void WaveCHNA::Read(WaveIO *input, uint32_t size) +{ + mNumTracks = input->ReadUInt16(); + mNumUIDs = input->ReadUInt16(); + + size_t num_audio_ids = (size - 4) / 40; + size_t i; + for (i = 0; i < num_audio_ids; i++) { + AudioID audio_id; + + audio_id.track_index = input->ReadUInt16(); + input->Read(audio_id.uid, sizeof(audio_id.uid)); + input->Read(audio_id.track_ref, sizeof(audio_id.track_ref)); + input->Read(audio_id.pack_ref, sizeof(audio_id.pack_ref)); + input->ReadUInt8(); // pad byte + + mAudioIDs.push_back(audio_id); + } +} diff --git a/src/wave/WaveChunk.cpp b/src/wave/WaveChunk.cpp new file mode 100644 index 00000000..631f8f3a --- /dev/null +++ b/src/wave/WaveChunk.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + +using namespace std; +using namespace bmx; + + +string bmx::get_wave_chunk_tag_str(WaveChunkTag tag) +{ + char buf[5]; + memcpy(buf, &tag, 4); + buf[4] = 0; + + return buf; +} + +bool operator==(const bmx::WaveChunkTag &left, const bmx::WaveChunkTag &right) +{ + return memcmp(&left, &right, sizeof(left)) == 0; +} + +bool operator!=(const bmx::WaveChunkTag &left, const bmx::WaveChunkTag &right) +{ + return memcmp(&left, &right, sizeof(left)) != 0; +} + +bool operator<(const bmx::WaveChunkTag &left, const bmx::WaveChunkTag &right) +{ + return memcmp(&left, &right, sizeof(left)) < 0; +} + +bool operator==(const bmx::WaveChunkTag &left, const char *right) +{ + return left == WAVE_CHUNK_TAG((const unsigned char*)right); +} + +bool operator!=(const bmx::WaveChunkTag &left, const char *right) +{ + return left != WAVE_CHUNK_TAG((const unsigned char*)right); +} + + +WaveChunk::WaveChunk(WaveChunkTag tag) +: BMXIO() +{ + mTag = tag; +} + +WaveChunk::~WaveChunk() +{ +} diff --git a/src/wave/WaveFileChunk.cpp b/src/wave/WaveFileChunk.cpp new file mode 100644 index 00000000..551878d7 --- /dev/null +++ b/src/wave/WaveFileChunk.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Author: Philip de Nier + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +using namespace std; +using namespace bmx; + + +WaveFileChunk::WaveFileChunk(WaveChunkTag tag, BMXIO *file, int64_t offset, uint32_t size) +: WaveChunk(tag) +{ + mFile = file; + mOffset = offset; + mSize = size; + mPosition = 0; +} + +WaveFileChunk::~WaveFileChunk() +{ +} + +uint32_t WaveFileChunk::Read(unsigned char *data, uint32_t size) +{ + if (mPosition >= mSize) + return 0; + + uint32_t to_read = mSize - mPosition; + if (to_read > size) + to_read = size; + + if (mPosition == 0) + mFile->Seek(mOffset, SEEK_SET); + + uint32_t have_read = mFile->Read(data, to_read); + mPosition += have_read; + + return have_read; +} diff --git a/src/wave/WaveIO.cpp b/src/wave/WaveIO.cpp index cec21f93..c742ad5a 100644 --- a/src/wave/WaveIO.cpp +++ b/src/wave/WaveIO.cpp @@ -55,6 +55,11 @@ void WaveIO::WriteTag(const char *tag) Write((const unsigned char*)tag, 4); } +void WaveIO::WriteTag(WaveChunkTag tag) +{ + Write((const unsigned char*)&tag, 4); +} + void WaveIO::WriteZeros(uint32_t size) { static const unsigned char zeros[256] = {0}; @@ -142,7 +147,19 @@ void WaveIO::WriteInt64(int64_t value) PutChar((unsigned char)((((uint64_t)value) >> 56) & 0xff)); } -bool WaveIO::ReadTag(char *tag) +void WaveIO::WriteChunk(WaveChunk *chunk) +{ + WriteTag(chunk->Tag()); + WriteSize(chunk->Size()); + BMXIO::Write(chunk); + + // add pad byte if chunk size is odd + if ((chunk->Size() & 1)) + PutChar(0); +} + + +bool WaveIO::ReadTag(WaveChunkTag *tag) { // could fail if reached eof return Read((unsigned char*)tag, 4) == 4; diff --git a/src/wave/WaveReader.cpp b/src/wave/WaveReader.cpp index 20204bbc..688fbdda 100644 --- a/src/wave/WaveReader.cpp +++ b/src/wave/WaveReader.cpp @@ -47,27 +47,21 @@ using namespace bmx; -static bool tag_equals(const char *left, const char *right) -{ - return memcmp(left, right, 4) == 0; -} - - WaveReader* WaveReader::Open(WaveIO *input, bool take_ownership) { try { - char tag[4]; - if (!input->ReadTag(tag)) { + WaveChunkTag tag; + if (!input->ReadTag(&tag)) { log_error("File is not a Wave file\n"); throw false; } - bool is_rf64; - if (tag_equals(tag, "RIFF")) { - is_rf64 = false; - } else if (tag_equals(tag, "RF64")) { - is_rf64 = true; + bool require_ds64; + if (tag == "RIFF") { + require_ds64 = false; + } else if (tag == "RF64" || tag == "BW64") { + require_ds64 = true; } else { log_error("File is not a Wave file\n"); throw false; @@ -75,12 +69,12 @@ WaveReader* WaveReader::Open(WaveIO *input, bool take_ownership) uint32_t size = input->ReadSize(); - if (!input->ReadTag(tag) || !tag_equals(tag, "WAVE")) { + if (!input->ReadTag(&tag) || tag != "WAVE") { log_error("File is not a Wave file\n"); throw false; } - return new WaveReader(input, take_ownership, is_rf64, size); + return new WaveReader(input, take_ownership, require_ds64, size); } catch (const BMXException &ex) { @@ -98,7 +92,7 @@ WaveReader* WaveReader::Open(WaveIO *input, bool take_ownership) } } -WaveReader::WaveReader(WaveIO *input, bool take_ownership, bool is_rf64, uint32_t riff_size) +WaveReader::WaveReader(WaveIO *input, bool take_ownership, bool require_ds64, uint32_t riff_size) { mInput = input; mOwnInput = take_ownership; @@ -108,13 +102,14 @@ WaveReader::WaveReader(WaveIO *input, bool take_ownership, bool is_rf64, uint32_ mChannelBlockAlign = 0; mBlockAlign = 0; mBEXT = 0; + mCHNA = 0; mSampleCount = 0; mReadStartPosition = 0; mReadDuration = 0; mDataStartFilePosition = 0; mPosition = 0; - ReadChunks(is_rf64, riff_size); + ReadChunks(require_ds64, riff_size); // 1 track per channel uint16_t i; @@ -128,6 +123,7 @@ WaveReader::WaveReader(WaveIO *input, bool take_ownership, bool is_rf64, uint32_ WaveReader::~WaveReader() { delete mBEXT; + delete mCHNA; if (mOwnInput) delete mInput; @@ -166,10 +162,11 @@ uint32_t WaveReader::Read(uint32_t num_samples) return 0; } - // adjust sample count and seek to start of data if needed + // adjust the sample count if needed + // seek if at the start of the data uint32_t first_sample_offset = 0; uint32_t read_num_samples = num_samples; - if (mPosition < mReadStartPosition) { + if (mPosition <= mReadStartPosition) { first_sample_offset = (uint32_t)(mReadStartPosition - mPosition); read_num_samples -= first_sample_offset; Seek(mReadStartPosition); @@ -270,7 +267,24 @@ bool WaveReader::IsEnabled() const return false; } -void WaveReader::ReadChunks(bool is_rf64, uint32_t riff_size) +WaveFileChunk* WaveReader::GetAdditionalChunk(uint32_t index) const +{ + BMX_CHECK(index < mChunks.size()); + return mChunks[index]; +} + +WaveFileChunk* WaveReader::GetAdditionalChunk(WaveChunkTag tag) const +{ + size_t i; + for (i = 0; i < mChunks.size(); i++) { + if (mChunks[i]->Tag() == tag) + return mChunks[i]; + } + + return 0; +} + +void WaveReader::ReadChunks(bool require_ds64, uint32_t riff_size) { (void)riff_size; @@ -279,14 +293,15 @@ void WaveReader::ReadChunks(bool is_rf64, uint32_t riff_size) bool have_fmt = false; bool have_fact = false; bool have_data = false; - char tag[4]; + WaveChunkTag tag; while (true) { - if (!mInput->ReadTag(tag)) + if (!mInput->ReadTag(&tag)) break; - uint32_t size = mInput->ReadSize(); - if (is_rf64 && tag_equals(tag, "ds64")) { + // Use uint64_t for size to allow assignment of actual_data_size and check to skip the WORD alignment byte + uint64_t size = mInput->ReadSize(); + if (require_ds64 && tag == "ds64") { BMX_CHECK(size == 28); mInput->Skip(8); // riff size actual_data_size = mInput->ReadUInt64(); @@ -294,7 +309,7 @@ void WaveReader::ReadChunks(bool is_rf64, uint32_t riff_size) BMX_CHECK(mSampleCount >= 0); mInput->Skip(4); have_ds64 = true; - } else if (tag_equals(tag, "fmt ")) { + } else if (tag == "fmt ") { BMX_CHECK(size >= 16); uint16_t format_category = mInput->ReadUInt16(); if (!(format_category == 1 || format_category == 0xFFFE)) { // PCM @@ -312,31 +327,43 @@ void WaveReader::ReadChunks(bool is_rf64, uint32_t riff_size) if (size > 16) mInput->Skip(size - 16); have_fmt = true; - } else if (tag_equals(tag, "fact")) { + } else if (tag == "fact") { BMX_CHECK(size == 4); - if (is_rf64) { + if (require_ds64) { BMX_CHECK(have_ds64); mInput->Skip(4); } else { mSampleCount = (int64_t)mInput->ReadUInt32(); } have_fact = true; - } else if (tag_equals(tag, "bext")) { + } else if (tag == "bext") { delete mBEXT; mBEXT = new WaveBEXT(); - mBEXT->Read(mInput, size); - } else if (tag_equals(tag, "data")) { + mBEXT->Read(mInput, (uint32_t)size); + } else if (tag == "chna") { + delete mCHNA; + mCHNA = new WaveCHNA(); + mCHNA->Read(mInput, (uint32_t)size); + } else if (tag == "data") { mDataStartFilePosition = mInput->Tell(); - if (is_rf64) { + if (require_ds64) { BMX_CHECK(have_ds64); + size = actual_data_size; } else { actual_data_size = size; } mInput->Skip(actual_data_size); have_data = true; } else { + if (tag != "JUNK") + mChunks.push_back(new WaveFileChunk(tag, mInput, mInput->Tell(), (uint32_t)size)); + mInput->Skip(size); } + + // Skip the WORD alignment byte + if ((size & 1)) + mInput->Skip(1); } if (!have_data) { diff --git a/src/wave/WaveTrackWriter.cpp b/src/wave/WaveTrackWriter.cpp index aaece714..1daaeee6 100644 --- a/src/wave/WaveTrackWriter.cpp +++ b/src/wave/WaveTrackWriter.cpp @@ -49,6 +49,7 @@ WaveTrackWriter::WaveTrackWriter(WaveWriter *writer, uint32_t track_index) { mWriter = writer; mTrackIndex = track_index; + mStartChannel = 0; mChannelCount = 1; mSampleCount = 0; } @@ -92,4 +93,3 @@ int64_t WaveTrackWriter::GetDuration() const { return mWriter->GetDuration(); } - diff --git a/src/wave/WaveWriter.cpp b/src/wave/WaveWriter.cpp index 441d89f3..bde3459b 100644 --- a/src/wave/WaveWriter.cpp +++ b/src/wave/WaveWriter.cpp @@ -36,6 +36,7 @@ #define __STDC_LIMIT_MACROS #include +#include #include #include @@ -58,6 +59,8 @@ WaveWriter::WaveWriter(WaveIO *output, bool take_ownership) mStartTimecodeSet = false; mSetSampleCount = -1; mBEXT = new WaveBEXT(); + mCHNA = 0; + mOwnCHNA = false; mSamplingRate = SAMPLING_RATE_48K; mSamplingRateSet = false; mQuantizationBits = 16; @@ -71,7 +74,8 @@ WaveWriter::WaveWriter(WaveIO *output, bool take_ownership) mBEXTFilePosition = 0; mDataChunkFilePosition = 0; mFactChunkFilePosition = 0; - mUseRF64 = false; + mRequire64Bit = false; + mWriteBW64 = false; mSetSize = -1; mSetDataSize = -1; } @@ -79,6 +83,8 @@ WaveWriter::WaveWriter(WaveIO *output, bool take_ownership) WaveWriter::~WaveWriter() { delete mBEXT; + if (mOwnCHNA) + delete mCHNA; if (mOwnOutput) delete mOutput; @@ -88,6 +94,9 @@ WaveWriter::~WaveWriter() for (i = 0; i < mTracks.size(); i++) delete mTracks[i]; + + for (i = 0; i < mOwnedAdditionalChunks.size(); i++) + delete mOwnedAdditionalChunks[i]; } void WaveWriter::SetStartTimecode(Timecode start_timecode) @@ -101,22 +110,77 @@ void WaveWriter::SetSampleCount(int64_t count) mSetSampleCount = count; } +void WaveWriter::AddCHNA(WaveCHNA *chna, bool take_ownership) +{ + mCHNA = chna; + mOwnCHNA = take_ownership; +} + +void WaveWriter::AddChunk(WaveChunk *chunk, bool take_ownership) +{ + mAdditionalChunks.push_back(chunk); + if (take_ownership) + mOwnedAdditionalChunks.push_back(chunk); +} + WaveTrackWriter* WaveWriter::CreateTrack() { mTracks.push_back(new WaveTrackWriter(this, (uint32_t)mTracks.size())); return mTracks.back(); } -void WaveWriter::PrepareWrite() +void WaveWriter::UpdateChannelCounts() { + mChannelCount = 0; + size_t i; for (i = 0; i < mTracks.size(); i++) { - mTracks[i]->mStartChannel = mChannelCount; - mChannelCount += mTracks[i]->mChannelCount; + WaveTrackWriter *track = mTracks[i]; + + track->mStartChannel = mChannelCount; + mChannelCount += track->mChannelCount; + } +} + +void WaveWriter::PrepareWrite() +{ + static WaveChunkTag builtin_chunks[] = { + WAVE_CHUNK_TAG("JUNK"), WAVE_CHUNK_TAG("ds64"), WAVE_CHUNK_TAG("fmt "), + WAVE_CHUNK_TAG("fact"), WAVE_CHUNK_TAG("bext"), WAVE_CHUNK_TAG("data"), + WAVE_CHUNK_TAG("chna") + }; + set builtin_chunks_set(builtin_chunks, builtin_chunks + BMX_ARRAY_SIZE(builtin_chunks)); + + // Update the channel count and track start channels + UpdateChannelCounts(); + + // Ensure ADM chna chunk is before other chunks. Filter out built-in chunks. + // Write BW64 if there are ADM chunks. + WaveChunk *chna_chunk = 0; + if (mCHNA) + mWriteBW64 = true; + + vector write_chunks; + size_t i; + for (i = 0; i < mAdditionalChunks.size(); i++) { + WaveChunk *chunk = mAdditionalChunks[i]; + + if (chunk->Tag() == "axml" || chunk->Tag() == "bxml" || chunk->Tag() == "sxml") { + mWriteBW64 = true; + write_chunks.push_back(chunk); + } else if (chunk->Tag() == "chna" && !mCHNA) { + // Accept a chna tag passed in using AddChunk() rather than AddCHNA() + // Don't add it to write_chunks here because it needs to be written first + mWriteBW64 = true; + chna_chunk = chunk; + } else if (!builtin_chunks_set.count(chunk->Tag())) { + write_chunks.push_back(chunk); + } } + mBlockAlign = mChannelBlockAlign * mChannelCount; - if (mStartTimecodeSet) { + if (!mWriteBW64 && mStartTimecodeSet) { mBEXT->SetTimeReference(convert_position(mStartTimecode.GetOffset(), mSamplingRate.numerator, mStartTimecode.GetRoundedTCBase(), @@ -125,13 +189,21 @@ void WaveWriter::PrepareWrite() if (mSetSampleCount >= 0) { mSetDataSize = mSetSampleCount * mBlockAlign; - mSetSize = 4 + (8 + 28) + (8 + mBEXT->GetSize()) + (8 + 16) + (8 + 4) + (8 + mSetDataSize); + mSetSize = 4 + (8 + 28) + (8 + 16) + (8 + mSetDataSize); + if (!mWriteBW64) + mSetSize += (8 + 4) + (8 + mBEXT->GetAlignedSize()); // fact and bext chunks + for (i = 0; i < write_chunks.size(); i++) + mSetSize += 8 + write_chunks[i]->AlignedSize(); + if (mSetSize > UINT32_MAX) - mUseRF64 = true; + mRequire64Bit = true; } - if (mUseRF64) { - mOutput->WriteTag("RF64"); + if (mRequire64Bit) { + if (mWriteBW64) + mOutput->WriteTag("BW64"); + else + mOutput->WriteTag("RF64"); mOutput->WriteSize(-1); } else { mOutput->WriteTag("RIFF"); @@ -143,12 +215,15 @@ void WaveWriter::PrepareWrite() mOutput->WriteTag("WAVE"); mJunkChunkFilePosition = mOutput->Tell(); - if (mUseRF64) { + if (mRequire64Bit) { mOutput->WriteTag("ds64"); mOutput->WriteSize(28); mOutput->WriteUInt64((uint64_t)mSetSize); mOutput->WriteUInt64((uint64_t)mSetDataSize); - mOutput->WriteUInt64((uint64_t)mSetSampleCount); + if (mWriteBW64) + mOutput->WriteUInt64(0); // dummy / not used + else + mOutput->WriteUInt64((uint64_t)mSetSampleCount); mOutput->WriteUInt32(0); } else { mOutput->WriteTag("JUNK"); @@ -156,8 +231,10 @@ void WaveWriter::PrepareWrite() mOutput->WriteZeros(28); } - mBEXTFilePosition = mOutput->Tell(); - mBEXT->Write(mOutput); + if (!mWriteBW64) { + mBEXTFilePosition = mOutput->Tell(); + mBEXT->Write(mOutput); + } mOutput->WriteTag("fmt "); mOutput->WriteSize(16); @@ -168,19 +245,29 @@ void WaveWriter::PrepareWrite() mOutput->WriteUInt16(mBlockAlign); mOutput->WriteUInt16(mQuantizationBits); - mFactChunkFilePosition = mOutput->Tell(); - mOutput->WriteTag("fact"); - mOutput->WriteSize(4); - if (mUseRF64) - mOutput->WriteUInt32((uint32_t)(-1)); - else if (mSetSampleCount >= 0) - mOutput->WriteUInt32((uint32_t)mSetSampleCount); - else - mOutput->WriteUInt32(0); + if (!mWriteBW64) { + mFactChunkFilePosition = mOutput->Tell(); + mOutput->WriteTag("fact"); + mOutput->WriteSize(4); + if (mRequire64Bit) + mOutput->WriteUInt32((uint32_t)(-1)); + else if (mSetSampleCount >= 0) + mOutput->WriteUInt32((uint32_t)mSetSampleCount); + else + mOutput->WriteUInt32(0); + } + + if (mCHNA) + mCHNA->Write(mOutput); + else if (chna_chunk) + mOutput->WriteChunk(chna_chunk); + + for (i = 0; i < write_chunks.size(); i++) + mOutput->WriteChunk(write_chunks[i]); mDataChunkFilePosition = mOutput->Tell(); mOutput->WriteTag("data"); - if (mUseRF64) + if (mRequire64Bit) mOutput->WriteSize(-1); else if (mSetDataSize >= 0) mOutput->WriteSize((uint32_t)mSetDataSize); @@ -289,7 +376,7 @@ void WaveWriter::CompleteWrite() mBufferSegments.clear(); } - if (mStartTimecodeSet) { + if (!mWriteBW64 && mStartTimecodeSet) { mBEXT->SetTimeReference(convert_position(mStartTimecode.GetOffset(), mSamplingRate.numerator, mStartTimecode.GetRoundedTCBase(), @@ -304,21 +391,23 @@ void WaveWriter::CompleteWrite() if ((data_size & 1)) mOutput->PutChar(0); - if (mUseRF64 || riff_size > UINT32_MAX) { - if (!mUseRF64) { + if (mRequire64Bit || riff_size > UINT32_MAX) { + if (!mRequire64Bit) { mOutput->Seek(mDataChunkFilePosition + 4, SEEK_SET); mOutput->WriteSize((uint32_t)(-1)); - mOutput->Seek(mFactChunkFilePosition + 8, SEEK_SET); - mOutput->WriteUInt32((uint32_t)(-1)); + if (!mWriteBW64) { + mOutput->Seek(mFactChunkFilePosition + 8, SEEK_SET); + mOutput->WriteUInt32((uint32_t)(-1)); + } } - if (mBEXT->WasUpdated()) { + if (!mWriteBW64 && mBEXT->WasUpdated()) { mOutput->Seek(mBEXTFilePosition, SEEK_SET); mBEXT->Write(mOutput); } - if (!mUseRF64 || riff_size != mSetSize || mSampleCount != mSetSampleCount) { + if (!mRequire64Bit || riff_size != mSetSize || mSampleCount != mSetSampleCount) { mOutput->Seek(mJunkChunkFilePosition, SEEK_SET); mOutput->WriteTag("ds64"); mOutput->WriteSize(28); @@ -328,9 +417,12 @@ void WaveWriter::CompleteWrite() mOutput->WriteUInt32(0); } - if (!mUseRF64) { + if (!mRequire64Bit) { mOutput->Seek(0, SEEK_SET); - mOutput->WriteTag("RF64"); + if (mWriteBW64) + mOutput->WriteTag("BW64"); + else + mOutput->WriteTag("RF64"); mOutput->WriteSize((uint32_t)(-1)); } } else { @@ -339,14 +431,16 @@ void WaveWriter::CompleteWrite() mOutput->WriteSize((uint32_t)data_size); } - if (mSampleCount != mSetSampleCount) { - mOutput->Seek(mFactChunkFilePosition + 8, SEEK_SET); - mOutput->WriteUInt32((uint32_t)mSampleCount); - } + if (!mWriteBW64) { + if (mSampleCount != mSetSampleCount) { + mOutput->Seek(mFactChunkFilePosition + 8, SEEK_SET); + mOutput->WriteUInt32((uint32_t)mSampleCount); + } - if (mBEXT->WasUpdated()) { - mOutput->Seek(mBEXTFilePosition, SEEK_SET); - mBEXT->Write(mOutput); + if (mBEXT->WasUpdated()) { + mOutput->Seek(mBEXTFilePosition, SEEK_SET); + mBEXT->Write(mOutput); + } } if (riff_size != mSetSize) { From 58889db576b063520a9873a247b91a554c342855 Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Thu, 19 Jan 2023 09:16:04 +0000 Subject: [PATCH 13/65] Add initial Wave ADM regression tests --- apps/bmxtranswrap/bmxtranswrap.cpp | 9 +- apps/raw2bmx/raw2bmx.cpp | 25 ++- include/bmx/wave/WaveTrackWriter.h | 3 + include/bmx/wave/WaveWriter.h | 2 + src/clip_writer/ClipWriter.cpp | 11 +- src/clip_writer/ClipWriterTrack.cpp | 4 +- src/wave/WaveTrackWriter.cpp | 9 + src/wave/WaveWriter.cpp | 13 ++ test/wave_adm/adm_1.wav | Bin 0 -> 25058 bytes test/wave_adm/axml_1.xml | 33 ++++ test/wave_adm/test.sh | 248 +++++++++++++++++++++++++ test/wave_adm/test_mxf_1.md5 | 1 + test/wave_adm/test_mxf_2.md5 | 1 + test/wave_adm/test_mxf_3.md5 | 1 + test/wave_adm/test_mxf_4.md5 | 1 + test/wave_adm/test_wave_1.md5 | 1 + test/wave_adm/test_wave_2.md5 | 1 + test/wave_adm/test_wave_3.md5 | 1 + test/wave_adm/test_wave_4.md5 | 1 + test/wave_adm/test_wave_5.md5 | 1 + test/wave_adm/test_wave_from_mxf_1.md5 | 1 + 21 files changed, 347 insertions(+), 20 deletions(-) create mode 100644 test/wave_adm/adm_1.wav create mode 100644 test/wave_adm/axml_1.xml create mode 100755 test/wave_adm/test.sh create mode 100644 test/wave_adm/test_mxf_1.md5 create mode 100644 test/wave_adm/test_mxf_2.md5 create mode 100644 test/wave_adm/test_mxf_3.md5 create mode 100644 test/wave_adm/test_mxf_4.md5 create mode 100644 test/wave_adm/test_wave_1.md5 create mode 100644 test/wave_adm/test_wave_2.md5 create mode 100644 test/wave_adm/test_wave_3.md5 create mode 100644 test/wave_adm/test_wave_4.md5 create mode 100644 test/wave_adm/test_wave_5.md5 create mode 100644 test/wave_adm/test_wave_from_mxf_1.md5 diff --git a/apps/bmxtranswrap/bmxtranswrap.cpp b/apps/bmxtranswrap/bmxtranswrap.cpp index 79f21e03..96397f9e 100644 --- a/apps/bmxtranswrap/bmxtranswrap.cpp +++ b/apps/bmxtranswrap/bmxtranswrap.cpp @@ -4397,7 +4397,6 @@ int main(int argc, const char** argv) // Loop over the Wave output tracks and add referenced chunks to the Wave file. // Construct the output chna chunk based on the track mapping - WaveCHNA *output_chna = 0; size_t i; for (i = 0; i < output_tracks.size(); i++) { OutputTrack *output_track = output_tracks[i]; @@ -4438,18 +4437,12 @@ int main(int argc, const char** argv) for (k = 0; k < audio_ids.size(); k++) { WaveCHNA::AudioID &audio_id = audio_ids[k]; - if (!output_chna) - output_chna = new WaveCHNA(); - // + 1 because the chna track_index starts at 1 audio_id.track_index = wave_track->GetStartChannel() + output_channel_index + 1; - output_chna->AppendAudioID(audio_id); + wave_track->AddADMAudioID(audio_id); } } } - - if (output_chna) - wave_clip->AddCHNA(output_chna, true); } diff --git a/apps/raw2bmx/raw2bmx.cpp b/apps/raw2bmx/raw2bmx.cpp index 461a4fd4..d68c442f 100644 --- a/apps/raw2bmx/raw2bmx.cpp +++ b/apps/raw2bmx/raw2bmx.cpp @@ -5731,7 +5731,13 @@ int main(int argc, const char** argv) // Add ADM Wave chunks and references - if (clip_type == CW_OP1A_CLIP_TYPE) { + if (clip_type == CW_OP1A_CLIP_TYPE || clip_type == CW_WAVE_CLIP_TYPE) { + if (clip_type == CW_WAVE_CLIP_TYPE) { + // Ensure that the start channels are up-to-date for each track + WaveWriter *wave_clip = clip->GetWaveClip(); + wave_clip->UpdateChannelCounts(); + } + // Get the output tracks and referenced Wave file inputs that contain ADM chunks // Only allow a single Wave with ADM for each output track to ensure that references between // the ADM chunks and channels remain unambiguous @@ -5787,8 +5793,10 @@ int main(int argc, const char** argv) } if (!output_tracks_using_adm.empty()) { - // Add ADM chunks to the clip + // These refs are only used in MXF. It is ignored for Wave map > input_chunk_refs; + + // Add ADM chunks to the clip set::const_iterator iter; for (iter = wave_adm_inputs.begin(); iter != wave_adm_inputs.end(); iter++) { RawInput *input = *iter; @@ -5812,11 +5820,13 @@ int main(int argc, const char** argv) ClipWriterTrack *clip_track = output_track->GetClipTrack(); - // Add generic stream ID references to the chunks to the clip track - const vector &chunk_refs = input_chunk_refs[wave_adm_input]; - size_t k; - for (k = 0; k < chunk_refs.size(); k++) - clip_track->AddWaveChunkReference(chunk_refs[k]); + if (clip_type != CW_WAVE_CLIP_TYPE) { + // Add generic stream ID references to the chunks to the MXF clip track + const vector &chunk_refs = input_chunk_refs[wave_adm_input]; + size_t k; + for (k = 0; k < chunk_refs.size(); k++) + clip_track->AddWaveChunkReference(chunk_refs[k]); + } // Add chna AudioIDs to the clip track. // Use the input to output channel mapping to set the chna track_index @@ -5831,6 +5841,7 @@ int main(int argc, const char** argv) // + 1 below because ADM track (channel) indexes start at 1 uint32_t input_channel_index = iter->second.input_channel_index; vector audio_ids = input_chna->GetAudioIDs(input_channel_index + 1); + size_t k; for (k = 0; k < audio_ids.size(); k++) { WaveCHNA::AudioID &audio_id = audio_ids[k]; diff --git a/include/bmx/wave/WaveTrackWriter.h b/include/bmx/wave/WaveTrackWriter.h index 78c217be..b4a17d42 100644 --- a/include/bmx/wave/WaveTrackWriter.h +++ b/include/bmx/wave/WaveTrackWriter.h @@ -34,6 +34,7 @@ #include +#include @@ -55,6 +56,8 @@ class WaveTrackWriter void SetQuantizationBits(uint16_t bits); // default 16 void SetChannelCount(uint16_t count); // default 1 + void AddADMAudioID(const WaveCHNA::AudioID &audio_id); + public: void WriteSamples(const unsigned char *data, uint32_t size, uint32_t num_samples); diff --git a/include/bmx/wave/WaveWriter.h b/include/bmx/wave/WaveWriter.h index 8a0a359b..a95876ef 100644 --- a/include/bmx/wave/WaveWriter.h +++ b/include/bmx/wave/WaveWriter.h @@ -65,6 +65,8 @@ class WaveWriter void AddCHNA(WaveCHNA *chna, bool take_ownership); void AddChunk(WaveChunk *chunk, bool take_ownership); + void AddADMAudioID(const WaveCHNA::AudioID &audio_id); + public: WaveTrackWriter* CreateTrack(); diff --git a/src/clip_writer/ClipWriter.cpp b/src/clip_writer/ClipWriter.cpp index f3da9450..46a80940 100644 --- a/src/clip_writer/ClipWriter.cpp +++ b/src/clip_writer/ClipWriter.cpp @@ -332,25 +332,28 @@ void ClipWriter::ForceWriteCBEDuration0(bool enable) uint32_t ClipWriter::AddWaveChunk(WaveChunk *chunk, bool take_ownership) { - uint32_t stream_id = 0; + uint32_t id = 0; switch (mType) { case CW_OP1A_CLIP_TYPE: - stream_id = mOP1AClip->AddWaveChunk(chunk, take_ownership); + id = mOP1AClip->AddWaveChunk(chunk, take_ownership); + break; + case CW_WAVE_CLIP_TYPE: + mWaveClip->AddChunk(chunk, take_ownership); + // No id and so 0 is always returned break; case CW_D10_CLIP_TYPE: case CW_RDD9_CLIP_TYPE: case CW_AS02_CLIP_TYPE: case CW_AVID_CLIP_TYPE: - case CW_WAVE_CLIP_TYPE: break; case CW_UNKNOWN_CLIP_TYPE: BMX_ASSERT(false); break; } - return stream_id; + return id; } ClipWriterTrack* ClipWriter::CreateTrack(EssenceType essence_type, string track_filename) diff --git a/src/clip_writer/ClipWriterTrack.cpp b/src/clip_writer/ClipWriterTrack.cpp index 0891b579..08caef17 100644 --- a/src/clip_writer/ClipWriterTrack.cpp +++ b/src/clip_writer/ClipWriterTrack.cpp @@ -1158,11 +1158,13 @@ void ClipWriterTrack::AddADMAudioID(const WaveCHNA::AudioID &audio_id) pcm_track->AddADMAudioID(audio_id); break; } + case CW_WAVE_CLIP_TYPE: + mWaveTrack->AddADMAudioID(audio_id); + break; case CW_D10_CLIP_TYPE: case CW_RDD9_CLIP_TYPE: case CW_AS02_CLIP_TYPE: case CW_AVID_CLIP_TYPE: - case CW_WAVE_CLIP_TYPE: break; case CW_UNKNOWN_CLIP_TYPE: BMX_ASSERT(false); diff --git a/src/wave/WaveTrackWriter.cpp b/src/wave/WaveTrackWriter.cpp index 1daaeee6..bea7b368 100644 --- a/src/wave/WaveTrackWriter.cpp +++ b/src/wave/WaveTrackWriter.cpp @@ -74,6 +74,15 @@ void WaveTrackWriter::SetChannelCount(uint16_t count) mChannelCount = count; } +void WaveTrackWriter::AddADMAudioID(const WaveCHNA::AudioID &audio_id) +{ + // Adjust the track_index in this track to a track_index in the whole clip + WaveCHNA::AudioID clip_audio_id = audio_id; + clip_audio_id.track_index += mStartChannel; + + mWriter->AddADMAudioID(clip_audio_id); +} + void WaveTrackWriter::WriteSamples(const unsigned char *data, uint32_t size, uint32_t num_samples) { mWriter->WriteSamples(mTrackIndex, data, size, num_samples); diff --git a/src/wave/WaveWriter.cpp b/src/wave/WaveWriter.cpp index bde3459b..f14dafbd 100644 --- a/src/wave/WaveWriter.cpp +++ b/src/wave/WaveWriter.cpp @@ -112,6 +112,9 @@ void WaveWriter::SetSampleCount(int64_t count) void WaveWriter::AddCHNA(WaveCHNA *chna, bool take_ownership) { + if (mOwnCHNA) + delete mCHNA; + mCHNA = chna; mOwnCHNA = take_ownership; } @@ -123,6 +126,16 @@ void WaveWriter::AddChunk(WaveChunk *chunk, bool take_ownership) mOwnedAdditionalChunks.push_back(chunk); } +void WaveWriter::AddADMAudioID(const WaveCHNA::AudioID &audio_id) +{ + if (!mCHNA) { + mCHNA = new WaveCHNA(); + mOwnCHNA = true; + } + + mCHNA->AppendAudioID(audio_id); +} + WaveTrackWriter* WaveWriter::CreateTrack() { mTracks.push_back(new WaveTrackWriter(this, (uint32_t)mTracks.size())); diff --git a/test/wave_adm/adm_1.wav b/test/wave_adm/adm_1.wav new file mode 100644 index 0000000000000000000000000000000000000000..7f116bb3251e5ff010463ea24f361baf0494d2c7 GIT binary patch literal 25058 zcmeIz%}(1u5C`xDQc5X@9((9vwRf7tduKN@v%h$|=k4}S$=FBd!`Yku#oJeG{pZSy`3nl! zU={ZDJ6-(PVSDT)8(sVI8{JmuZ-Y6#{-CBmb*GnH)|3B1t?qQpoy9hbaaJB@mEyLF zaR+%^dA&+8u93%;*ORy2^w&0H_Ay=XFDi^Cf!`GM*EPYFKMLH5KW>VCuf2aLj$6C7 z8qQCGP`#HEpVJIKYKnR2AJO9@PsP%evD}YF*UFR0vm|t2)#?qA1RqUhvY7HkYnO9- zl&q7@NgmLnt044btZ(R6&fQ7SPM@9K#>#h8YmZsVL@Wx6+$U75^jV9i=*#V~SJ$IL$XnF!|`LP6D42iqB8G>Z;|OT&7=S zSJNbx#?r#>nrW?_nGG&#EB7G#K3(PF%c=e>t*riRL{}fpl)RzcULL!v>dWD0H8Mpn z)m$7|l)PNkKc;Ohr>4_R`b#X;APVNb8?D%wVj@nOqG@h%>X z>-5}-oCf1Lr5CGE1%jIg^ov@NYe$Z5H1Et&{z5Q&UW!=cZ5;MOis)z43vZfiesTD| zb4|Zi&dt`uS{QM_ldTQCFiv?w?!M%vGm= zUCqx6ySjXw*ww;G)k=;f_K8mF&8^Cl?Wa4>cAxLz8hwBP7=Qs7fB_hQ0T_S*7=Qs7 zfB_hQ0T_S*7=Qs7fB_hQ0T_S*7=Qs7fB_hQ0T_S*7=Qs7fB_hQ0T_S*7=Qs7fB_hQ z0T_S*7=Qs7fB_hQ0T_S*7=Qs7fB_hQ0T_S*7=Qs7fB_hQ0T_S*7=Qs7fB_hQ0T_S* Q7=Qs7fB_hQfrlIT4WA>92><{9 literal 0 HcmV?d00001 diff --git a/test/wave_adm/axml_1.xml b/test/wave_adm/axml_1.xml new file mode 100644 index 00000000..4460ec08 --- /dev/null +++ b/test/wave_adm/axml_1.xml @@ -0,0 +1,33 @@ + + + + + + + ACO_1001 + ACO_1002 + + + AO_1001 + + + AO_1002 + + + AP_00010002 + ATU_00000001 + ATU_00000002 + + + AP_00010002 + ATU_00000003 + ATU_00000004 + + + + + + + + + \ No newline at end of file diff --git a/test/wave_adm/test.sh b/test/wave_adm/test.sh new file mode 100755 index 00000000..608ec905 --- /dev/null +++ b/test/wave_adm/test.sh @@ -0,0 +1,248 @@ +#!/bin/sh + +base=$(dirname $0) + +md5tool=../file_md5 + +testdir=.. +appsdir=../../apps +tmpdir=/tmp/wave_adm_temp$$ +sampledir=/tmp/ + +create_mxf_1() +{ + # Create an MXF from a Wave+ADM and AVC-Intra. + # Map the audio channels to 2 stereo tracks, + # with the stereo tracks in reverse order. + + $testdir/create_test_essence -t 7 -d 1 $tmpdir/video + + $appsdir/raw2bmx/raw2bmx \ + --regtest \ + -t op1a \ + -f 25 \ + -o $1 \ + --track-map "2,3;0,1" \ + --avci100_1080i $tmpdir/video \ + --wave $base/adm_1.wav \ + >/dev/null +} + +create_mxf_2() +{ + # Create an MXF from a Wave+ADM and AVC-Intra. + # Map only audio 2 channels to a stereo track, + # with the channels in reverse order. + + $testdir/create_test_essence -t 7 -d 1 $tmpdir/video + + $appsdir/raw2bmx/raw2bmx \ + --regtest \ + -t op1a \ + -f 25 \ + -o $1 \ + --track-map "3,2" \ + --avci100_1080i $tmpdir/video \ + --wave $base/adm_1.wav \ + >/dev/null +} + +create_mxf_3() +{ + # Create an MXF from a Wave+ADM and AVC-Intra. + # Map only audio 2 channels to 2 stereo tracks, + # with a silence channel in each track. + + $testdir/create_test_essence -t 7 -d 1 $tmpdir/video + + $appsdir/raw2bmx/raw2bmx \ + --regtest \ + -t op1a \ + -f 25 \ + -o $1 \ + --track-map "0,s1;s1,1" \ + --avci100_1080i $tmpdir/video \ + --wave $base/adm_1.wav \ + >/dev/null +} + +create_wave_1() +{ + # Create a Wave file from mxf_1 and map the channels + # back into the original order in adm_1.wav. + + $appsdir/bmxtranswrap/bmxtranswrap \ + --regtest \ + -t wave \ + -o $2 \ + --track-map "2,3,0,1" \ + $1 \ + >/dev/null +} + +create_wave_2() +{ + # Create a Wave file from mxf_1 and only map 2 channels back + # into the original order in adm_1.wav. + + $appsdir/bmxtranswrap/bmxtranswrap \ + --regtest \ + -t wave \ + -o $2 \ + --track-map "2,3" \ + $1 \ + >/dev/null +} + +create_wave_3() +{ + # Create a Wave file from mxf_3, including the 2 silence channels, + # and map the 2 channels back into the original order in adm_1.wav. + + $appsdir/bmxtranswrap/bmxtranswrap \ + --regtest \ + -t wave \ + -o $2 \ + --track-map "0,3,1,2" \ + $1 \ + >/dev/null +} + +create_wave_4() +{ + # Create a Wave file from mxf_3 with no ADM channels mapped. + + $appsdir/bmxtranswrap/bmxtranswrap \ + --regtest \ + -t wave \ + -o $2 \ + --track-map "1,2" \ + $1 \ + >/dev/null +} + +create_wave_5() +{ + # Create a Wave file from the sample Wave+ADM file. + + $appsdir/raw2bmx/raw2bmx \ + --regtest \ + -t wave \ + -o $1 \ + --wave $base/adm_1.wav \ + >/dev/null +} + +create_mxf_4() +{ + # Create an MXF from wave_3 including only silence (non-ADM) channels. + + $appsdir/raw2bmx/raw2bmx \ + --regtest \ + -t op1a \ + -o $2 \ + --track-map "2,3" \ + --wave $1 \ + >/dev/null +} + + +check() +{ + create_mxf_1 $tmpdir/test_mxf_1.mxf && + $md5tool < $tmpdir/test_mxf_1.mxf > $tmpdir/test.md5 && + diff $tmpdir/test.md5 $base/test_mxf_1.md5 && + create_mxf_2 $tmpdir/test_mxf_2.mxf && + $md5tool < $tmpdir/test_mxf_2.mxf > $tmpdir/test.md5 && + diff $tmpdir/test.md5 $base/test_mxf_2.md5 && + create_mxf_3 $tmpdir/test_mxf_3.mxf && + $md5tool < $tmpdir/test_mxf_3.mxf > $tmpdir/test.md5 && + diff $tmpdir/test.md5 $base/test_mxf_3.md5 && + create_wave_1 $tmpdir/test_mxf_1.mxf $tmpdir/test.wav && + $md5tool < $tmpdir/test.wav > $tmpdir/test.md5 && + diff $tmpdir/test.md5 $base/test_wave_1.md5 && + diff $tmpdir/test.wav $base/adm_1.wav && + create_wave_2 $tmpdir/test_mxf_1.mxf $tmpdir/test.wav && + $md5tool < $tmpdir/test.wav > $tmpdir/test.md5 && + diff $tmpdir/test.md5 $base/test_wave_2.md5 && + create_wave_3 $tmpdir/test_mxf_3.mxf $tmpdir/test_wav_3.wav && + $md5tool < $tmpdir/test_wav_3.wav > $tmpdir/test.md5 && + diff $tmpdir/test.md5 $base/test_wave_3.md5 && + create_wave_4 $tmpdir/test_mxf_3.mxf $tmpdir/test.wav && + $md5tool < $tmpdir/test.wav > $tmpdir/test.md5 && + diff $tmpdir/test.md5 $base/test_wave_4.md5 && + create_wave_5 $tmpdir/test.wav && + $md5tool < $tmpdir/test.wav > $tmpdir/test.md5 && + diff $tmpdir/test.md5 $base/test_wave_5.md5 && + diff $tmpdir/test.wav $base/adm_1.wav && + create_mxf_4 $tmpdir/test_wav_3.wav $tmpdir/test.mxf && + $md5tool < $tmpdir/test.mxf > $tmpdir/test.md5 && + diff $tmpdir/test.md5 $base/test_mxf_4.md5 +} + +create_data() +{ + create_mxf_1 $tmpdir/test_mxf_1.mxf && + $md5tool < $tmpdir/test_mxf_1.mxf > $base/test_mxf_1.md5 && + create_mxf_2 $tmpdir/test_mxf_2.mxf && + $md5tool < $tmpdir/test_mxf_2.mxf > $base/test_mxf_2.md5 && + create_mxf_3 $tmpdir/test_mxf_3.mxf && + $md5tool < $tmpdir/test_mxf_3.mxf > $base/test_mxf_3.md5 && + create_wave_1 $tmpdir/test_mxf_1.mxf $tmpdir/test.wav && + $md5tool < $tmpdir/test.wav > $base/test_wave_1.md5 && + create_wave_2 $tmpdir/test_mxf_1.mxf $tmpdir/test.wav && + $md5tool < $tmpdir/test.wav > $base/test_wave_2.md5 && + create_wave_3 $tmpdir/test_mxf_3.mxf $tmpdir/test_wave_3.wav && + $md5tool < $tmpdir/test_wave_3.wav > $base/test_wave_3.md5 && + create_wave_4 $tmpdir/test_mxf_3.mxf $tmpdir/test.wav && + $md5tool < $tmpdir/test.wav > $base/test_wave_4.md5 && + create_wave_5 $tmpdir/test.wav && + $md5tool < $tmpdir/test.wav > $base/test_wave_5.md5 && + create_mxf_4 $tmpdir/test_wave_3.wav $tmpdir/test.mxf && + $md5tool < $tmpdir/test.mxf > $base/test_mxf_4.md5 +} + +create_samples() +{ + create_mxf_1 $sampledir/test_mxf_1.mxf && + create_mxf_2 $sampledir/test_mxf_2.mxf && + create_mxf_3 $sampledir/test_mxf_3.mxf && + create_wave_1 $sampledir/test_mxf_1.mxf $sampledir/test_wave_1.wav && + create_wave_2 $sampledir/test_mxf_1.mxf $sampledir/test_wave_2.wav && + create_wave_3 $sampledir/test_mxf_3.mxf $sampledir/test_wave_3.wav && + create_wave_4 $sampledir/test_mxf_3.mxf $sampledir/test_wave_4.wav && + create_wave_5 $sampledir/test_wave_5.wav && + create_mxf_4 $sampledir/test_wave_3.wav $sampledir/test_mxf_4.mxf +} + + +check_all() +{ + check +} + +create_data_all() +{ + create_data +} + +create_samples_all() +{ + create_samples +} + + +mkdir -p $tmpdir + +if test "$1" = "create_data" ; then + create_data_all +elif test "$1" = "create_samples" ; then + create_samples_all +else + check_all +fi +res=$? + +rm -Rf $tmpdir + +exit $res diff --git a/test/wave_adm/test_mxf_1.md5 b/test/wave_adm/test_mxf_1.md5 new file mode 100644 index 00000000..d67396c2 --- /dev/null +++ b/test/wave_adm/test_mxf_1.md5 @@ -0,0 +1 @@ +35e48e7f62efc6621982483adcf55ef2 - diff --git a/test/wave_adm/test_mxf_2.md5 b/test/wave_adm/test_mxf_2.md5 new file mode 100644 index 00000000..80e9f04a --- /dev/null +++ b/test/wave_adm/test_mxf_2.md5 @@ -0,0 +1 @@ +dc5765741331ad812fcbef7a09d79483 - diff --git a/test/wave_adm/test_mxf_3.md5 b/test/wave_adm/test_mxf_3.md5 new file mode 100644 index 00000000..aa6dee01 --- /dev/null +++ b/test/wave_adm/test_mxf_3.md5 @@ -0,0 +1 @@ +1a324812b106b511ff60ff048b1fea0b - diff --git a/test/wave_adm/test_mxf_4.md5 b/test/wave_adm/test_mxf_4.md5 new file mode 100644 index 00000000..5f431a3a --- /dev/null +++ b/test/wave_adm/test_mxf_4.md5 @@ -0,0 +1 @@ +786546818c2696bf69812e66c37e5a22 - diff --git a/test/wave_adm/test_wave_1.md5 b/test/wave_adm/test_wave_1.md5 new file mode 100644 index 00000000..8f1ff90d --- /dev/null +++ b/test/wave_adm/test_wave_1.md5 @@ -0,0 +1 @@ +af9c5363ca67c94abec8c953533c2e6a - diff --git a/test/wave_adm/test_wave_2.md5 b/test/wave_adm/test_wave_2.md5 new file mode 100644 index 00000000..1014b55c --- /dev/null +++ b/test/wave_adm/test_wave_2.md5 @@ -0,0 +1 @@ +0e4ab7c53bae594e25c03402f69f8186 - diff --git a/test/wave_adm/test_wave_3.md5 b/test/wave_adm/test_wave_3.md5 new file mode 100644 index 00000000..de0a03dc --- /dev/null +++ b/test/wave_adm/test_wave_3.md5 @@ -0,0 +1 @@ +6b65bb005ed842aa5107d5be43af2b5b - diff --git a/test/wave_adm/test_wave_4.md5 b/test/wave_adm/test_wave_4.md5 new file mode 100644 index 00000000..e31edb68 --- /dev/null +++ b/test/wave_adm/test_wave_4.md5 @@ -0,0 +1 @@ +4103eed5f9cb826552e3e14f1bcfbddb - diff --git a/test/wave_adm/test_wave_5.md5 b/test/wave_adm/test_wave_5.md5 new file mode 100644 index 00000000..8f1ff90d --- /dev/null +++ b/test/wave_adm/test_wave_5.md5 @@ -0,0 +1 @@ +af9c5363ca67c94abec8c953533c2e6a - diff --git a/test/wave_adm/test_wave_from_mxf_1.md5 b/test/wave_adm/test_wave_from_mxf_1.md5 new file mode 100644 index 00000000..c6c58cc0 --- /dev/null +++ b/test/wave_adm/test_wave_from_mxf_1.md5 @@ -0,0 +1 @@ +cb62a7695d4c9ffbe474dced59f434a2 - From eee2b71fad49b348e97dd42ac87fe5df06ff7fa5 Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Thu, 19 Jan 2023 09:18:30 +0000 Subject: [PATCH 14/65] Add support for ADM in raw2bmx wave -> wave --- apps/raw2bmx/raw2bmx.cpp | 75 ++++++++++- include/bmx/apps/ADMCHNATextFileHelper.h | 49 +++++++ include/bmx/wave/WaveCHNA.h | 3 + include/bmx/wave/WaveChunk.h | 2 +- include/bmx/wave/WaveWriter.h | 7 +- src/apps/ADMCHNATextFileHelper.cpp | 157 +++++++++++++++++++++++ src/wave/WaveWriter.cpp | 42 ++++-- test/create_test_essence.cpp | 2 +- test/wave_adm/chna_1.txt | 19 +++ test/wave_adm/test.sh | 28 ++++ test/wave_adm/test_wave_6.md5 | 1 + 11 files changed, 370 insertions(+), 15 deletions(-) create mode 100644 include/bmx/apps/ADMCHNATextFileHelper.h create mode 100644 src/apps/ADMCHNATextFileHelper.cpp create mode 100644 test/wave_adm/chna_1.txt create mode 100644 test/wave_adm/test_wave_6.md5 diff --git a/apps/raw2bmx/raw2bmx.cpp b/apps/raw2bmx/raw2bmx.cpp index d68c442f..b82c89ec 100644 --- a/apps/raw2bmx/raw2bmx.cpp +++ b/apps/raw2bmx/raw2bmx.cpp @@ -68,7 +68,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -76,6 +78,7 @@ #include #include #include +#include #include #include #include @@ -118,6 +121,12 @@ typedef struct AvidLocator locator; } LocatorOption; +typedef struct +{ + const char *filename; + WaveChunkTag tag; +} WaveChunkData; + struct RawInput { bool disabled; @@ -605,7 +614,11 @@ static void usage(const char *cmd) printf(" --force-no-avci-head Strip AVCI header (512 bytes, sequence and picture parameter sets) if present\n"); printf("\n"); printf(" wave:\n"); - printf(" --orig Set originator in the output Wave bext chunk. Default '%s'\n", DEFAULT_BEXT_ORIGINATOR); + printf(" --orig Set originator in the output Wave bext chunk. Default '%s'\n", DEFAULT_BEXT_ORIGINATOR); + printf(" --wave-chunk-data Add a chunk to the output Wave file that has chunk data (not including tag and size) from and \n"); + printf(" This chunk will override any non-builtin and 'chna' chunk originating from the input Wave files\n"); + printf(" --chna-audio-ids Add a 'chna' chunk to the output Wave file which is defined in the text \n"); + printf(" This chunk will override any 'chna' chunk originating from the input Wave files\n"); printf("\n"); printf(" as02/op1a/as11op1a:\n"); printf(" --use-avc-subdesc Use the AVC sub-descriptor rather than the MPEG video descriptor for AVC-Intra tracks\n"); @@ -958,6 +971,8 @@ int main(int argc, const char** argv) BMX_OPT_PROP_DECL_DEF(uint32_t, head_fill, 0); mxfThreeColorPrimaries three_color_primaries; mxfColorPrimary color_primary; + vector wave_chunk_datas; + const char *chna_audio_ids_file = 0; bool real_essence_regtest = false; int value, num, den; unsigned int uvalue; @@ -1814,6 +1829,41 @@ int main(int argc, const char** argv) originator = argv[cmdln_index + 1]; cmdln_index++; } + else if (strcmp(argv[cmdln_index], "--wave-chunk-data") == 0) + { + if (cmdln_index + 2 >= argc) + { + usage(argv[0]); + fprintf(stderr, "Missing argument(s) for option '%s'\n", argv[cmdln_index]); + return 1; + } + if (argv[cmdln_index + 2][0] == 0 || strlen(argv[cmdln_index + 2]) > 4) { + usage(argv[0]); + fprintf(stderr, "Invalid Wave chunk tag '%s' for option '%s'\n", argv[cmdln_index + 2], argv[cmdln_index]); + return 1; + } + + string tag_str = argv[cmdln_index + 2]; + tag_str.resize(4); + + WaveChunkData wave_chunk_data; + wave_chunk_data.filename = argv[cmdln_index + 1]; + wave_chunk_data.tag = WAVE_CHUNK_TAG(tag_str); + wave_chunk_datas.push_back(wave_chunk_data); + + cmdln_index += 2; + } + else if (strcmp(argv[cmdln_index], "--chna-audio-ids") == 0) + { + if (cmdln_index + 1 >= argc) + { + usage(argv[0]); + fprintf(stderr, "Missing argument(s) for option '%s'\n", argv[cmdln_index]); + return 1; + } + chna_audio_ids_file = argv[cmdln_index + 1]; + cmdln_index++; + } else if (strcmp(argv[cmdln_index], "--track-map") == 0) { if (cmdln_index + 1 >= argc) @@ -5856,6 +5906,29 @@ int main(int argc, const char** argv) } + // Add Wave chunks provided via commandline args. + // These chunks will override any chunks added above for ADM + + if (clip_type == CW_WAVE_CLIP_TYPE) { + WaveWriter *wave_clip = clip->GetWaveClip(); + size_t i; + for (i = 0; i < wave_chunk_datas.size(); i++) { + const WaveChunkData &wave_chunk_data = wave_chunk_datas[i]; + + // Use the WaveFileIO class as a generic BMXIO class + BMXIO *file = WaveFileIO::OpenRead(wave_chunk_data.filename); + + WaveFileChunk *chunk = new WaveFileChunk(wave_chunk_data.tag, file, 0, file->Size()); + wave_clip->AddChunk(chunk, true); + } + + if (chna_audio_ids_file) { + WaveCHNA *chna = parse_chna_text_file(chna_audio_ids_file); + wave_clip->AddCHNA(chna, true); + } + } + + // prepare the clip's header metadata clip->PrepareHeaderMetadata(); diff --git a/include/bmx/apps/ADMCHNATextFileHelper.h b/include/bmx/apps/ADMCHNATextFileHelper.h new file mode 100644 index 00000000..1a7ed570 --- /dev/null +++ b/include/bmx/apps/ADMCHNATextFileHelper.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BMX_ADM_CHNA_TEST_FILE_HELPER_H_ +#define BMX_ADM_CHNA_TEST_FILE_HELPER_H_ + +#include + +#include + + +namespace bmx +{ + + +WaveCHNA* parse_chna_text_file(const std::string &filename); + +void write_chna_text_file(const std::string &filename, WaveCHNA *chna); + + +}; + +#endif diff --git a/include/bmx/wave/WaveCHNA.h b/include/bmx/wave/WaveCHNA.h index f96d0812..c0a83c92 100644 --- a/include/bmx/wave/WaveCHNA.h +++ b/include/bmx/wave/WaveCHNA.h @@ -37,6 +37,7 @@ #include #include +#include @@ -67,6 +68,8 @@ class WaveCHNA void Write(WaveIO *output); public: + WaveChunkTag Tag() const { return WAVE_CHUNK_TAG("chna"); } + uint16_t GetNumTracks() const { return mNumTracks; } uint16_t GetNumUIDs() const { return mNumUIDs; } const std::vector& GetAudioIDs() const { return mAudioIDs; } diff --git a/include/bmx/wave/WaveChunk.h b/include/bmx/wave/WaveChunk.h index 42a8a311..ea0a68be 100644 --- a/include/bmx/wave/WaveChunk.h +++ b/include/bmx/wave/WaveChunk.h @@ -44,7 +44,7 @@ namespace bmx typedef mxfRIFFChunkIDType WaveChunkTag; -#define WAVE_CHUNK_TAG(cstr) (WaveChunkTag){(cstr)[0], (cstr)[1], (cstr)[2], (cstr)[3]} +#define WAVE_CHUNK_TAG(cstr) (WaveChunkTag){(uint8_t)((cstr)[0]), (uint8_t)((cstr)[1]), (uint8_t)((cstr)[2]), (uint8_t)((cstr)[3])} std::string get_wave_chunk_tag_str(WaveChunkTag tag); diff --git a/include/bmx/wave/WaveWriter.h b/include/bmx/wave/WaveWriter.h index a95876ef..4b500f7c 100644 --- a/include/bmx/wave/WaveWriter.h +++ b/include/bmx/wave/WaveWriter.h @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -88,6 +89,8 @@ class WaveWriter void SetSamplingRate(Rational sampling_rate); void SetQuantizationBits(uint16_t bits); + void RemoveChunk(WaveChunkTag tag); + private: WaveIO *mOutput; bool mOwnOutput; @@ -97,8 +100,8 @@ class WaveWriter WaveBEXT *mBEXT; WaveCHNA *mCHNA; bool mOwnCHNA; - std::vector mAdditionalChunks; - std::vector mOwnedAdditionalChunks; + std::map mAdditionalChunks; + std::map mOwnedAdditionalChunks; Rational mSamplingRate; bool mSamplingRateSet; diff --git a/src/apps/ADMCHNATextFileHelper.cpp b/src/apps/ADMCHNATextFileHelper.cpp new file mode 100644 index 00000000..47786bc1 --- /dev/null +++ b/src/apps/ADMCHNATextFileHelper.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2022, British Broadcasting Corporation + * All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the British Broadcasting Corporation nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include +#include + +#include +#include +#include + +using namespace std; +using namespace bmx; + + +WaveCHNA* bmx::parse_chna_text_file(const string &filename) +{ + PropertyFileParser property_parser; + if (!property_parser.Open(filename)) + BMX_EXCEPTION(("Failed to open chna text file '%s'", filename.c_str())); + + WaveCHNA *chna = new WaveCHNA(); + try { + string name; + string value; + unsigned int uint_value; + bool have_audio_id = false; + WaveCHNA::AudioID audio_id = {0, {0}, {0}, {0}}; + while (property_parser.ParseNext(&name, &value)) { + if (name == "track_index") { + if (sscanf(value.c_str(), "%u", &uint_value) != 1) + BMX_EXCEPTION(("Failed to parse chna track_index")); + + if (have_audio_id) + chna->AppendAudioID(audio_id); + + memset(&audio_id, 0, sizeof(audio_id)); + audio_id.track_index = uint_value; + have_audio_id = true; + } else if (name == "uid") { + if (!have_audio_id) + BMX_EXCEPTION(("Missing chna track_index to start audio ID")); + + if (audio_id.track_index != 0) { // track_index == 0 means null/placeholder audio ID + value.resize(sizeof(audio_id.uid)); + memcpy(audio_id.uid, value.c_str(), sizeof(audio_id.uid)); + } + } else if (name == "track_ref") { + if (!have_audio_id) + BMX_EXCEPTION(("Missing chna track_index to start audio ID")); + + if (audio_id.track_index != 0) { // track_index == 0 means null/placeholder audio ID + value.resize(sizeof(audio_id.track_ref)); + memcpy(audio_id.track_ref, value.c_str(), sizeof(audio_id.track_ref)); + } + } else if (name == "pack_ref") { + if (!have_audio_id) + BMX_EXCEPTION(("Missing chna track_index to start audio ID")); + + if (audio_id.track_index != 0) { // track_index == 0 means null/placeholder audio ID + value.resize(sizeof(audio_id.pack_ref)); + memcpy(audio_id.pack_ref, value.c_str(), sizeof(audio_id.pack_ref)); + } + } else { + log_warn("Ignoring unknown property '%s' in chna text file\n", name.c_str()); + } + } + + if (have_audio_id) + chna->AppendAudioID(audio_id); + + if (chna->GetNumTracks() == 0) + BMX_EXCEPTION(("No audio IDs parsed")); + + } catch (...) { + delete chna; + throw; + } + + return chna; +} + +void bmx::write_chna_text_file(const string &filename, WaveCHNA *chna) +{ + FILE *text_file = fopen(filename.c_str(), "wb"); + if (!text_file) + BMX_EXCEPTION(("Failed to open chna text file '%s' for writing: %s", filename.c_str(), bmx_strerror(errno).c_str())); + + try { + const vector &audio_ids = chna->GetAudioIDs(); + size_t i; + for (i = 0; i < audio_ids.size(); i++) { + const WaveCHNA::AudioID &audio_id = audio_ids[i]; + + if (i > 0) + fprintf(text_file, "\n"); + + fprintf(text_file, "track_index: %u\n", audio_id.track_index); + if (audio_id.track_index == 0) // track_index == 0 means null/placeholder audio ID + continue; + + string value; + if (audio_id.uid[0] != 0) { + value.assign((const char*)audio_id.uid, sizeof(audio_id.uid)); + fprintf(text_file, "uid: %s\n", value.c_str()); + } + + if (audio_id.track_ref[0] != 0) { + value.assign((const char*)audio_id.track_ref, sizeof(audio_id.track_ref)); + fprintf(text_file, "track_ref: %s\n", value.c_str()); + } + + if (audio_id.pack_ref[0] != 0) { + value.assign((const char*)audio_id.pack_ref, sizeof(audio_id.pack_ref)); + fprintf(text_file, "pack_ref: %s\n", value.c_str()); + } + } + + } catch (...) { + fclose(text_file); + throw; + } + + fclose(text_file); +} diff --git a/src/wave/WaveWriter.cpp b/src/wave/WaveWriter.cpp index f14dafbd..b0ecdd0d 100644 --- a/src/wave/WaveWriter.cpp +++ b/src/wave/WaveWriter.cpp @@ -95,8 +95,9 @@ WaveWriter::~WaveWriter() for (i = 0; i < mTracks.size(); i++) delete mTracks[i]; - for (i = 0; i < mOwnedAdditionalChunks.size(); i++) - delete mOwnedAdditionalChunks[i]; + map::const_iterator iter; + for (iter = mOwnedAdditionalChunks.begin(); iter != mOwnedAdditionalChunks.end(); iter++) + delete iter->second; } void WaveWriter::SetStartTimecode(Timecode start_timecode) @@ -112,8 +113,7 @@ void WaveWriter::SetSampleCount(int64_t count) void WaveWriter::AddCHNA(WaveCHNA *chna, bool take_ownership) { - if (mOwnCHNA) - delete mCHNA; + RemoveChunk(chna->Tag()); mCHNA = chna; mOwnCHNA = take_ownership; @@ -121,9 +121,11 @@ void WaveWriter::AddCHNA(WaveCHNA *chna, bool take_ownership) void WaveWriter::AddChunk(WaveChunk *chunk, bool take_ownership) { - mAdditionalChunks.push_back(chunk); + RemoveChunk(chunk->Tag()); + + mAdditionalChunks[chunk->Tag()] = chunk; if (take_ownership) - mOwnedAdditionalChunks.push_back(chunk); + mOwnedAdditionalChunks[chunk->Tag()] = chunk; } void WaveWriter::AddADMAudioID(const WaveCHNA::AudioID &audio_id) @@ -174,14 +176,14 @@ void WaveWriter::PrepareWrite() mWriteBW64 = true; vector write_chunks; - size_t i; - for (i = 0; i < mAdditionalChunks.size(); i++) { - WaveChunk *chunk = mAdditionalChunks[i]; + map::const_iterator iter; + for (iter = mAdditionalChunks.begin(); iter != mAdditionalChunks.end(); iter++) { + WaveChunk *chunk = iter->second; if (chunk->Tag() == "axml" || chunk->Tag() == "bxml" || chunk->Tag() == "sxml") { mWriteBW64 = true; write_chunks.push_back(chunk); - } else if (chunk->Tag() == "chna" && !mCHNA) { + } else if (chunk->Tag() == "chna") { // Accept a chna tag passed in using AddChunk() rather than AddCHNA() // Don't add it to write_chunks here because it needs to be written first mWriteBW64 = true; @@ -205,6 +207,7 @@ void WaveWriter::PrepareWrite() mSetSize = 4 + (8 + 28) + (8 + 16) + (8 + mSetDataSize); if (!mWriteBW64) mSetSize += (8 + 4) + (8 + mBEXT->GetAlignedSize()); // fact and bext chunks + size_t i; for (i = 0; i < write_chunks.size(); i++) mSetSize += 8 + write_chunks[i]->AlignedSize(); @@ -275,6 +278,7 @@ void WaveWriter::PrepareWrite() else if (chna_chunk) mOutput->WriteChunk(chna_chunk); + size_t i; for (i = 0; i < write_chunks.size(); i++) mOutput->WriteChunk(write_chunks[i]); @@ -491,3 +495,21 @@ void WaveWriter::SetQuantizationBits(uint16_t bits) mChannelBlockAlign = (mQuantizationBits + 7) / 8; } +void WaveWriter::RemoveChunk(WaveChunkTag tag) +{ + if (tag == "chna") { + if (mOwnCHNA) + delete mCHNA; + mCHNA = 0; + mOwnCHNA = false; + } + + if (mAdditionalChunks.count(tag)) { + mAdditionalChunks.erase(tag); + + if (mOwnedAdditionalChunks.count(tag)) { + delete mOwnedAdditionalChunks[tag]; + mOwnedAdditionalChunks.erase(tag); + } + } +} diff --git a/test/create_test_essence.cpp b/test/create_test_essence.cpp index 9a23f4dc..ee88d76c 100644 --- a/test/create_test_essence.cpp +++ b/test/create_test_essence.cpp @@ -910,7 +910,7 @@ static void write_vbi_data(FILE *file, unsigned int duration) static void print_usage(const char *cmd) { - fprintf(stderr, "Usage: %s [-d ] -t \n", cmd); + fprintf(stderr, "Usage: %s [-d ] [-s ] -t \n", cmd); fprintf(stderr, "Types:\n"); fprintf(stderr, " 1: 16-bit PCM\n"); fprintf(stderr, " 2: IEC DV 25\n"); diff --git a/test/wave_adm/chna_1.txt b/test/wave_adm/chna_1.txt new file mode 100644 index 00000000..dc705e66 --- /dev/null +++ b/test/wave_adm/chna_1.txt @@ -0,0 +1,19 @@ +track_index: 1 +uid: ATU_00000001 +track_ref: AT_00010001_01 +pack_ref: AP_00010002 + +track_index: 2 +uid: ATU_00000002 +track_ref: AT_00010002_01 +pack_ref: AP_00010002 + +track_index: 3 +uid: ATU_00000003 +track_ref: AT_00010001_01 +pack_ref: AP_00010002 + +track_index: 4 +uid: ATU_00000004 +track_ref: AT_00010002_01 +pack_ref: AP_00010002 diff --git a/test/wave_adm/test.sh b/test/wave_adm/test.sh index 608ec905..86e0aecc 100755 --- a/test/wave_adm/test.sh +++ b/test/wave_adm/test.sh @@ -133,6 +133,28 @@ create_wave_5() >/dev/null } +create_wave_6() +{ + # Create a Wave file from test generated content, an axml chunk file and a chna text file. + + $testdir/create_test_essence -t 42 -d 1 -s 1 $tmpdir/audio1.pcm + $testdir/create_test_essence -t 42 -d 1 -s 2 $tmpdir/audio2.pcm + $testdir/create_test_essence -t 42 -d 1 -s 3 $tmpdir/audio3.pcm + $testdir/create_test_essence -t 42 -d 1 -s 4 $tmpdir/audio4.pcm + + $appsdir/raw2bmx/raw2bmx \ + --regtest \ + -t wave \ + -o $3 \ + --wave-chunk-data $1 axml \ + --chna-audio-ids $2 \ + -s 48000 -q 24 --pcm $tmpdir/audio1.pcm \ + -s 48000 -q 24 --pcm $tmpdir/audio2.pcm \ + -s 48000 -q 24 --pcm $tmpdir/audio3.pcm \ + -s 48000 -q 24 --pcm $tmpdir/audio4.pcm \ + >/dev/null +} + create_mxf_4() { # Create an MXF from wave_3 including only silence (non-ADM) channels. @@ -175,6 +197,9 @@ check() $md5tool < $tmpdir/test.wav > $tmpdir/test.md5 && diff $tmpdir/test.md5 $base/test_wave_5.md5 && diff $tmpdir/test.wav $base/adm_1.wav && + create_wave_6 $base/axml_1.xml $base/chna_1.txt $tmpdir/test.wav && + $md5tool < $tmpdir/test.wav > $tmpdir/test.md5 && + diff $tmpdir/test.md5 $base/test_wave_6.md5 && create_mxf_4 $tmpdir/test_wav_3.wav $tmpdir/test.mxf && $md5tool < $tmpdir/test.mxf > $tmpdir/test.md5 && diff $tmpdir/test.md5 $base/test_mxf_4.md5 @@ -198,6 +223,8 @@ create_data() $md5tool < $tmpdir/test.wav > $base/test_wave_4.md5 && create_wave_5 $tmpdir/test.wav && $md5tool < $tmpdir/test.wav > $base/test_wave_5.md5 && + create_wave_6 $base/axml_1.xml $base/chna_1.txt $tmpdir/test.wav && + $md5tool < $tmpdir/test.wav > $base/test_wave_6.md5 && create_mxf_4 $tmpdir/test_wave_3.wav $tmpdir/test.mxf && $md5tool < $tmpdir/test.mxf > $base/test_mxf_4.md5 } @@ -212,6 +239,7 @@ create_samples() create_wave_3 $sampledir/test_mxf_3.mxf $sampledir/test_wave_3.wav && create_wave_4 $sampledir/test_mxf_3.mxf $sampledir/test_wave_4.wav && create_wave_5 $sampledir/test_wave_5.wav && + create_wave_6 $base/axml_1.xml $base/chna_1.txt $sampledir/test_wave_6.wav && create_mxf_4 $sampledir/test_wave_3.wav $sampledir/test_mxf_4.mxf } diff --git a/test/wave_adm/test_wave_6.md5 b/test/wave_adm/test_wave_6.md5 new file mode 100644 index 00000000..568a0ed1 --- /dev/null +++ b/test/wave_adm/test_wave_6.md5 @@ -0,0 +1 @@ +aaef12b815b25fa627bb4f13292971af - From 10ccc597af1c1631e474822c41d3bbbe4b84c43c Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Thu, 19 Jan 2023 14:13:42 +0000 Subject: [PATCH 15/65] Add readme for ADM support --- README.md | 1 + apps/raw2bmx/raw2bmx.cpp | 1 + docs/audio_definition_model.md | 113 +++++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+) create mode 100644 docs/audio_definition_model.md diff --git a/README.md b/README.md index 4afd2e66..34a58e72 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,7 @@ including the following: * [IMF JPEG 2000 Track Files](./docs/imf_jpeg_2000_track_files.md) * [IMF Audio Track Files](./docs/imf_audio_track_files.md) * [IMF ProRes Image Track Files](./docs/imf_prores_track_files.md) +* [Audio Definition Model](./docs/audio_definition_model.md) ## Build, Test and Install diff --git a/apps/raw2bmx/raw2bmx.cpp b/apps/raw2bmx/raw2bmx.cpp index b82c89ec..44e71761 100644 --- a/apps/raw2bmx/raw2bmx.cpp +++ b/apps/raw2bmx/raw2bmx.cpp @@ -619,6 +619,7 @@ static void usage(const char *cmd) printf(" This chunk will override any non-builtin and 'chna' chunk originating from the input Wave files\n"); printf(" --chna-audio-ids Add a 'chna' chunk to the output Wave file which is defined in the text \n"); printf(" This chunk will override any 'chna' chunk originating from the input Wave files\n"); + printf(" The format for the is described in bmx/docs/audio_definition_model#chna-text-file-definition-format\n"); printf("\n"); printf(" as02/op1a/as11op1a:\n"); printf(" --use-avc-subdesc Use the AVC sub-descriptor rather than the MPEG video descriptor for AVC-Intra tracks\n"); diff --git a/docs/audio_definition_model.md b/docs/audio_definition_model.md new file mode 100644 index 00000000..cae835c9 --- /dev/null +++ b/docs/audio_definition_model.md @@ -0,0 +1,113 @@ +# Audio Definition Model (ADM) Support + +A SMPTE project named "31FS ST Mapping ADM to MXF" started in March 2022 to "define a means of mapping audio metadata RIFF chunks to MXF with specific consideration of the requirements related to ADM metadata (for example, with reference to ADM carriage in BW64 files per Rec. ITU-R BS.2088-1)." + +Provisional support for ADM has been implemented in `bmx` to allow samples files to be created to support the SMPTE project. The implementation is based on an initial design specification and is likely to change. + +The current support in the `bmx` implementation is as follows: +- Reading Wave (BW64) that includes ADM chunks (chna, axml, bxml and sxml) +- Writing Wave (BW64) with ADM chunks (chna, axml, bxml and sxml) +- Reading MXF that includes Wave chunks and (mapped) ADM chna +- Writing MXF that with Wave chunks and (mapped) ADM chna +- Converting Wave+ADM to MXF+ADM using raw2bmx +- Converting Wave+ADM to Wave+ADM using raw2bmx +- Converting MXF+ADM to Wave+ADM using bmxtranswrap +- Creating Wave+ADM with Wave / raw PCM, chna text file and axml/bxml/sxml file inputs +- Preservation of ADM links after remapping audio channels using the `--track-map` option can be used to reorder, omit, group and add silence channels. + +The known limitations are: +- mxf2raw doesn't yet show ADM metadata presence or allow ADM chunks or a chna text file to be extracted. +- Re-wrapping a file using raw2bmx or bmxtranswrap with an offset or duration change may result in the ADM metadata and links becoming invalid. E.g. an audio object is no longer available in the new duration or the start offset has changed. The axml, bxml or sxml chunks are not parsed to ensure that the re-wrap retains valid ADM. +- \> 4 GB chunk size is only supported for the data chunk. The ADM chunks are unlikely to be that large but it's worth adding support just in case that assumption is wrong. + + +## Creating a Wave+ADM sample file + +A Wave+ADM sample file can be created using the following example commandline given a Wave file, a chna text file and an axml XML file: + +`raw2bmx -t wave -o output.wav --wave-chunk-data axml.xml axml --chna-audio-ids chna.txt --wave input.wav` + +The axml file `axml.xml` is the data that will be written into the axml chunk (with tag `axml`). The chna text file `chna.txt` lists the audio identifiers that make up the chna chunk. The format of the text file is described in [chna Text file Definition Format](#chna-text-file-definition-format). + +If the source Wave file contained an axml chunk then the `--wave-chunk-data axml.xml axml` option will override it. If the source Wave file contained a chna chunk then the `--chna-audio-ids chna.txt` option will override it. + +Raw PCM files can also be used as input, e.g. replace `--wave input.wave` with: + +`-s 48000 -q 24 --audio-chan 2 --pcm audio_0_1.pcm -s 48000 -q 24 --audio-chan 2 --pcm audio_2_3.pcm` + + +## Converting a Wave+ADM to MXF+ADM + +A Wave+ADM can be converted to MXF+ADM using the following example commandline: + +`raw2bmx -t op1a -o output.mxf --wave input.wave` + +The default layout is to have mono-audio MXF tracks. This can be changed using the `--track-map` option. For example, this command will group each stereo channels into an MXF track: + +`raw2bmx -t op1a -o output.mxf --track-map '0,1;2,3' --wave input.wave` + +Note that the channel index is zero-based for track mapping. + + +## Converting a MXF+ADM to Wave+ADM + +A MXF+ADM can be converted to Wave+ADM using the following example commandline: + +`bmxtranswrap -t wave -o output.wav input.mxf` + +The `--track-map` option can be used to change the audio channels. For example, if only the first sereo pair is required: + +`bmxtranswrap -t wave -o output.wav --track-map '0,1' input.mxf` + + +## Converting a Wave+ADM to Wave+ADM + +A Wave+ADM can be converted to another Wave+ADM using the following example commandline: + +`raw2bmx -t wave -o output.wave --wave input.wave` + +The `--track-map` option can be used to change what is output. For example, reorder the stereo pairs: + +`raw2bmx -t wave -o output.wave --track-map '2,3,0,1' --wave input.wave` + + +## chna Text File Definition Format + +The chna text file contains the list of ADM audio identifiers that make up the chna chunk. The number of tracks and UIDs is automatically calculated. + +The chna text file consists of a set of name/value property pairs separated by a newline. The name/value pair uses the first ':' character as a separator. A '#' character signals the start of a comment. + +The properties for each audio identifier are as follows. + +- `track_index`: The index of the track in the Wave file, starting from 1. A value 0 represents a null / placeholder entry. +- `uid`: The audioTrackUID value of the track. +- `track_ref`: The audioTrackFormatID reference for the track. +- `pack_ref`: The audioPackFormatID reference for the track. + +Each audio identifier is started by a `track_index` property. + +A `track_index` 0 represents a null / placeholder entry that is used to support Wave file updates. These entries are stripped when mapping to MXF. + +An example chna text file is shown below. It describes 2 stereo pairs, each with "front left" and "front right" channels. + +``` +track_index: 1 +uid: ATU_00000001 +track_ref: AT_00010001_01 +pack_ref: AP_00010002 + +track_index: 2 +uid: ATU_00000002 +track_ref: AT_00010002_01 +pack_ref: AP_00010002 + +track_index: 3 +uid: ATU_00000003 +track_ref: AT_00010001_01 +pack_ref: AP_00010002 + +track_index: 4 +uid: ATU_00000004 +track_ref: AT_00010002_01 +pack_ref: AP_00010002 +``` From f8fe58197de54c3401e9f7fd63a5e3e98823e3be Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Mon, 25 Jul 2022 15:17:00 +0000 Subject: [PATCH 16/65] test: update checksums after ADM data model was updated --- test/wave_adm/test_mxf_1.md5 | 2 +- test/wave_adm/test_mxf_2.md5 | 2 +- test/wave_adm/test_mxf_3.md5 | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/wave_adm/test_mxf_1.md5 b/test/wave_adm/test_mxf_1.md5 index d67396c2..fc08106a 100644 --- a/test/wave_adm/test_mxf_1.md5 +++ b/test/wave_adm/test_mxf_1.md5 @@ -1 +1 @@ -35e48e7f62efc6621982483adcf55ef2 - +f8fb075f662b05fba544a119d7b13842 - diff --git a/test/wave_adm/test_mxf_2.md5 b/test/wave_adm/test_mxf_2.md5 index 80e9f04a..b3fd76fe 100644 --- a/test/wave_adm/test_mxf_2.md5 +++ b/test/wave_adm/test_mxf_2.md5 @@ -1 +1 @@ -dc5765741331ad812fcbef7a09d79483 - +7389f87f35bdcf26e6f91c83272db8dc - diff --git a/test/wave_adm/test_mxf_3.md5 b/test/wave_adm/test_mxf_3.md5 index aa6dee01..57bf5aed 100644 --- a/test/wave_adm/test_mxf_3.md5 +++ b/test/wave_adm/test_mxf_3.md5 @@ -1 +1 @@ -1a324812b106b511ff60ff048b1fea0b - +ce3cf209d705d8a49ae46a13bd7937f0 - From f60abb5d855e870d80efaa9cdfba1d7184b428f8 Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Wed, 22 Nov 2023 10:17:37 +0000 Subject: [PATCH 17/65] Update ADM data model in mxflib dict --- meta/extensions_mxflib_dict.xml | 40 +++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/meta/extensions_mxflib_dict.xml b/meta/extensions_mxflib_dict.xml index 7bd26458..9b538fd3 100644 --- a/meta/extensions_mxflib_dict.xml +++ b/meta/extensions_mxflib_dict.xml @@ -149,33 +149,39 @@ - - - - - - + + + + + + - - - - + + + + - - - - - + + + + + - - + + + + + + + + From e720e0cec76047a965ea67724ad70d5526bdb8bb Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Tue, 26 Jul 2022 09:02:13 +0000 Subject: [PATCH 18/65] Prevent null ADM audio mappings in MXF descriptor --- src/mxf_helper/ADMCHNAMXFDescriptorHelper.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/mxf_helper/ADMCHNAMXFDescriptorHelper.cpp b/src/mxf_helper/ADMCHNAMXFDescriptorHelper.cpp index 96e81056..b29cc76c 100644 --- a/src/mxf_helper/ADMCHNAMXFDescriptorHelper.cpp +++ b/src/mxf_helper/ADMCHNAMXFDescriptorHelper.cpp @@ -90,6 +90,10 @@ ADM_CHNASubDescriptor* bmx::convert_chunk_to_adm_chna_descriptor(HeaderMetadata for (i = 0; i < audio_ids.size(); i++) { const WaveCHNA::AudioID &audio_id = audio_ids[i]; + // The descriptor shall have no "null" or "unused" mappings + if (audio_id.track_index == 0) + continue; + ADMChannelMapping *mapping = new ADMChannelMapping(header_metadata); mapping->setLocalChannelID(audio_id.track_index); mapping->setADMAudioTrackUID(string((const char*)audio_id.uid, sizeof(audio_id.uid))); From 59ad19d21f1ee7578f89d88a24f2ac115ec0eead Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Tue, 26 Jul 2022 09:32:14 +0000 Subject: [PATCH 19/65] Additional checks for audio mappings --- src/apps/ADMCHNATextFileHelper.cpp | 3 +++ src/wave/WaveCHNA.cpp | 7 +++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/apps/ADMCHNATextFileHelper.cpp b/src/apps/ADMCHNATextFileHelper.cpp index 47786bc1..d3989d7f 100644 --- a/src/apps/ADMCHNATextFileHelper.cpp +++ b/src/apps/ADMCHNATextFileHelper.cpp @@ -104,6 +104,9 @@ WaveCHNA* bmx::parse_chna_text_file(const string &filename) if (chna->GetNumTracks() == 0) BMX_EXCEPTION(("No audio IDs parsed")); + if (chna->GetNumUIDs() == 0) + BMX_EXCEPTION(("No non-null audio IDs parsed")); + } catch (...) { delete chna; throw; diff --git a/src/wave/WaveCHNA.cpp b/src/wave/WaveCHNA.cpp index 82a6e7c0..ff429238 100644 --- a/src/wave/WaveCHNA.cpp +++ b/src/wave/WaveCHNA.cpp @@ -68,10 +68,9 @@ void WaveCHNA::AppendAudioID(const AudioID &audio_id) if (existing_audio_id.track_index == 0) continue; - if (audio_id.track_index == existing_audio_id.track_index && - memcmp(audio_id.uid, existing_audio_id.uid, sizeof(existing_audio_id.uid)) == 0) - { - log_warn("Ignoring duplicate audio ID with track index %u in CHNA chunk\n", audio_id.track_index); + // Each audio track UID shall be unique + if (memcmp(audio_id.uid, existing_audio_id.uid, sizeof(existing_audio_id.uid)) == 0) { + log_warn("Ignoring audio ID that has a duplicate UID\n"); return; } From 785aa5a7c412adcab3d5c54ac2cf88a062b23d19 Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Thu, 19 Jan 2023 09:19:56 +0000 Subject: [PATCH 20/65] Implement support for ADM MCA labelling --- apps/bmxtranswrap/bmxtranswrap.cpp | 1 + apps/raw2bmx/raw2bmx.cpp | 1 + docs/audio_definition_model.md | 18 +++++ docs/mca_labels_format.md | 5 ++ include/bmx/apps/AppMCALabelHelper.h | 6 ++ include/bmx/clip_writer/ClipWriterTrack.h | 2 + include/bmx/mxf_op1a/OP1APCMTrack.h | 2 + include/bmx/rdd9_mxf/RDD9PCMTrack.h | 2 + src/apps/AppMCALabelHelper.cpp | 84 ++++++++++++++++------- src/clip_writer/ClipWriterTrack.cpp | 31 +++++++++ src/mxf_op1a/OP1APCMTrack.cpp | 18 +++++ src/rdd9_mxf/RDD9PCMTrack.cpp | 18 +++++ test/wave_adm/mca_1.txt | 9 +++ test/wave_adm/test.sh | 33 ++++++++- test/wave_adm/test_mxf_5.md5 | 1 + 15 files changed, 205 insertions(+), 26 deletions(-) create mode 100644 test/wave_adm/mca_1.txt create mode 100644 test/wave_adm/test_mxf_5.md5 diff --git a/apps/bmxtranswrap/bmxtranswrap.cpp b/apps/bmxtranswrap/bmxtranswrap.cpp index 96397f9e..46b74286 100644 --- a/apps/bmxtranswrap/bmxtranswrap.cpp +++ b/apps/bmxtranswrap/bmxtranswrap.cpp @@ -702,6 +702,7 @@ static void usage(const char *cmd) printf(" * 'as11-mode-1', which corresponds to urn:smpte:ul:060e2b34.04010101.0d010801.02020000,\n"); printf(" * 'as11-mode-2', which corresponds to urn:smpte:ul:060e2b34.04010101.0d010801.02030000\n"); printf(" * 'imf', which corresponds to urn:smpte:ul:060e2b34.0401010d.04020210.04010000\n"); + printf(" * 'adm', which corresponds to urn:smpte:ul:060e2b34.0401010d.04020210.05010000\n"); printf(" --track-mca-labels Insert audio labels defined in . The 'as11' will add an override and otherwise is ignored\n"); printf(" The format of is described in bmx/docs/mca_labels_format.md\n"); printf(" All tag symbols registered in the bmx code are available for use\n"); diff --git a/apps/raw2bmx/raw2bmx.cpp b/apps/raw2bmx/raw2bmx.cpp index 44e71761..c25fd882 100644 --- a/apps/raw2bmx/raw2bmx.cpp +++ b/apps/raw2bmx/raw2bmx.cpp @@ -632,6 +632,7 @@ static void usage(const char *cmd) printf(" * 'as11-mode-1', which corresponds to urn:smpte:ul:060e2b34.04010101.0d010801.02020000,\n"); printf(" * 'as11-mode-2', which corresponds to urn:smpte:ul:060e2b34.04010101.0d010801.02030000\n"); printf(" * 'imf', which corresponds to urn:smpte:ul:060e2b34.0401010d.04020210.04010000\n"); + printf(" * 'adm', which corresponds to urn:smpte:ul:060e2b34.0401010d.04020210.05010000\n"); printf(" --track-mca-labels Insert audio labels defined in . The 'as11' will add an override and otherwise is ignored\n"); printf(" The format of is described in bmx/docs/mca_labels_format.md\n"); printf(" All tag symbols registered in the bmx code are available for use\n"); diff --git a/docs/audio_definition_model.md b/docs/audio_definition_model.md index cae835c9..1d4e6dfd 100644 --- a/docs/audio_definition_model.md +++ b/docs/audio_definition_model.md @@ -14,6 +14,8 @@ The current support in the `bmx` implementation is as follows: - Converting MXF+ADM to Wave+ADM using bmxtranswrap - Creating Wave+ADM with Wave / raw PCM, chna text file and axml/bxml/sxml file inputs - Preservation of ADM links after remapping audio channels using the `--track-map` option can be used to reorder, omit, group and add silence channels. +- Add ADM Soundfield Group MCA label +- Set the Channel Assignment audio descriptor property for ADM-described content labelling The known limitations are: - mxf2raw doesn't yet show ADM metadata presence or allow ADM chunks or a chna text file to be extracted. @@ -71,6 +73,22 @@ The `--track-map` option can be used to change what is output. For example, reor `raw2bmx -t wave -o output.wave --track-map '2,3,0,1' --wave input.wave` +## Add ADM MCA labels to MXF+ADM + +An ADM Soundfield Group MCA label can be added using the `sgADM` symbol in a [MCA labels text file](./mca_labels_format.md): + +`mca.txt`: +``` +0 +chL, chan=0 +chR, chan=1 +sgADM, lang=eng, mca_title="Example Programme", adm_audio_programme_id="APR_1001", adm_audio_content_id="ACO_1001", adm_audio_object_id="AO_1001" +``` + +The MCA labels defined in `mca.txt` can be added and the ADM-described content label can be set in the audio descriptor Channel Assignment property using the following example commandline: +`raw2bmx -t op1a -o output.mxf --track-map '0,1' --track-mca-labels adm mca.txt --audio-layout adm --wave input.wave` + + ## chna Text File Definition Format The chna text file contains the list of ADM audio identifiers that make up the chna chunk. The number of tracks and UIDs is automatically calculated. diff --git a/docs/mca_labels_format.md b/docs/mca_labels_format.md index efa04fdd..2e1a0443 100644 --- a/docs/mca_labels_format.md +++ b/docs/mca_labels_format.md @@ -58,11 +58,16 @@ The following string value properties can be used: - MCASpokenLanguageAttribute - RFC5646AdditionalSpokenLanguages - MCAAdditionalLanguageAttributes +- ADMAudioProgrammeID_ADMsg +- ADMAudioContentID_ADMsg +- ADMAudioObjectID_ADMsg The "lang" name can be used instead of "RFC5646SpokenLanguage". The name may omit the "MCA" prefix, e.g. "TitleVersion" is accepted. The name matching is case-insenstive, e.g. "titleversion" is accepted. Underscores are ignored, e.g. "title_version" is accepted. +The ADM properties, which are the properties with the "ADM" prefix, may also omit the "_ADMsg" suffix. The ADM properties can only be used in a "sgADM" SG label. + The property value may be between quotation marks, either single or double quotes. Some special characters (e.g. used in RFC5646AdditionalSpokenLanguages and MCAAdditionalLanguageAttributes) can be set by using the `\` escape character. They are tab `\t` (0x09), line feed `\n` (0x0a) and carriage return `\r` (0x0d). diff --git a/include/bmx/apps/AppMCALabelHelper.h b/include/bmx/apps/AppMCALabelHelper.h index a1db4a05..228990f2 100644 --- a/include/bmx/apps/AppMCALabelHelper.h +++ b/include/bmx/apps/AppMCALabelHelper.h @@ -77,6 +77,12 @@ static const UL IMF_MCA_LABEL_FRAMEWORK = {0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x0d, 0x04, 0x02, 0x02, 0x10, 0x04, 0x01, 0x00, 0x00}; +// ADM SMPTE ST 2131 Channel Assignment Label + +static const UL ADM_MCA_LABEL_FRAMEWORK = + {0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x0d, 0x04, 0x02, 0x02, 0x10, 0x05, 0x01, 0x00, 0x00}; + + class ClipWriter; class AppMCALabelHelper diff --git a/include/bmx/clip_writer/ClipWriterTrack.h b/include/bmx/clip_writer/ClipWriterTrack.h index 6df2e11a..9fde9714 100644 --- a/include/bmx/clip_writer/ClipWriterTrack.h +++ b/include/bmx/clip_writer/ClipWriterTrack.h @@ -104,6 +104,8 @@ class ClipWriterTrack mxfpp::SoundfieldGroupLabelSubDescriptor *copy_from = 0); mxfpp::GroupOfSoundfieldGroupsLabelSubDescriptor* AddGroupOfSoundfieldGroupLabel( mxfpp::GroupOfSoundfieldGroupsLabelSubDescriptor *copy_from = 0); + mxfpp::ADMSoundfieldGroupLabelSubDescriptor* AddADMSoundfieldGroupLabel( + mxfpp::ADMSoundfieldGroupLabelSubDescriptor *copy_from = 0); void AddWaveChunkReference(uint32_t stream_id); void AddADMAudioID(const WaveCHNA::AudioID &audio_id); diff --git a/include/bmx/mxf_op1a/OP1APCMTrack.h b/include/bmx/mxf_op1a/OP1APCMTrack.h index 78b640ca..be631d78 100644 --- a/include/bmx/mxf_op1a/OP1APCMTrack.h +++ b/include/bmx/mxf_op1a/OP1APCMTrack.h @@ -68,6 +68,8 @@ class OP1APCMTrack : public OP1ATrack mxfpp::SoundfieldGroupLabelSubDescriptor *copy_from = 0); mxfpp::GroupOfSoundfieldGroupsLabelSubDescriptor* AddGroupOfSoundfieldGroupLabel( mxfpp::GroupOfSoundfieldGroupsLabelSubDescriptor *copy_from = 0); + mxfpp::ADMSoundfieldGroupLabelSubDescriptor* AddADMSoundfieldGroupLabel( + mxfpp::ADMSoundfieldGroupLabelSubDescriptor *copy_from = 0); public: const std::vector& GetSampleSequence() const { return mSampleSequence; } diff --git a/include/bmx/rdd9_mxf/RDD9PCMTrack.h b/include/bmx/rdd9_mxf/RDD9PCMTrack.h index bcfd5bec..f74feb4c 100644 --- a/include/bmx/rdd9_mxf/RDD9PCMTrack.h +++ b/include/bmx/rdd9_mxf/RDD9PCMTrack.h @@ -63,6 +63,8 @@ class RDD9PCMTrack : public RDD9Track mxfpp::SoundfieldGroupLabelSubDescriptor *copy_from = 0); mxfpp::GroupOfSoundfieldGroupsLabelSubDescriptor* AddGroupOfSoundfieldGroupLabel( mxfpp::GroupOfSoundfieldGroupsLabelSubDescriptor *copy_from = 0); + mxfpp::ADMSoundfieldGroupLabelSubDescriptor* AddADMSoundfieldGroupLabel( + mxfpp::ADMSoundfieldGroupLabelSubDescriptor *copy_from = 0); public: const std::vector& GetSampleSequence() const { return mSampleSequence; } diff --git a/src/apps/AppMCALabelHelper.cpp b/src/apps/AppMCALabelHelper.cpp index 90830454..4d56a813 100644 --- a/src/apps/AppMCALabelHelper.cpp +++ b/src/apps/AppMCALabelHelper.cpp @@ -166,33 +166,59 @@ static const MCALabelEntry AS11_OVERRIDE_MCA_LABELS[] = }; +// Multi-channel audio labels from ADM, SMPTE ST 2131 + +static const UL ADM_SG_DICT_ID = {0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x0d, 0x03, 0x02, 0x02, 0x23, 0x00, 0x00, 0x00, 0x00}; + +static const MCALabelEntry ADM_MCA_LABELS[] = +{ + // Soundfield Groups + {SOUNDFIELD_GROUP_LABEL, "sgADM", "ADM", ADM_SG_DICT_ID}, +}; + + #define PROPERTY_FUNCTIONS(name) \ - static void Set##name (MCALabelSubDescriptor *descriptor, const string &value) { \ - descriptor->set##name (value); \ - } \ - static bool Check##name (MCALabelSubDescriptor *descriptor, const string &value) { \ - return descriptor->have##name () && descriptor->get##name () == value; \ - } + static void Set##name (MCALabelSubDescriptor *descriptor, const string &value) { \ + descriptor->set##name (value); \ + } \ + static bool Check##name (MCALabelSubDescriptor *descriptor, const string &value) { \ + return descriptor->have##name () && descriptor->get##name () == value; \ + } + +#define ADM_PROPERTY_FUNCTIONS(name) \ + static void Set##name (MCALabelSubDescriptor *descriptor, const string &value) { \ + ADMSoundfieldGroupLabelSubDescriptor *adm_descriptor = dynamic_cast(descriptor); \ + BMX_CHECK_M(adm_descriptor, ("Can't set ADM SG label property on non-ADM SG label descriptor")); \ + adm_descriptor->set##name (value); \ + } \ + static bool Check##name (MCALabelSubDescriptor *descriptor, const string &value) { \ + ADMSoundfieldGroupLabelSubDescriptor *adm_descriptor = dynamic_cast(descriptor); \ + BMX_CHECK_M(adm_descriptor, ("Can't check ADM SG label property on non-ADM SG label descriptor")); \ + return adm_descriptor->have##name () && adm_descriptor->get##name () == value; \ + } class MCAPropertyFunctions { public: - PROPERTY_FUNCTIONS(MCAPartitionKind); - PROPERTY_FUNCTIONS(MCAPartitionNumber); - PROPERTY_FUNCTIONS(MCATitle); - PROPERTY_FUNCTIONS(MCATitleVersion); - PROPERTY_FUNCTIONS(MCATitleSubVersion); - PROPERTY_FUNCTIONS(MCAEpisode); - PROPERTY_FUNCTIONS(RFC5646SpokenLanguage); - PROPERTY_FUNCTIONS(MCAAudioContentKind); - PROPERTY_FUNCTIONS(MCAAudioElementKind); - PROPERTY_FUNCTIONS(MCAContent); - PROPERTY_FUNCTIONS(MCAUseClass); - PROPERTY_FUNCTIONS(MCAContentSubtype); - PROPERTY_FUNCTIONS(MCAContentDifferentiator); - PROPERTY_FUNCTIONS(MCASpokenLanguageAttribute); - PROPERTY_FUNCTIONS(RFC5646AdditionalSpokenLanguages); - PROPERTY_FUNCTIONS(MCAAdditionalLanguageAttributes); + PROPERTY_FUNCTIONS(MCAPartitionKind); + PROPERTY_FUNCTIONS(MCAPartitionNumber); + PROPERTY_FUNCTIONS(MCATitle); + PROPERTY_FUNCTIONS(MCATitleVersion); + PROPERTY_FUNCTIONS(MCATitleSubVersion); + PROPERTY_FUNCTIONS(MCAEpisode); + PROPERTY_FUNCTIONS(RFC5646SpokenLanguage); + PROPERTY_FUNCTIONS(MCAAudioContentKind); + PROPERTY_FUNCTIONS(MCAAudioElementKind); + PROPERTY_FUNCTIONS(MCAContent); + PROPERTY_FUNCTIONS(MCAUseClass); + PROPERTY_FUNCTIONS(MCAContentSubtype); + PROPERTY_FUNCTIONS(MCAContentDifferentiator); + PROPERTY_FUNCTIONS(MCASpokenLanguageAttribute); + PROPERTY_FUNCTIONS(RFC5646AdditionalSpokenLanguages); + PROPERTY_FUNCTIONS(MCAAdditionalLanguageAttributes); + ADM_PROPERTY_FUNCTIONS(ADMAudioProgrammeID_ADMsg); + ADM_PROPERTY_FUNCTIONS(ADMAudioContentID_ADMsg); + ADM_PROPERTY_FUNCTIONS(ADMAudioObjectID_ADMsg); }; #define PROPERTY_FUNCTION_REFS(name) MCAPropertyFunctions::Set##name, MCAPropertyFunctions::Check##name @@ -219,6 +245,12 @@ struct MCAPropertyMapEntry { {"mcaspokenlanguageattribute", PROPERTY_FUNCTION_REFS(MCASpokenLanguageAttribute)}, {"rfc5646additionalspokenlanguages", PROPERTY_FUNCTION_REFS(RFC5646AdditionalSpokenLanguages)}, {"mcaadditionallanguageattributes", PROPERTY_FUNCTION_REFS(MCAAdditionalLanguageAttributes)}, + {"admaudioprogrammeid_admsg", PROPERTY_FUNCTION_REFS(ADMAudioProgrammeID_ADMsg)}, + {"admaudioprogrammeid", PROPERTY_FUNCTION_REFS(ADMAudioProgrammeID_ADMsg)}, // without "_admsg" suffix + {"admaudiocontentid_admsg", PROPERTY_FUNCTION_REFS(ADMAudioContentID_ADMsg)}, + {"admaudiocontentid", PROPERTY_FUNCTION_REFS(ADMAudioContentID_ADMsg)}, // without "_admsg" suffix + {"admaudioobjectid_admsg", PROPERTY_FUNCTION_REFS(ADMAudioObjectID_ADMsg)}, + {"admaudioobjectid", PROPERTY_FUNCTION_REFS(ADMAudioObjectID_ADMsg)}, // without "_admsg" suffix }; @@ -256,6 +288,8 @@ bool AppMCALabelHelper::ParseAudioLayoutMode(const string &audio_mode_str, UL *l *label = DEFAULT_LAYOUT_A_WITHOUT_MCA_LABEL; else if (audio_mode_str == "imf") *label = IMF_MCA_LABEL_FRAMEWORK; + else if (audio_mode_str == "adm") + *label = ADM_MCA_LABEL_FRAMEWORK; else return false; @@ -270,6 +304,7 @@ AppMCALabelHelper::AppMCALabelHelper(bool is_as11) IndexLabels(AS11_MCA_LABELS, BMX_ARRAY_SIZE(AS11_MCA_LABELS), true); if (is_as11) IndexLabels(AS11_OVERRIDE_MCA_LABELS, BMX_ARRAY_SIZE(AS11_OVERRIDE_MCA_LABELS), true); + IndexLabels(ADM_MCA_LABELS, BMX_ARRAY_SIZE(ADM_MCA_LABELS), true); // Generate numbered source audio labels char buffer[32]; @@ -518,7 +553,10 @@ void AppMCALabelHelper::InsertTrackLabels(ClipWriter *clip) sg_label_line.id.c_str()); } - sg_desc = pcm_track->AddSoundfieldGroupLabel(); + if (sg_label_line.label->dict_id == ADM_SG_DICT_ID) + sg_desc = pcm_track->AddADMSoundfieldGroupLabel(); + else + sg_desc = pcm_track->AddSoundfieldGroupLabel(); sg_desc->setMCALabelDictionaryID(sg_label_line.label->dict_id); sg_desc->setMCATagSymbol(sg_label_line.label->tag_symbol); if (sg_label_line.label->tag_name && sg_label_line.label->tag_name[0]) diff --git a/src/clip_writer/ClipWriterTrack.cpp b/src/clip_writer/ClipWriterTrack.cpp index 08caef17..329dbb42 100644 --- a/src/clip_writer/ClipWriterTrack.cpp +++ b/src/clip_writer/ClipWriterTrack.cpp @@ -1147,6 +1147,37 @@ GroupOfSoundfieldGroupsLabelSubDescriptor* ClipWriterTrack::AddGroupOfSoundfield return 0; } +ADMSoundfieldGroupLabelSubDescriptor* ClipWriterTrack::AddADMSoundfieldGroupLabel(ADMSoundfieldGroupLabelSubDescriptor *copy_from) +{ + switch (mClipType) + { + case CW_OP1A_CLIP_TYPE: + { + OP1APCMTrack *pcm_track = dynamic_cast(mOP1ATrack); + if (pcm_track) + return pcm_track->AddADMSoundfieldGroupLabel(copy_from); + break; + } + case CW_RDD9_CLIP_TYPE: + { + RDD9PCMTrack *pcm_track = dynamic_cast(mRDD9Track); + if (pcm_track) + return pcm_track->AddADMSoundfieldGroupLabel(copy_from); + break; + } + case CW_AS02_CLIP_TYPE: + case CW_AVID_CLIP_TYPE: + case CW_D10_CLIP_TYPE: + case CW_WAVE_CLIP_TYPE: + break; + case CW_UNKNOWN_CLIP_TYPE: + BMX_ASSERT(false); + break; + } + + return 0; +} + void ClipWriterTrack::AddADMAudioID(const WaveCHNA::AudioID &audio_id) { switch (mClipType) diff --git a/src/mxf_op1a/OP1APCMTrack.cpp b/src/mxf_op1a/OP1APCMTrack.cpp index 6db02636..9407924d 100644 --- a/src/mxf_op1a/OP1APCMTrack.cpp +++ b/src/mxf_op1a/OP1APCMTrack.cpp @@ -217,6 +217,24 @@ SoundfieldGroupLabelSubDescriptor* OP1APCMTrack::AddSoundfieldGroupLabel(Soundfi return desc; } +ADMSoundfieldGroupLabelSubDescriptor* OP1APCMTrack::AddADMSoundfieldGroupLabel(ADMSoundfieldGroupLabelSubDescriptor *copy_from) +{ + ADMSoundfieldGroupLabelSubDescriptor *desc; + if (copy_from) { + desc = dynamic_cast(copy_from->clone(mOP1AFile->GetHeaderMetadata())); + BMX_CHECK_M(desc, ("Copying non-ADM SG label descriptor")); + } else { + desc = new ADMSoundfieldGroupLabelSubDescriptor(mOP1AFile->GetHeaderMetadata()); + desc->setMCALinkID(generate_uuid()); + } + mMCALabels.push_back(desc); + + if (mOP1AFile->HavePreparedHeaderMetadata()) + mDescriptorHelper->GetFileDescriptor()->appendSubDescriptors(mMCALabels.back()); + + return desc; +} + GroupOfSoundfieldGroupsLabelSubDescriptor* OP1APCMTrack::AddGroupOfSoundfieldGroupLabel( GroupOfSoundfieldGroupsLabelSubDescriptor *copy_from) { diff --git a/src/rdd9_mxf/RDD9PCMTrack.cpp b/src/rdd9_mxf/RDD9PCMTrack.cpp index 5c8df626..e29fae6c 100644 --- a/src/rdd9_mxf/RDD9PCMTrack.cpp +++ b/src/rdd9_mxf/RDD9PCMTrack.cpp @@ -165,6 +165,24 @@ SoundfieldGroupLabelSubDescriptor* RDD9PCMTrack::AddSoundfieldGroupLabel(Soundfi return desc; } +ADMSoundfieldGroupLabelSubDescriptor* RDD9PCMTrack::AddADMSoundfieldGroupLabel(ADMSoundfieldGroupLabelSubDescriptor *copy_from) +{ + ADMSoundfieldGroupLabelSubDescriptor *desc; + if (copy_from) { + desc = dynamic_cast(copy_from->clone(mRDD9File->GetHeaderMetadata())); + BMX_CHECK_M(desc, ("Copying non-ADM SG label descriptor")); + } else { + desc = new ADMSoundfieldGroupLabelSubDescriptor(mRDD9File->GetHeaderMetadata()); + desc->setMCALinkID(generate_uuid()); + } + mMCALabels.push_back(desc); + + if (mRDD9File->HavePreparedHeaderMetadata()) + mDescriptorHelper->GetFileDescriptor()->appendSubDescriptors(mMCALabels.back()); + + return desc; +} + GroupOfSoundfieldGroupsLabelSubDescriptor* RDD9PCMTrack::AddGroupOfSoundfieldGroupLabel( GroupOfSoundfieldGroupsLabelSubDescriptor *copy_from) { diff --git a/test/wave_adm/mca_1.txt b/test/wave_adm/mca_1.txt new file mode 100644 index 00000000..761b93cd --- /dev/null +++ b/test/wave_adm/mca_1.txt @@ -0,0 +1,9 @@ +0 +chL, chan=0 +chR, chan=1 +sgADM, lang=eng, mca_title="Test Example 1", adm_audio_programme_id="APR_1001", adm_audio_content_id="ACO_1001", adm_audio_object_id="AO_1001" + +1 +chL, chan=0 +chR, chan=1 +sgADM, lang=eng, mca_title="Test Example 1", adm_audio_programme_id="APR_1001", adm_audio_content_id="ACO_1002", adm_audio_object_id="AO_1002" diff --git a/test/wave_adm/test.sh b/test/wave_adm/test.sh index 86e0aecc..67961679 100755 --- a/test/wave_adm/test.sh +++ b/test/wave_adm/test.sh @@ -168,6 +168,27 @@ create_mxf_4() >/dev/null } +create_mxf_5() +{ + # Create an MXF from a Wave+ADM and AVC-Intra. + # Map the audio channels to 2 stereo tracks + # Add ADM MCA labels + + $testdir/create_test_essence -t 7 -d 1 $tmpdir/video + + $appsdir/raw2bmx/raw2bmx \ + --regtest \ + -t op1a \ + -f 25 \ + -o $1 \ + --track-map "0,1;2,3" \ + --track-mca-labels adm $2 \ + --audio-layout adm \ + --avci100_1080i $tmpdir/video \ + --wave $base/adm_1.wav \ + >/dev/null +} + check() { @@ -202,7 +223,10 @@ check() diff $tmpdir/test.md5 $base/test_wave_6.md5 && create_mxf_4 $tmpdir/test_wav_3.wav $tmpdir/test.mxf && $md5tool < $tmpdir/test.mxf > $tmpdir/test.md5 && - diff $tmpdir/test.md5 $base/test_mxf_4.md5 + diff $tmpdir/test.md5 $base/test_mxf_4.md5 && + create_mxf_5 $tmpdir/test.mxf $base/mca_1.txt && + $md5tool < $tmpdir/test.mxf > $tmpdir/test.md5 && + diff $tmpdir/test.md5 $base/test_mxf_5.md5 } create_data() @@ -226,7 +250,9 @@ create_data() create_wave_6 $base/axml_1.xml $base/chna_1.txt $tmpdir/test.wav && $md5tool < $tmpdir/test.wav > $base/test_wave_6.md5 && create_mxf_4 $tmpdir/test_wave_3.wav $tmpdir/test.mxf && - $md5tool < $tmpdir/test.mxf > $base/test_mxf_4.md5 + $md5tool < $tmpdir/test.mxf > $base/test_mxf_4.md5 && + create_mxf_5 $tmpdir/test.mxf $base/mca_1.txt && + $md5tool < $tmpdir/test.mxf > $base/test_mxf_5.md5 } create_samples() @@ -240,7 +266,8 @@ create_samples() create_wave_4 $sampledir/test_mxf_3.mxf $sampledir/test_wave_4.wav && create_wave_5 $sampledir/test_wave_5.wav && create_wave_6 $base/axml_1.xml $base/chna_1.txt $sampledir/test_wave_6.wav && - create_mxf_4 $sampledir/test_wave_3.wav $sampledir/test_mxf_4.mxf + create_mxf_4 $sampledir/test_wave_3.wav $sampledir/test_mxf_4.mxf && + create_mxf_5 $sampledir/test_mxf_5.mxf $base/mca_1.txt } diff --git a/test/wave_adm/test_mxf_5.md5 b/test/wave_adm/test_mxf_5.md5 new file mode 100644 index 00000000..ad2ad9b8 --- /dev/null +++ b/test/wave_adm/test_mxf_5.md5 @@ -0,0 +1 @@ +a79843f81429f8777e0761ae23e2e75b - From b7fce02a298d5428db83e26f868695bc15e80483 Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Thu, 19 Jan 2023 09:28:45 +0000 Subject: [PATCH 21/65] Update how ADM SG Label Subdescriptor is processed --- apps/mxf2raw/mxf2raw.cpp | 106 +++++---- docs/audio_definition_model.md | 20 +- docs/mca_labels_format.md | 2 + include/bmx/apps/AppMCALabelHelper.h | 3 + include/bmx/mxf_reader/MXFMCALabelIndex.h | 2 + include/bmx/mxf_reader/MXFTrackInfo.h | 4 +- meta/mxf2raw/mxf2raw_info.xsd | 9 +- src/apps/AppMCALabelHelper.cpp | 73 ++++-- src/mxf_reader/MXFFileReader.cpp | 7 +- src/mxf_reader/MXFMCALabelIndex.cpp | 16 ++ test/wave_adm/mca_1.txt | 6 +- test/wave_adm/mca_2.txt | 16 ++ test/wave_adm/test.sh | 59 ++++- test/wave_adm/test_mxf_5.md5 | 2 +- test/wave_adm/test_mxf_5.xml | 246 ++++++++++++++++++++ test/wave_adm/test_mxf_6.md5 | 1 + test/wave_adm/test_mxf_6.xml | 271 ++++++++++++++++++++++ 17 files changed, 767 insertions(+), 76 deletions(-) create mode 100644 test/wave_adm/mca_2.txt create mode 100644 test/wave_adm/test_mxf_5.xml create mode 100644 test/wave_adm/test_mxf_6.md5 create mode 100644 test/wave_adm/test_mxf_6.xml diff --git a/apps/mxf2raw/mxf2raw.cpp b/apps/mxf2raw/mxf2raw.cpp index 52e4dc40..0657dab9 100644 --- a/apps/mxf2raw/mxf2raw.cpp +++ b/apps/mxf2raw/mxf2raw.cpp @@ -652,20 +652,31 @@ static void write_track_mca_label_info(AppInfoWriter *info_writer, MXFReader *re map gosg_labels; size_t i; for (i = 0; i < sound_info->mca_labels.size(); i++) { - AudioChannelLabelSubDescriptor *c_label = sound_info->mca_labels[i]; - if (c_label->haveMCAChannelID()) { - c_labels[c_label->getMCAChannelID()].push_back(c_label); - } else { - BMX_CHECK(sound_info->channel_count == 1); - c_labels[1].push_back(c_label); + AudioChannelLabelSubDescriptor *c_label = dynamic_cast(sound_info->mca_labels[i]); + ADMSoundfieldGroupLabelSubDescriptor *adm_sg_label = dynamic_cast(sound_info->mca_labels[i]); + SoundfieldGroupLabelSubDescriptor *sg_label = 0; + + if (c_label) { + if (c_label->haveMCAChannelID()) { + c_labels[c_label->getMCAChannelID()].push_back(c_label); + } else { + BMX_CHECK(sound_info->channel_count == 1); + c_labels[1].push_back(c_label); + } + + if (c_label->haveSoundfieldGroupLinkID()) { + UUID link_id = c_label->getSoundfieldGroupLinkID(); + MCALabelSubDescriptor *label = mca_label_index->FindLabel(link_id); + sg_label = dynamic_cast(label); + BMX_CHECK(sg_label); + } + } else if (adm_sg_label) { + // ADM Soundfield Group that is not referenced by a Audio Channel + sg_label = adm_sg_label; } - if (c_label->haveSoundfieldGroupLinkID()) { - UUID link_id = c_label->getSoundfieldGroupLinkID(); - MCALabelSubDescriptor *label = mca_label_index->FindLabel(link_id); - SoundfieldGroupLabelSubDescriptor *sg_label = dynamic_cast(label); - BMX_CHECK(sg_label); - sg_labels[link_id] = sg_label; + if (sg_label) { + sg_labels[sg_label->getMCALinkID()] = sg_label; if (sg_label->haveGroupOfSoundfieldGroupsLinkID()) { vector link_ids = sg_label->getGroupOfSoundfieldGroupsLinkID(); @@ -682,6 +693,7 @@ static void write_track_mca_label_info(AppInfoWriter *info_writer, MXFReader *re } string c_summary; + bool have_channel_label = false; uint32_t c; for (c = 0; c < sound_info->channel_count; c++) { uint32_t channel_id = c + 1; @@ -696,20 +708,26 @@ static void write_track_mca_label_info(AppInfoWriter *info_writer, MXFReader *re c_summary.append(","); c_summary.append(c_label->getMCATagSymbol()); } + have_channel_label = true; } else { c_summary.append("_"); } } - info_writer->WriteStringItem("channel_summary", c_summary); + if (have_channel_label) + info_writer->WriteStringItem("channel_summary", c_summary); if (!sg_labels.empty()) { string sg_summary; map::iterator sg_iter; for (sg_iter = sg_labels.begin(); sg_iter != sg_labels.end(); sg_iter++) { SoundfieldGroupLabelSubDescriptor *sg_label = sg_iter->second; + ADMSoundfieldGroupLabelSubDescriptor *adm_sg_label = dynamic_cast(sg_iter->second); if (sg_iter != sg_labels.begin()) sg_summary.append("; "); - sg_summary.append(sg_label->getMCATagSymbol()); + if (adm_sg_label) + sg_summary.append(sg_label->getMCATagSymbol() + "(ADM)"); + else + sg_summary.append(sg_label->getMCATagSymbol()); } info_writer->WriteStringItem("sg_summary", sg_summary); } @@ -728,36 +746,38 @@ static void write_track_mca_label_info(AppInfoWriter *info_writer, MXFReader *re if (mca_detail) { - info_writer->StartArrayItem("channels", sound_info->channel_count); - uint32_t c; - for (c = 0; c < sound_info->channel_count; c++) { - uint32_t channel_id = c + 1; - info_writer->StartArrayElement("channel", c); - info_writer->WriteIntegerItem("index", c); - info_writer->WriteIntegerItem("id", channel_id); - if (c_labels.count(channel_id)) { - vector &labels = c_labels[channel_id]; - info_writer->StartArrayItem("labels", labels.size()); - size_t l; - for (l = 0; l < labels.size(); l++) { - AudioChannelLabelSubDescriptor *c_label = labels[l]; - info_writer->StartArrayElement("channel_label", l); - write_mca_label_info(info_writer, c_label); - if (c_label->haveSoundfieldGroupLinkID()) { - UUID link_id = c_label->getSoundfieldGroupLinkID(); - SoundfieldGroupLabelSubDescriptor *sg_label = sg_labels.at(link_id); - info_writer->StartAnnotations(); - info_writer->WriteStringItem("tag_symbol", sg_label->getMCATagSymbol()); - info_writer->EndAnnotations(); - info_writer->WriteIDAUItem("sg_link_id", link_id); + if (have_channel_label) { + info_writer->StartArrayItem("channels", sound_info->channel_count); + uint32_t c; + for (c = 0; c < sound_info->channel_count; c++) { + uint32_t channel_id = c + 1; + info_writer->StartArrayElement("channel", c); + info_writer->WriteIntegerItem("index", c); + info_writer->WriteIntegerItem("id", channel_id); + if (c_labels.count(channel_id)) { + vector &labels = c_labels[channel_id]; + info_writer->StartArrayItem("labels", labels.size()); + size_t l; + for (l = 0; l < labels.size(); l++) { + AudioChannelLabelSubDescriptor *c_label = labels[l]; + info_writer->StartArrayElement("channel_label", l); + write_mca_label_info(info_writer, c_label); + if (c_label->haveSoundfieldGroupLinkID()) { + UUID link_id = c_label->getSoundfieldGroupLinkID(); + SoundfieldGroupLabelSubDescriptor *sg_label = sg_labels.at(link_id); + info_writer->StartAnnotations(); + info_writer->WriteStringItem("tag_symbol", sg_label->getMCATagSymbol()); + info_writer->EndAnnotations(); + info_writer->WriteIDAUItem("sg_link_id", link_id); + } + info_writer->EndArrayElement(); } - info_writer->EndArrayElement(); + info_writer->EndArrayItem(); } - info_writer->EndArrayItem(); + info_writer->EndArrayElement(); } - info_writer->EndArrayElement(); + info_writer->EndArrayItem(); } - info_writer->EndArrayItem(); if (!sg_labels.empty()) { info_writer->StartArrayItem("soundfield_groups", sg_labels.size()); @@ -765,7 +785,11 @@ static void write_track_mca_label_info(AppInfoWriter *info_writer, MXFReader *re map::iterator iter; for (iter = sg_labels.begin(), index = 0; iter != sg_labels.end(); iter++, index++) { SoundfieldGroupLabelSubDescriptor *sg_label = iter->second; - info_writer->StartArrayElement("soundfield_group", index); + ADMSoundfieldGroupLabelSubDescriptor *adm_sg_label = dynamic_cast(iter->second); + if (adm_sg_label) + info_writer->StartArrayElement("adm_soundfield_group", index); + else + info_writer->StartArrayElement("soundfield_group", index); write_mca_label_info(info_writer, sg_label); if (sg_label->haveGroupOfSoundfieldGroupsLinkID()) { vector gosg_link_ids = sg_label->getGroupOfSoundfieldGroupsLinkID(); diff --git a/docs/audio_definition_model.md b/docs/audio_definition_model.md index 1d4e6dfd..ef9c0689 100644 --- a/docs/audio_definition_model.md +++ b/docs/audio_definition_model.md @@ -75,18 +75,30 @@ The `--track-map` option can be used to change what is output. For example, reor ## Add ADM MCA labels to MXF+ADM -An ADM Soundfield Group MCA label can be added using the `sgADM` symbol in a [MCA labels text file](./mca_labels_format.md): +A ADM Soundfield Group Label Subdescriptor is created from a [MCA labels text file](./mca_labels_format.md) if the list of properties associated with the Soundfield Group contains an ADM property (the ADM properties have the prefix "ADM") or it is a ADM Soundfield Group label and there are no Audio Channels that reference it. + +A ADM Soundfield Group label can be added using the `ADM` symbol in a [MCA labels text file](./mca_labels_format.md). `mca.txt`: ``` 0 chL, chan=0 chR, chan=1 -sgADM, lang=eng, mca_title="Example Programme", adm_audio_programme_id="APR_1001", adm_audio_content_id="ACO_1001", adm_audio_object_id="AO_1001" +sgST, lang=eng, mca_title="Example Programme" +ADM, adm_audio_object_id="AO_1001" + +1 +chL, chan=0 +chR, chan=1 +sgST, lang=eng, mca_title="Example Programme" +ADM, adm_audio_object_id="AO_1002" ``` -The MCA labels defined in `mca.txt` can be added and the ADM-described content label can be set in the audio descriptor Channel Assignment property using the following example commandline: -`raw2bmx -t op1a -o output.mxf --track-map '0,1' --track-mca-labels adm mca.txt --audio-layout adm --wave input.wave` +The MCA labels defined in `mca.txt` can be added and the ADM-described content label can be set in the audio descriptor Channel Assignment property using the following example commandline: (_note_: the `x` in `--track-mca-labels` is a legacy option component and will be ignored) + +`raw2bmx -t op1a -o output.mxf --track-map '0,1' --track-mca-labels x mca.txt --audio-layout adm --wave input.wave` + +The Soundfield Groups that use the ADM Soundfield Group Label Subdescriptor are shown using a `(ADM)` suffix in the summary output of `mxf2raw`. E.g. `ADM(ADM)` in the example `mca.txt` above. If the `--mca-detail` option is used and the Soundfield Group uses the ADM Soundfield Group Label Subdescriptor then the name used in the `SoundfieldGroups` array is `ADMSoundfieldGroup`. ## chna Text File Definition Format diff --git a/docs/mca_labels_format.md b/docs/mca_labels_format.md index 2e1a0443..4f28f422 100644 --- a/docs/mca_labels_format.md +++ b/docs/mca_labels_format.md @@ -109,3 +109,5 @@ chR sgST, id=sg1, repeat=false ggAPg, id=gosg1, repeat=false ``` + +See [audio_definition_model.md](./audio_definition_model.md#add-adm-mca-labels-to-mxfadm) for an example that uses the ADM properties. diff --git a/include/bmx/apps/AppMCALabelHelper.h b/include/bmx/apps/AppMCALabelHelper.h index 228990f2..6c009acb 100644 --- a/include/bmx/apps/AppMCALabelHelper.h +++ b/include/bmx/apps/AppMCALabelHelper.h @@ -35,6 +35,7 @@ #include #include #include +#include #include @@ -117,12 +118,14 @@ class AppMCALabelHelper uint32_t channel_index; // starts from 0. Note that the descriptor ChannelID starts from 1! bool repeat; std::vector > string_properties; + bool adm_sg_subdesc; }; class SoundfieldGroup { public: void Reset(); + bool IsNull() const { return !sg_label_line.label; } LabelLine sg_label_line; // can be 'null', indicating that the channels are not assigned to a soundfield group std::vector c_label_lines; diff --git a/include/bmx/mxf_reader/MXFMCALabelIndex.h b/include/bmx/mxf_reader/MXFMCALabelIndex.h index f8fae436..ae1c4388 100644 --- a/include/bmx/mxf_reader/MXFMCALabelIndex.h +++ b/include/bmx/mxf_reader/MXFMCALabelIndex.h @@ -52,6 +52,8 @@ class MXFMCALabelIndex void RegisterLabel(mxfpp::MCALabelSubDescriptor *label); void RegisterLabels(const MXFMCALabelIndex *from_index); + bool IsReferenced(mxfpp::SoundfieldGroupLabelSubDescriptor *sg_label); + void CheckReferences(mxfpp::MCALabelSubDescriptor *label); public: diff --git a/include/bmx/mxf_reader/MXFTrackInfo.h b/include/bmx/mxf_reader/MXFTrackInfo.h index c3cfefb2..876af405 100644 --- a/include/bmx/mxf_reader/MXFTrackInfo.h +++ b/include/bmx/mxf_reader/MXFTrackInfo.h @@ -42,7 +42,7 @@ namespace mxfpp { - class AudioChannelLabelSubDescriptor; + class MCALabelSubDescriptor; }; @@ -135,7 +135,7 @@ class MXFSoundTrackInfo : public MXFTrackInfo BMX_OPT_PROP_DECL(int8_t, audio_ref_level); BMX_OPT_PROP_DECL(int8_t, dial_norm); UL channel_assignment; - std::vector mca_labels; + std::vector mca_labels; }; diff --git a/meta/mxf2raw/mxf2raw_info.xsd b/meta/mxf2raw/mxf2raw_info.xsd index 42fe5059..7802a801 100644 --- a/meta/mxf2raw/mxf2raw_info.xsd +++ b/meta/mxf2raw/mxf2raw_info.xsd @@ -427,11 +427,18 @@ + + + + + + + - + diff --git a/src/apps/AppMCALabelHelper.cpp b/src/apps/AppMCALabelHelper.cpp index 4d56a813..b2201379 100644 --- a/src/apps/AppMCALabelHelper.cpp +++ b/src/apps/AppMCALabelHelper.cpp @@ -173,7 +173,7 @@ static const UL ADM_SG_DICT_ID = {0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x0d static const MCALabelEntry ADM_MCA_LABELS[] = { // Soundfield Groups - {SOUNDFIELD_GROUP_LABEL, "sgADM", "ADM", ADM_SG_DICT_ID}, + {SOUNDFIELD_GROUP_LABEL, "ADM", "ADM", ADM_SG_DICT_ID}, }; @@ -245,6 +245,7 @@ struct MCAPropertyMapEntry { {"mcaspokenlanguageattribute", PROPERTY_FUNCTION_REFS(MCASpokenLanguageAttribute)}, {"rfc5646additionalspokenlanguages", PROPERTY_FUNCTION_REFS(RFC5646AdditionalSpokenLanguages)}, {"mcaadditionallanguageattributes", PROPERTY_FUNCTION_REFS(MCAAdditionalLanguageAttributes)}, + // ADM propertues will be identified by the "adm" prefix in AppMCALabelHelper {"admaudioprogrammeid_admsg", PROPERTY_FUNCTION_REFS(ADMAudioProgrammeID_ADMsg)}, {"admaudioprogrammeid", PROPERTY_FUNCTION_REFS(ADMAudioProgrammeID_ADMsg)}, // without "_admsg" suffix {"admaudiocontentid_admsg", PROPERTY_FUNCTION_REFS(ADMAudioContentID_ADMsg)}, @@ -266,6 +267,7 @@ void AppMCALabelHelper::LabelLine::Reset() channel_index = (uint32_t)(-1); repeat = true; string_properties.clear(); + adm_sg_subdesc = false; } @@ -553,7 +555,7 @@ void AppMCALabelHelper::InsertTrackLabels(ClipWriter *clip) sg_label_line.id.c_str()); } - if (sg_label_line.label->dict_id == ADM_SG_DICT_ID) + if (sg_label_line.adm_sg_subdesc) sg_desc = pcm_track->AddADMSoundfieldGroupLabel(); else sg_desc = pcm_track->AddSoundfieldGroupLabel(); @@ -643,7 +645,8 @@ void AppMCALabelHelper::ParseTrackLines(const vector &lines) track_labels = new TrackLabels(); track_labels->track_index = track_index; - SoundfieldGroup sg; + vector sgs; + SoundfieldGroup next_sg; size_t i; for (i = 1; i < lines.size(); i++) { LabelLine label_line = ParseLabelLine(lines[i]); @@ -651,28 +654,60 @@ void AppMCALabelHelper::ParseTrackLines(const vector &lines) continue; if (label_line.label->type == AUDIO_CHANNEL_LABEL) { - if (!sg.gosg_label_lines.empty() || sg.sg_label_line.label) { - track_labels->soundfield_groups.push_back(sg); - sg.Reset(); + // Add all the SGs created for this track before this CH + if (!sgs.empty()) { + track_labels->soundfield_groups.insert(track_labels->soundfield_groups.end(), sgs.begin(), sgs.end()); + sgs.clear(); } - sg.c_label_lines.push_back(label_line); + + next_sg.c_label_lines.push_back(label_line); + } else if (label_line.label->type == SOUNDFIELD_GROUP_LABEL) { - if (sg.c_label_lines.empty()) - throw BMXException("No channels in soundfield group"); - if (sg.sg_label_line.label) - throw BMXException("Multiple soundfield group labels"); - sg.sg_label_line = label_line; + // The ADM SG sub-descriptor allows the SG to have no references from CH. + // The ADM SG sub-descriptor also allows multiple SGs in a track. + // If there are no ADM properties present (!adm_sg_subdesc) then force a + // "ADM" SG label to use the ADM SG sub-descriptor if the conditions fail below + if (!label_line.adm_sg_subdesc) { + if (next_sg.c_label_lines.empty()) { + if (label_line.label->dict_id == ADM_SG_DICT_ID) + label_line.adm_sg_subdesc = true; + else + throw BMXException("No channels in soundfield group"); + } + if (!sgs.empty()) { + if (label_line.label->dict_id == ADM_SG_DICT_ID) + label_line.adm_sg_subdesc = true; + else + throw BMXException("Multiple soundfield group labels"); + } + } + + next_sg.sg_label_line = label_line; + sgs.push_back(next_sg); + next_sg.Reset(); + } else { // GROUP_OF_SOUNDFIELD_GROUP_LABEL - if (!sg.sg_label_line.label) + if (sgs.empty()) throw BMXException("No soundfield group label before group of soundfield groups label"); - sg.gosg_label_lines.push_back(label_line); + + // Add the GOSG to all SG that came before it + size_t k; + for (k = 0; k < sgs.size(); k++) { + SoundfieldGroup &sg = sgs[k]; + sg.gosg_label_lines.push_back(label_line); + } } } - if (!sg.gosg_label_lines.empty() || sg.sg_label_line.label || !sg.c_label_lines.empty()) { - track_labels->soundfield_groups.push_back(sg); - sg.Reset(); + + // Add the remaining placeholder SG (sg_label_line not set) that is used to carry the CHs + if (!next_sg.c_label_lines.empty()) { + sgs.push_back(next_sg); + next_sg.Reset(); } + // Add all the SGs created for this track + track_labels->soundfield_groups.insert(track_labels->soundfield_groups.end(), sgs.begin(), sgs.end()); + mTrackLabels.push_back(track_labels); mTrackLabelsByTrackIndex[track_index] = track_labels; } @@ -922,6 +957,10 @@ AppMCALabelHelper::LabelLine AppMCALabelHelper::ParseLabelLine(const string &lin throw BMXException("Unknown MCA label property '%s', %s", name.c_str()); } + // If there are ADM properties then the ADM SG subdescriptor must be used + if (map_name.compare(0, 3, "adm") == 0) + label_line.adm_sg_subdesc = true; + label_line.string_properties.push_back(make_pair(map_name, value)); } } diff --git a/src/mxf_reader/MXFFileReader.cpp b/src/mxf_reader/MXFFileReader.cpp index 9ea30407..7b268d91 100644 --- a/src/mxf_reader/MXFFileReader.cpp +++ b/src/mxf_reader/MXFFileReader.cpp @@ -2077,12 +2077,13 @@ void MXFFileReader::IndexMCALabels(GenericDescriptor *descriptor) void MXFFileReader::ProcessMCALabels(FileDescriptor *file_desc, MXFSoundTrackInfo *sound_track_info) { - vector mca_labels; + vector mca_labels; if (file_desc->haveSubDescriptors()) { vector sub_descs = file_desc->getSubDescriptors(); size_t i; for (i = 0; i < sub_descs.size(); i++) { AudioChannelLabelSubDescriptor *c_label = dynamic_cast(sub_descs[i]); + ADMSoundfieldGroupLabelSubDescriptor *adm_sg_label = dynamic_cast(sub_descs[i]); if (c_label) { if (sound_track_info->channel_count == 0) { BMX_EXCEPTION(("MCA channel label in track containing 0 channels")); @@ -2101,6 +2102,10 @@ void MXFFileReader::ProcessMCALabels(FileDescriptor *file_desc, MXFSoundTrackInf } mMCALabelIndex->CheckReferences(c_label); mca_labels.push_back(c_label); + } else if (adm_sg_label && !mMCALabelIndex->IsReferenced(adm_sg_label)) { + // Add ADM Soundfield Group labels that are not referenced by a Channel label + mMCALabelIndex->CheckReferences(adm_sg_label); + mca_labels.push_back(adm_sg_label); } } } diff --git a/src/mxf_reader/MXFMCALabelIndex.cpp b/src/mxf_reader/MXFMCALabelIndex.cpp index 4a95e882..7a9be123 100644 --- a/src/mxf_reader/MXFMCALabelIndex.cpp +++ b/src/mxf_reader/MXFMCALabelIndex.cpp @@ -94,6 +94,22 @@ void MXFMCALabelIndex::CheckReferences(MCALabelSubDescriptor *label) } } +bool MXFMCALabelIndex::IsReferenced(SoundfieldGroupLabelSubDescriptor *sg_label) +{ + map::const_iterator iter; + for (iter = mLabels.begin(); iter != mLabels.end(); iter++) { + AudioChannelLabelSubDescriptor *ch_label = dynamic_cast(iter->second); + if (ch_label && + ch_label->haveSoundfieldGroupLinkID() && + ch_label->getSoundfieldGroupLinkID() == sg_label->getMCALinkID()) + { + return true; + } + } + + return false; +} + MCALabelSubDescriptor* MXFMCALabelIndex::FindLabel(mxfUUID link_id) const { if (mLabels.count(link_id)) diff --git a/test/wave_adm/mca_1.txt b/test/wave_adm/mca_1.txt index 761b93cd..f84f5692 100644 --- a/test/wave_adm/mca_1.txt +++ b/test/wave_adm/mca_1.txt @@ -1,9 +1,11 @@ 0 chL, chan=0 chR, chan=1 -sgADM, lang=eng, mca_title="Test Example 1", adm_audio_programme_id="APR_1001", adm_audio_content_id="ACO_1001", adm_audio_object_id="AO_1001" +sgST, lang=eng, mca_title="Test Example 1" +ADM, adm_audio_programme_id="APR_1001", adm_audio_content_id="ACO_1001", adm_audio_object_id="AO_1001" 1 chL, chan=0 chR, chan=1 -sgADM, lang=eng, mca_title="Test Example 1", adm_audio_programme_id="APR_1001", adm_audio_content_id="ACO_1002", adm_audio_object_id="AO_1002" +sgST, lang=eng, mca_title="Test Example 1" +ADM, adm_audio_programme_id="APR_1001", adm_audio_content_id="ACO_1002", adm_audio_object_id="AO_1002" diff --git a/test/wave_adm/mca_2.txt b/test/wave_adm/mca_2.txt new file mode 100644 index 00000000..dafcbdd4 --- /dev/null +++ b/test/wave_adm/mca_2.txt @@ -0,0 +1,16 @@ +# Test ADM Soundfield Group label only +0 +ADM + +# Test ADM Soundfield Group label with Channel label +1 +chM1, chan=0 +ADM + +# Test 377-41 Soundfield Group label and 2 Soundfield Group labels using the ADM sub-descriptor +2 +chL, chan=0 +chR, chan=1 +sgST +sgST, adm_audio_object_id="AO_1001" +sgST, adm_audio_object_id="AO_1002" diff --git a/test/wave_adm/test.sh b/test/wave_adm/test.sh index 67961679..c6e21ef6 100755 --- a/test/wave_adm/test.sh +++ b/test/wave_adm/test.sh @@ -172,7 +172,7 @@ create_mxf_5() { # Create an MXF from a Wave+ADM and AVC-Intra. # Map the audio channels to 2 stereo tracks - # Add ADM MCA labels + # Add ADM MCA labels from mca_1.txt $testdir/create_test_essence -t 7 -d 1 $tmpdir/video @@ -182,11 +182,48 @@ create_mxf_5() -f 25 \ -o $1 \ --track-map "0,1;2,3" \ - --track-mca-labels adm $2 \ + --track-mca-labels x $base/mca_1.txt \ --audio-layout adm \ --avci100_1080i $tmpdir/video \ --wave $base/adm_1.wav \ >/dev/null + + $appsdir/mxf2raw/mxf2raw \ + --regtest \ + --info \ + --info-format xml \ + --info-file $2 \ + --mca-detail \ + $1 +} + +create_mxf_6() +{ + # Create an MXF from a Wave+ADM and AVC-Intra. + # Map the audio channels to mono, mono and stereo tracks + # Add ADM MCA labels from mca_2.txt + + $testdir/create_test_essence -t 7 -d 1 $tmpdir/video + + $appsdir/raw2bmx/raw2bmx \ + --regtest \ + -t op1a \ + -f 25 \ + -o $1 \ + --track-map "0;1;2,3" \ + --track-mca-labels x $base/mca_2.txt \ + --audio-layout adm \ + --avci100_1080i $tmpdir/video \ + --wave $base/adm_1.wav \ + >/dev/null + + $appsdir/mxf2raw/mxf2raw \ + --regtest \ + --info \ + --info-format xml \ + --info-file $2 \ + --mca-detail \ + $1 } @@ -224,9 +261,14 @@ check() create_mxf_4 $tmpdir/test_wav_3.wav $tmpdir/test.mxf && $md5tool < $tmpdir/test.mxf > $tmpdir/test.md5 && diff $tmpdir/test.md5 $base/test_mxf_4.md5 && - create_mxf_5 $tmpdir/test.mxf $base/mca_1.txt && + create_mxf_5 $tmpdir/test.mxf $tmpdir/test.xml && + $md5tool < $tmpdir/test.mxf > $tmpdir/test.md5 && + diff $tmpdir/test.md5 $base/test_mxf_5.md5 && + diff $tmpdir/test.xml $base/test_mxf_5.xml && + create_mxf_6 $tmpdir/test.mxf $tmpdir/test.xml && $md5tool < $tmpdir/test.mxf > $tmpdir/test.md5 && - diff $tmpdir/test.md5 $base/test_mxf_5.md5 + diff $tmpdir/test.md5 $base/test_mxf_6.md5 && + diff $tmpdir/test.xml $base/test_mxf_6.xml } create_data() @@ -251,8 +293,10 @@ create_data() $md5tool < $tmpdir/test.wav > $base/test_wave_6.md5 && create_mxf_4 $tmpdir/test_wave_3.wav $tmpdir/test.mxf && $md5tool < $tmpdir/test.mxf > $base/test_mxf_4.md5 && - create_mxf_5 $tmpdir/test.mxf $base/mca_1.txt && - $md5tool < $tmpdir/test.mxf > $base/test_mxf_5.md5 + create_mxf_5 $tmpdir/test.mxf $base/test_mxf_5.xml && + $md5tool < $tmpdir/test.mxf > $base/test_mxf_5.md5 && + create_mxf_6 $tmpdir/test.mxf $base/test_mxf_6.xml && + $md5tool < $tmpdir/test.mxf > $base/test_mxf_6.md5 } create_samples() @@ -267,7 +311,8 @@ create_samples() create_wave_5 $sampledir/test_wave_5.wav && create_wave_6 $base/axml_1.xml $base/chna_1.txt $sampledir/test_wave_6.wav && create_mxf_4 $sampledir/test_wave_3.wav $sampledir/test_mxf_4.mxf && - create_mxf_5 $sampledir/test_mxf_5.mxf $base/mca_1.txt + create_mxf_5 $sampledir/test_mxf_5.mxf $sampledir/test_mxf_5.xml && + create_mxf_6 $sampledir/test_mxf_6.mxf $sampledir/test_mxf_6.xml } diff --git a/test/wave_adm/test_mxf_5.md5 b/test/wave_adm/test_mxf_5.md5 index ad2ad9b8..7e459694 100644 --- a/test/wave_adm/test_mxf_5.md5 +++ b/test/wave_adm/test_mxf_5.md5 @@ -1 +1 @@ -a79843f81429f8777e0761ae23e2e75b - +480a1e7634d7a9b7e0cc500e762abb8c - diff --git a/test/wave_adm/test_mxf_5.xml b/test/wave_adm/test_mxf_5.xml new file mode 100644 index 00000000..97cc4665 --- /dev/null +++ b/test/wave_adm/test_mxf_5.xml @@ -0,0 +1,246 @@ + + + + mxf2raw + RegLib + 0.0.0 + 1970-01-01T00:00:00.000Z + regtest-head + + + + regtest_file_uri + 1.3 + OP1A + true + + + urn:uuid:00000000-0000-0000-0000-000000000001 + RegCo + RegLib + 1.0.0.0.0 + 0.0.0 + urn:uuid:00000000-0000-0000-0000-000000000000 + 1000-01-01T00:00:00 + 1.0.0.0.0 + libMXF (Linux) + + + + + urn:smpte:umid:00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000001 + 1000-01-01T00:00:00 + 1000-01-01T00:00:00 + + + + + urn:smpte:umid:00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000002 + 1000-01-01T00:00:00 + 1000-01-01T00:00:00 + + + + + + 25/1 + 00:00:00:01 + + 00:00:00:00 + 00:00:00:00 + + + + Picture + AVCI_100_1080i + urn:smpte:ul:060e2b34.0401010a.0d010301.02106001 + 25/1 + 00:00:00:01 + + + + urn:smpte:umid:00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000001 + 1001 + 0 + + + urn:smpte:umid:00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000002 + 1001 + 0x15010500 + regtest_file_uri + + + + + urn:smpte:ul:060e2b34.0401010a.04010202.01323102 + SMPTE_274 + Separate_Fields + 1920 + 1080 + 1920 + 1080 + 16/9 + true + + 10 + 2 + 1 + Cositing + + + + + Sound + WAVE_PCM + urn:smpte:ul:060e2b34.04010101.0d010301.02060100 + 25/1 + 00:00:00:01 + + + + urn:smpte:umid:00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000001 + 2001 + 0 + + + urn:smpte:umid:00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000002 + 2001 + 0x16020100 + regtest_file_uri + + + + + 48000/1 + 24 + 6 + 2 + urn:smpte:ul:060e2b34.0401010d.04020210.05010000 + + chL; chR + sgST; ADM(ADM) + + + 0 + 1 + + + urn:uuid:00000000-0000-0000-0000-000000010002 + urn:smpte:ul:060e2b34.0401010d.03020101.00000000 + chL + Left + urn:uuid:00000000-0000-0000-0000-000000010001 + + + + + 1 + 2 + + + urn:uuid:00000000-0000-0000-0000-000000010003 + urn:smpte:ul:060e2b34.0401010d.03020102.00000000 + chR + Right + urn:uuid:00000000-0000-0000-0000-000000010001 + + + + + + + urn:uuid:00000000-0000-0000-0000-000000010001 + urn:smpte:ul:060e2b34.0401010d.03020220.01000000 + sgST + Standard Stereo + eng + + + urn:uuid:00000000-0000-0000-0000-000000010004 + urn:smpte:ul:060e2b34.0401010d.03020223.00000000 + ADM + ADM + + + + + + + Sound + WAVE_PCM + urn:smpte:ul:060e2b34.04010101.0d010301.02060100 + 25/1 + 00:00:00:01 + + + + urn:smpte:umid:00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000001 + 2002 + 0 + + + urn:smpte:umid:00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000002 + 2002 + 0x16020101 + regtest_file_uri + + + + + 48000/1 + 24 + 6 + 2 + urn:smpte:ul:060e2b34.0401010d.04020210.05010000 + + chL; chR + sgST; ADM(ADM) + + + 0 + 1 + + + urn:uuid:00000000-0000-0000-0000-000000010006 + urn:smpte:ul:060e2b34.0401010d.03020101.00000000 + chL + Left + urn:uuid:00000000-0000-0000-0000-000000010005 + + + + + 1 + 2 + + + urn:uuid:00000000-0000-0000-0000-000000010007 + urn:smpte:ul:060e2b34.0401010d.03020102.00000000 + chR + Right + urn:uuid:00000000-0000-0000-0000-000000010005 + + + + + + + urn:uuid:00000000-0000-0000-0000-000000010005 + urn:smpte:ul:060e2b34.0401010d.03020220.01000000 + sgST + Standard Stereo + eng + + + urn:uuid:00000000-0000-0000-0000-000000010008 + urn:smpte:ul:060e2b34.0401010d.03020223.00000000 + ADM + ADM + + + + + + + + diff --git a/test/wave_adm/test_mxf_6.md5 b/test/wave_adm/test_mxf_6.md5 new file mode 100644 index 00000000..4c468904 --- /dev/null +++ b/test/wave_adm/test_mxf_6.md5 @@ -0,0 +1 @@ +1c510bc7fea06f2183a57c7e12110d16 - diff --git a/test/wave_adm/test_mxf_6.xml b/test/wave_adm/test_mxf_6.xml new file mode 100644 index 00000000..e36823e4 --- /dev/null +++ b/test/wave_adm/test_mxf_6.xml @@ -0,0 +1,271 @@ + + + + mxf2raw + RegLib + 0.0.0 + 1970-01-01T00:00:00.000Z + regtest-head + + + + regtest_file_uri + 1.3 + OP1A + true + + + urn:uuid:00000000-0000-0000-0000-000000000001 + RegCo + RegLib + 1.0.0.0.0 + 0.0.0 + urn:uuid:00000000-0000-0000-0000-000000000000 + 1000-01-01T00:00:00 + 1.0.0.0.0 + libMXF (Linux) + + + + + urn:smpte:umid:00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000001 + 1000-01-01T00:00:00 + 1000-01-01T00:00:00 + + + + + urn:smpte:umid:00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000002 + 1000-01-01T00:00:00 + 1000-01-01T00:00:00 + + + + + + 25/1 + 00:00:00:01 + + 00:00:00:00 + 00:00:00:00 + + + + Picture + AVCI_100_1080i + urn:smpte:ul:060e2b34.0401010a.0d010301.02106001 + 25/1 + 00:00:00:01 + + + + urn:smpte:umid:00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000001 + 1001 + 0 + + + urn:smpte:umid:00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000002 + 1001 + 0x15010500 + regtest_file_uri + + + + + urn:smpte:ul:060e2b34.0401010a.04010202.01323102 + SMPTE_274 + Separate_Fields + 1920 + 1080 + 1920 + 1080 + 16/9 + true + + 10 + 2 + 1 + Cositing + + + + + Sound + WAVE_PCM + urn:smpte:ul:060e2b34.04010101.0d010301.02060100 + 25/1 + 00:00:00:01 + + + + urn:smpte:umid:00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000001 + 2001 + 0 + + + urn:smpte:umid:00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000002 + 2001 + 0x16030100 + regtest_file_uri + + + + + 48000/1 + 24 + 3 + 1 + urn:smpte:ul:060e2b34.0401010d.04020210.05010000 + + ADM(ADM) + + + urn:uuid:00000000-0000-0000-0000-000000010001 + urn:smpte:ul:060e2b34.0401010d.03020223.00000000 + ADM + ADM + + + + + + + Sound + WAVE_PCM + urn:smpte:ul:060e2b34.04010101.0d010301.02060100 + 25/1 + 00:00:00:01 + + + + urn:smpte:umid:00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000001 + 2002 + 0 + + + urn:smpte:umid:00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000002 + 2002 + 0x16030101 + regtest_file_uri + + + + + 48000/1 + 24 + 3 + 1 + urn:smpte:ul:060e2b34.0401010d.04020210.05010000 + + chM1 + ADM + + + 0 + 1 + + + urn:uuid:00000000-0000-0000-0000-000000010003 + urn:smpte:ul:060e2b34.0401010d.03020120.01000000 + chM1 + Mono One + urn:uuid:00000000-0000-0000-0000-000000010002 + + + + + + + urn:uuid:00000000-0000-0000-0000-000000010002 + urn:smpte:ul:060e2b34.0401010d.03020223.00000000 + ADM + ADM + + + + + + + Sound + WAVE_PCM + urn:smpte:ul:060e2b34.04010101.0d010301.02060100 + 25/1 + 00:00:00:01 + + + + urn:smpte:umid:00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000001 + 2003 + 0 + + + urn:smpte:umid:00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000002 + 2003 + 0x16030102 + regtest_file_uri + + + + + 48000/1 + 24 + 6 + 2 + urn:smpte:ul:060e2b34.0401010d.04020210.05010000 + + chL; chR + sgST; sgST(ADM); sgST(ADM) + + + 0 + 1 + + + urn:uuid:00000000-0000-0000-0000-000000010005 + urn:smpte:ul:060e2b34.0401010d.03020101.00000000 + chL + Left + urn:uuid:00000000-0000-0000-0000-000000010004 + + + + + 1 + 2 + + + urn:uuid:00000000-0000-0000-0000-000000010006 + urn:smpte:ul:060e2b34.0401010d.03020102.00000000 + chR + Right + urn:uuid:00000000-0000-0000-0000-000000010004 + + + + + + + urn:uuid:00000000-0000-0000-0000-000000010004 + urn:smpte:ul:060e2b34.0401010d.03020220.01000000 + sgST + Standard Stereo + + + urn:uuid:00000000-0000-0000-0000-000000010007 + urn:smpte:ul:060e2b34.0401010d.03020220.01000000 + sgST + Standard Stereo + + + urn:uuid:00000000-0000-0000-0000-000000010008 + urn:smpte:ul:060e2b34.0401010d.03020220.01000000 + sgST + Standard Stereo + + + + + + + + From 8dff699fa6f9c631b0534b906afc90a468e05be1 Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Thu, 19 Jan 2023 09:29:41 +0000 Subject: [PATCH 22/65] Support ADM with only a chna --- apps/bmxtranswrap/bmxtranswrap.cpp | 2 +- apps/raw2bmx/raw2bmx.cpp | 5 ++ docs/audio_definition_model.md | 6 ++- include/bmx/wave/WaveTrackWriter.h | 1 - src/mxf_reader/MXFFileTrackReader.cpp | 6 +-- test/wave_adm/test.sh | 70 +++++++++++++++++++++++++-- test/wave_adm/test_mxf_7.md5 | 1 + test/wave_adm/test_wave_7.md5 | 1 + test/wave_adm/test_wave_8.md5 | 1 + 9 files changed, 83 insertions(+), 10 deletions(-) create mode 100644 test/wave_adm/test_mxf_7.md5 create mode 100644 test/wave_adm/test_wave_7.md5 create mode 100644 test/wave_adm/test_wave_8.md5 diff --git a/apps/bmxtranswrap/bmxtranswrap.cpp b/apps/bmxtranswrap/bmxtranswrap.cpp index 46b74286..94c67edd 100644 --- a/apps/bmxtranswrap/bmxtranswrap.cpp +++ b/apps/bmxtranswrap/bmxtranswrap.cpp @@ -4439,7 +4439,7 @@ int main(int argc, const char** argv) WaveCHNA::AudioID &audio_id = audio_ids[k]; // + 1 because the chna track_index starts at 1 - audio_id.track_index = wave_track->GetStartChannel() + output_channel_index + 1; + audio_id.track_index = output_channel_index + 1; wave_track->AddADMAudioID(audio_id); } } diff --git a/apps/raw2bmx/raw2bmx.cpp b/apps/raw2bmx/raw2bmx.cpp index c25fd882..5bc97579 100644 --- a/apps/raw2bmx/raw2bmx.cpp +++ b/apps/raw2bmx/raw2bmx.cpp @@ -5840,6 +5840,11 @@ int main(int argc, const char** argv) output_track_wave_adm_input = input; wave_adm_inputs.insert(input); } + } else { + // Input only has a chna + output_tracks_using_adm.push_back(make_pair(output_track, input)); + output_track_wave_adm_input = input; + wave_adm_inputs.insert(input); } } } diff --git a/docs/audio_definition_model.md b/docs/audio_definition_model.md index ef9c0689..e0ab78d9 100644 --- a/docs/audio_definition_model.md +++ b/docs/audio_definition_model.md @@ -12,7 +12,7 @@ The current support in the `bmx` implementation is as follows: - Converting Wave+ADM to MXF+ADM using raw2bmx - Converting Wave+ADM to Wave+ADM using raw2bmx - Converting MXF+ADM to Wave+ADM using bmxtranswrap -- Creating Wave+ADM with Wave / raw PCM, chna text file and axml/bxml/sxml file inputs +- Creating Wave+ADM with Wave / raw PCM, chna text file and (optionally) axml/bxml/sxml file inputs - Preservation of ADM links after remapping audio channels using the `--track-map` option can be used to reorder, omit, group and add silence channels. - Add ADM Soundfield Group MCA label - Set the Channel Assignment audio descriptor property for ADM-described content labelling @@ -33,6 +33,10 @@ The axml file `axml.xml` is the data that will be written into the axml chunk (w If the source Wave file contained an axml chunk then the `--wave-chunk-data axml.xml axml` option will override it. If the source Wave file contained a chna chunk then the `--chna-audio-ids chna.txt` option will override it. +A Wave+ADM sample file can be created without a axml chunk, i.e. just a chna chunk, using the following example commandline given a Wave file (which doesn't have a axml chunk!) and a chna text file: + +`raw2bmx -t wave -o output.wav --chna-audio-ids chna.txt --wave input.wav` + Raw PCM files can also be used as input, e.g. replace `--wave input.wave` with: `-s 48000 -q 24 --audio-chan 2 --pcm audio_0_1.pcm -s 48000 -q 24 --audio-chan 2 --pcm audio_2_3.pcm` diff --git a/include/bmx/wave/WaveTrackWriter.h b/include/bmx/wave/WaveTrackWriter.h index b4a17d42..d29f8ee2 100644 --- a/include/bmx/wave/WaveTrackWriter.h +++ b/include/bmx/wave/WaveTrackWriter.h @@ -65,7 +65,6 @@ class WaveTrackWriter uint32_t GetSampleSize() const; Rational GetSamplingRate() const; uint16_t GetChannelCount() const { return mChannelCount; } - uint16_t GetStartChannel() const { return mStartChannel; } int64_t GetDuration() const; diff --git a/src/mxf_reader/MXFFileTrackReader.cpp b/src/mxf_reader/MXFFileTrackReader.cpp index 7070a463..eda486d3 100644 --- a/src/mxf_reader/MXFFileTrackReader.cpp +++ b/src/mxf_reader/MXFFileTrackReader.cpp @@ -69,9 +69,7 @@ MXFFileTrackReader::MXFFileTrackReader(MXFFileReader *file_reader, size_t track_ // get MXFWaveChunks for each RIFFChunkReferenceSubDescriptor sub-descriptor reference // get a WaveCHNA from a ADM_CHNASubDescriptor WaveAudioDescriptor *wave_descriptor = dynamic_cast(file_descriptor); - if (file_source_package->getDescriptor()->haveSubDescriptors() && - wave_descriptor && wave_descriptor->haveSubDescriptors()) - { + if (wave_descriptor && wave_descriptor->haveSubDescriptors()) { vector sub_descriptors = wave_descriptor->getSubDescriptors(); size_t i; for (i = 0; i < sub_descriptors.size(); i++) { @@ -82,7 +80,7 @@ MXFFileTrackReader::MXFFileTrackReader(MXFFileReader *file_reader, size_t track_ // Get the chunk descriptors associated with the File Source Package descriptor map chunk_descriptors; MultipleDescriptor *multi_descriptor = dynamic_cast(file_source_package->getDescriptor()); - if (multi_descriptor) { + if (multi_descriptor && multi_descriptor->haveSubDescriptors()) { vector fsp_sub_descriptors = multi_descriptor->getSubDescriptors(); size_t k; for (k = 0; k < fsp_sub_descriptors.size(); k++) { diff --git a/test/wave_adm/test.sh b/test/wave_adm/test.sh index c6e21ef6..8eb92ede 100755 --- a/test/wave_adm/test.sh +++ b/test/wave_adm/test.sh @@ -155,6 +155,27 @@ create_wave_6() >/dev/null } +create_wave_7() +{ + # Create a Wave file from test generated content and a chna text file. + + $testdir/create_test_essence -t 42 -d 1 -s 1 $tmpdir/audio1.pcm + $testdir/create_test_essence -t 42 -d 1 -s 2 $tmpdir/audio2.pcm + $testdir/create_test_essence -t 42 -d 1 -s 3 $tmpdir/audio3.pcm + $testdir/create_test_essence -t 42 -d 1 -s 4 $tmpdir/audio4.pcm + + $appsdir/raw2bmx/raw2bmx \ + --regtest \ + -t wave \ + -o $2 \ + --chna-audio-ids $1 \ + -s 48000 -q 24 --pcm $tmpdir/audio1.pcm \ + -s 48000 -q 24 --pcm $tmpdir/audio2.pcm \ + -s 48000 -q 24 --pcm $tmpdir/audio3.pcm \ + -s 48000 -q 24 --pcm $tmpdir/audio4.pcm \ + >/dev/null +} + create_mxf_4() { # Create an MXF from wave_3 including only silence (non-ADM) channels. @@ -226,6 +247,31 @@ create_mxf_6() $1 } +create_mxf_7() +{ + # Create an MXF from wave_7 + + $appsdir/raw2bmx/raw2bmx \ + --regtest \ + -t op1a \ + -o $2 \ + --wave $1 \ + >/dev/null +} + + +create_wave_8() +{ + # Create a Wave file from mxf_7 + + $appsdir/bmxtranswrap/bmxtranswrap \ + --regtest \ + -t wave \ + -o $2 \ + $1 \ + >/dev/null +} + check() { @@ -268,7 +314,16 @@ check() create_mxf_6 $tmpdir/test.mxf $tmpdir/test.xml && $md5tool < $tmpdir/test.mxf > $tmpdir/test.md5 && diff $tmpdir/test.md5 $base/test_mxf_6.md5 && - diff $tmpdir/test.xml $base/test_mxf_6.xml + diff $tmpdir/test.xml $base/test_mxf_6.xml && + create_wave_7 $base/chna_1.txt $tmpdir/test_wave_7.wav && + $md5tool < $tmpdir/test_wave_7.wav > $tmpdir/test.md5 && + diff $tmpdir/test.md5 $base/test_wave_7.md5 && + create_mxf_7 $tmpdir/test_wave_7.wav $tmpdir/test_mxf_7.mxf && + $md5tool < $tmpdir/test_mxf_7.mxf > $tmpdir/test.md5 && + diff $tmpdir/test.md5 $base/test_mxf_7.md5 && + create_wave_8 $sampledir/test_mxf_7.mxf $tmpdir/test.wav && + $md5tool < $tmpdir/test.wav > $tmpdir/test.md5 && + diff $tmpdir/test.md5 $base/test_wave_8.md5 } create_data() @@ -296,7 +351,13 @@ create_data() create_mxf_5 $tmpdir/test.mxf $base/test_mxf_5.xml && $md5tool < $tmpdir/test.mxf > $base/test_mxf_5.md5 && create_mxf_6 $tmpdir/test.mxf $base/test_mxf_6.xml && - $md5tool < $tmpdir/test.mxf > $base/test_mxf_6.md5 + $md5tool < $tmpdir/test.mxf > $base/test_mxf_6.md5 && + create_wave_7 $base/chna_1.txt $tmpdir/test_wave_7.wav && + $md5tool < $tmpdir/test_wave_7.wav > $base/test_wave_7.md5 && + create_mxf_7 $tmpdir/test_wave_7.wav $tmpdir/test_mxf_7.mxf && + $md5tool < $tmpdir/test_mxf_7.mxf > $base/test_mxf_7.md5 && + create_wave_8 $sampledir/test_mxf_7.mxf $tmpdir/test.wav && + $md5tool < $tmpdir/test.wav > $base/test_wave_8.md5 } create_samples() @@ -312,7 +373,10 @@ create_samples() create_wave_6 $base/axml_1.xml $base/chna_1.txt $sampledir/test_wave_6.wav && create_mxf_4 $sampledir/test_wave_3.wav $sampledir/test_mxf_4.mxf && create_mxf_5 $sampledir/test_mxf_5.mxf $sampledir/test_mxf_5.xml && - create_mxf_6 $sampledir/test_mxf_6.mxf $sampledir/test_mxf_6.xml + create_mxf_6 $sampledir/test_mxf_6.mxf $sampledir/test_mxf_6.xml && + create_wave_7 $base/chna_1.txt $sampledir/test_wave_7.wav && + create_mxf_7 $sampledir/test_wave_7.wav $sampledir/test_mxf_7.mxf && + create_wave_8 $sampledir/test_mxf_7.mxf $sampledir/test_wave_8.wav } diff --git a/test/wave_adm/test_mxf_7.md5 b/test/wave_adm/test_mxf_7.md5 new file mode 100644 index 00000000..b3d2440d --- /dev/null +++ b/test/wave_adm/test_mxf_7.md5 @@ -0,0 +1 @@ +06dabcf71b90480ebb4df58db7aa5fb2 - diff --git a/test/wave_adm/test_wave_7.md5 b/test/wave_adm/test_wave_7.md5 new file mode 100644 index 00000000..81a1fce2 --- /dev/null +++ b/test/wave_adm/test_wave_7.md5 @@ -0,0 +1 @@ +55dd973958140cf2e4b46138877ab0c9 - diff --git a/test/wave_adm/test_wave_8.md5 b/test/wave_adm/test_wave_8.md5 new file mode 100644 index 00000000..81a1fce2 --- /dev/null +++ b/test/wave_adm/test_wave_8.md5 @@ -0,0 +1 @@ +55dd973958140cf2e4b46138877ab0c9 - From fa0783b652cf530e0747218564644f19745ce322 Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Thu, 28 Jul 2022 18:13:08 +0000 Subject: [PATCH 23/65] Lint updates for audio_definition_model.md --- docs/audio_definition_model.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/docs/audio_definition_model.md b/docs/audio_definition_model.md index e0ab78d9..cc13015c 100644 --- a/docs/audio_definition_model.md +++ b/docs/audio_definition_model.md @@ -5,6 +5,7 @@ A SMPTE project named "31FS ST Mapping ADM to MXF" started in March 2022 to "def Provisional support for ADM has been implemented in `bmx` to allow samples files to be created to support the SMPTE project. The implementation is based on an initial design specification and is likely to change. The current support in the `bmx` implementation is as follows: + - Reading Wave (BW64) that includes ADM chunks (chna, axml, bxml and sxml) - Writing Wave (BW64) with ADM chunks (chna, axml, bxml and sxml) - Reading MXF that includes Wave chunks and (mapped) ADM chna @@ -18,11 +19,11 @@ The current support in the `bmx` implementation is as follows: - Set the Channel Assignment audio descriptor property for ADM-described content labelling The known limitations are: + - mxf2raw doesn't yet show ADM metadata presence or allow ADM chunks or a chna text file to be extracted. - Re-wrapping a file using raw2bmx or bmxtranswrap with an offset or duration change may result in the ADM metadata and links becoming invalid. E.g. an audio object is no longer available in the new duration or the start offset has changed. The axml, bxml or sxml chunks are not parsed to ensure that the re-wrap retains valid ADM. - \> 4 GB chunk size is only supported for the data chunk. The ADM chunks are unlikely to be that large but it's worth adding support just in case that assumption is wrong. - ## Creating a Wave+ADM sample file A Wave+ADM sample file can be created using the following example commandline given a Wave file, a chna text file and an axml XML file: @@ -41,7 +42,6 @@ Raw PCM files can also be used as input, e.g. replace `--wave input.wave` with: `-s 48000 -q 24 --audio-chan 2 --pcm audio_0_1.pcm -s 48000 -q 24 --audio-chan 2 --pcm audio_2_3.pcm` - ## Converting a Wave+ADM to MXF+ADM A Wave+ADM can be converted to MXF+ADM using the following example commandline: @@ -54,7 +54,6 @@ The default layout is to have mono-audio MXF tracks. This can be changed using t Note that the channel index is zero-based for track mapping. - ## Converting a MXF+ADM to Wave+ADM A MXF+ADM can be converted to Wave+ADM using the following example commandline: @@ -65,7 +64,6 @@ The `--track-map` option can be used to change the audio channels. For example, `bmxtranswrap -t wave -o output.wav --track-map '0,1' input.mxf` - ## Converting a Wave+ADM to Wave+ADM A Wave+ADM can be converted to another Wave+ADM using the following example commandline: @@ -76,7 +74,6 @@ The `--track-map` option can be used to change what is output. For example, reor `raw2bmx -t wave -o output.wave --track-map '2,3,0,1' --wave input.wave` - ## Add ADM MCA labels to MXF+ADM A ADM Soundfield Group Label Subdescriptor is created from a [MCA labels text file](./mca_labels_format.md) if the list of properties associated with the Soundfield Group contains an ADM property (the ADM properties have the prefix "ADM") or it is a ADM Soundfield Group label and there are no Audio Channels that reference it. @@ -84,7 +81,8 @@ A ADM Soundfield Group Label Subdescriptor is created from a [MCA labels text fi A ADM Soundfield Group label can be added using the `ADM` symbol in a [MCA labels text file](./mca_labels_format.md). `mca.txt`: -``` + +```text 0 chL, chan=0 chR, chan=1 @@ -104,7 +102,6 @@ The MCA labels defined in `mca.txt` can be added and the ADM-described content l The Soundfield Groups that use the ADM Soundfield Group Label Subdescriptor are shown using a `(ADM)` suffix in the summary output of `mxf2raw`. E.g. `ADM(ADM)` in the example `mca.txt` above. If the `--mca-detail` option is used and the Soundfield Group uses the ADM Soundfield Group Label Subdescriptor then the name used in the `SoundfieldGroups` array is `ADMSoundfieldGroup`. - ## chna Text File Definition Format The chna text file contains the list of ADM audio identifiers that make up the chna chunk. The number of tracks and UIDs is automatically calculated. @@ -124,7 +121,7 @@ A `track_index` 0 represents a null / placeholder entry that is used to support An example chna text file is shown below. It describes 2 stereo pairs, each with "front left" and "front right" channels. -``` +```text track_index: 1 uid: ATU_00000001 track_ref: AT_00010001_01 From 7b110e70a4e05cbd15fe4f25be24dea3225fefe8 Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Fri, 30 Sep 2022 11:39:43 +0000 Subject: [PATCH 24/65] ADMSoundfieldGroupLabelSubDescriptor prop names and set UL changed --- src/apps/AppMCALabelHelper.cpp | 18 +++++++++--------- test/wave_adm/test_mxf_5.md5 | 2 +- test/wave_adm/test_mxf_6.md5 | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/apps/AppMCALabelHelper.cpp b/src/apps/AppMCALabelHelper.cpp index b2201379..6c9810e1 100644 --- a/src/apps/AppMCALabelHelper.cpp +++ b/src/apps/AppMCALabelHelper.cpp @@ -216,9 +216,9 @@ class MCAPropertyFunctions PROPERTY_FUNCTIONS(MCASpokenLanguageAttribute); PROPERTY_FUNCTIONS(RFC5646AdditionalSpokenLanguages); PROPERTY_FUNCTIONS(MCAAdditionalLanguageAttributes); - ADM_PROPERTY_FUNCTIONS(ADMAudioProgrammeID_ADMsg); - ADM_PROPERTY_FUNCTIONS(ADMAudioContentID_ADMsg); - ADM_PROPERTY_FUNCTIONS(ADMAudioObjectID_ADMsg); + ADM_PROPERTY_FUNCTIONS(ADMAudioProgrammeID_ST2131); + ADM_PROPERTY_FUNCTIONS(ADMAudioContentID_ST2131); + ADM_PROPERTY_FUNCTIONS(ADMAudioObjectID_ST2131); }; #define PROPERTY_FUNCTION_REFS(name) MCAPropertyFunctions::Set##name, MCAPropertyFunctions::Check##name @@ -246,12 +246,12 @@ struct MCAPropertyMapEntry { {"rfc5646additionalspokenlanguages", PROPERTY_FUNCTION_REFS(RFC5646AdditionalSpokenLanguages)}, {"mcaadditionallanguageattributes", PROPERTY_FUNCTION_REFS(MCAAdditionalLanguageAttributes)}, // ADM propertues will be identified by the "adm" prefix in AppMCALabelHelper - {"admaudioprogrammeid_admsg", PROPERTY_FUNCTION_REFS(ADMAudioProgrammeID_ADMsg)}, - {"admaudioprogrammeid", PROPERTY_FUNCTION_REFS(ADMAudioProgrammeID_ADMsg)}, // without "_admsg" suffix - {"admaudiocontentid_admsg", PROPERTY_FUNCTION_REFS(ADMAudioContentID_ADMsg)}, - {"admaudiocontentid", PROPERTY_FUNCTION_REFS(ADMAudioContentID_ADMsg)}, // without "_admsg" suffix - {"admaudioobjectid_admsg", PROPERTY_FUNCTION_REFS(ADMAudioObjectID_ADMsg)}, - {"admaudioobjectid", PROPERTY_FUNCTION_REFS(ADMAudioObjectID_ADMsg)}, // without "_admsg" suffix + {"admaudioprogrammeid_st2131", PROPERTY_FUNCTION_REFS(ADMAudioProgrammeID_ST2131)}, + {"admaudioprogrammeid", PROPERTY_FUNCTION_REFS(ADMAudioProgrammeID_ST2131)}, // without "_st2131" suffix + {"admaudiocontentid_st2131", PROPERTY_FUNCTION_REFS(ADMAudioContentID_ST2131)}, + {"admaudiocontentid", PROPERTY_FUNCTION_REFS(ADMAudioContentID_ST2131)}, // without "_st2131" suffix + {"admaudioobjectid_st2131", PROPERTY_FUNCTION_REFS(ADMAudioObjectID_ST2131)}, + {"admaudioobjectid", PROPERTY_FUNCTION_REFS(ADMAudioObjectID_ST2131)}, // without "_st2131" suffix }; diff --git a/test/wave_adm/test_mxf_5.md5 b/test/wave_adm/test_mxf_5.md5 index 7e459694..59fb9290 100644 --- a/test/wave_adm/test_mxf_5.md5 +++ b/test/wave_adm/test_mxf_5.md5 @@ -1 +1 @@ -480a1e7634d7a9b7e0cc500e762abb8c - +2dd10102566c1876ae53abc57cf7a1c7 - diff --git a/test/wave_adm/test_mxf_6.md5 b/test/wave_adm/test_mxf_6.md5 index 4c468904..c14bfe38 100644 --- a/test/wave_adm/test_mxf_6.md5 +++ b/test/wave_adm/test_mxf_6.md5 @@ -1 +1 @@ -1c510bc7fea06f2183a57c7e12110d16 - +51e65315395c9ab6ebcea9ca85fa61cf - From b4fd6edd60f848e612ee552db1e78c8a3bd90343 Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Fri, 30 Sep 2022 15:26:29 +0100 Subject: [PATCH 25/65] tests wav_adm: fix location of input file Co-authored-by: thomasheritage --- test/wave_adm/test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/wave_adm/test.sh b/test/wave_adm/test.sh index 8eb92ede..87f5e825 100755 --- a/test/wave_adm/test.sh +++ b/test/wave_adm/test.sh @@ -321,7 +321,7 @@ check() create_mxf_7 $tmpdir/test_wave_7.wav $tmpdir/test_mxf_7.mxf && $md5tool < $tmpdir/test_mxf_7.mxf > $tmpdir/test.md5 && diff $tmpdir/test.md5 $base/test_mxf_7.md5 && - create_wave_8 $sampledir/test_mxf_7.mxf $tmpdir/test.wav && + create_wave_8 $tmpdir/test_mxf_7.mxf $tmpdir/test.wav && $md5tool < $tmpdir/test.wav > $tmpdir/test.md5 && diff $tmpdir/test.md5 $base/test_wave_8.md5 } @@ -356,7 +356,7 @@ create_data() $md5tool < $tmpdir/test_wave_7.wav > $base/test_wave_7.md5 && create_mxf_7 $tmpdir/test_wave_7.wav $tmpdir/test_mxf_7.mxf && $md5tool < $tmpdir/test_mxf_7.mxf > $base/test_mxf_7.md5 && - create_wave_8 $sampledir/test_mxf_7.mxf $tmpdir/test.wav && + create_wave_8 $tmpdir/test_mxf_7.mxf $tmpdir/test.wav && $md5tool < $tmpdir/test.wav > $base/test_wave_8.md5 } From 26aa5a510388186047b17969801481ecd7a2b857 Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Fri, 30 Sep 2022 14:56:20 +0000 Subject: [PATCH 26/65] Fix missing RIFFChunkDefinitionSubDescriptor for a single track / file descriptor --- src/mxf_op1a/OP1AFile.cpp | 21 ++++++++++++--------- test/wave_adm/test_mxf_1.md5 | 2 +- test/wave_adm/test_mxf_2.md5 | 2 +- test/wave_adm/test_mxf_3.md5 | 2 +- test/wave_adm/test_mxf_5.md5 | 2 +- test/wave_adm/test_mxf_6.md5 | 2 +- 6 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/mxf_op1a/OP1AFile.cpp b/src/mxf_op1a/OP1AFile.cpp index 5f25e1b4..24608b98 100644 --- a/src/mxf_op1a/OP1AFile.cpp +++ b/src/mxf_op1a/OP1AFile.cpp @@ -908,15 +908,6 @@ void OP1AFile::CreateHeaderMetadata() mult_descriptor->setEssenceContainer(MXF_EC_L(MultipleWrappings)); if (mSupportCompleteSinglePass) mult_descriptor->setContainerDuration(mInputDuration); - - // Preface - ContentStorage - SourcePackage - (Multiple) File Descriptor - Wave Chunk sub-descriptors - map::const_iterator iter; - for (iter = mWaveChunks.begin(); iter != mWaveChunks.end(); iter++) { - RIFFChunkDefinitionSubDescriptor *wave_chunk_subdesc = new RIFFChunkDefinitionSubDescriptor(mHeaderMetadata); - mult_descriptor->appendSubDescriptors(wave_chunk_subdesc); - wave_chunk_subdesc->setRIFFChunkStreamID(iter->first); - wave_chunk_subdesc->setRIFFChunkID(iter->second->Tag()); - } } } @@ -952,6 +943,18 @@ void OP1AFile::CreateHeaderMetadata() for (i = 0; i < mXMLTracks.size(); i++) mXMLTracks[i]->AddHeaderMetadata(mHeaderMetadata, mMaterialPackage); + // Preface - ContentStorage - SourcePackage - File Descriptor - Wave Chunk sub-descriptors + if (mFileSourcePackage && mFileSourcePackage->getDescriptor()) { + GenericDescriptor *descriptor = mFileSourcePackage->getDescriptor(); + map::const_iterator iter; + for (iter = mWaveChunks.begin(); iter != mWaveChunks.end(); iter++) { + RIFFChunkDefinitionSubDescriptor *wave_chunk_subdesc = new RIFFChunkDefinitionSubDescriptor(mHeaderMetadata); + descriptor->appendSubDescriptors(wave_chunk_subdesc); + wave_chunk_subdesc->setRIFFChunkStreamID(iter->first); + wave_chunk_subdesc->setRIFFChunkID(iter->second->Tag()); + } + } + // Signal ST 379-2 generic container compliance if mSignalST3792 or there is RDD 36 / ProRes video. // RDD 44 (RDD 36 / ProRes in MXF) requires ST 379-2 and specifically mentions ContainerConstraintSubDescriptor. bool have_rdd36 = false; diff --git a/test/wave_adm/test_mxf_1.md5 b/test/wave_adm/test_mxf_1.md5 index fc08106a..761c0357 100644 --- a/test/wave_adm/test_mxf_1.md5 +++ b/test/wave_adm/test_mxf_1.md5 @@ -1 +1 @@ -f8fb075f662b05fba544a119d7b13842 - +dd59c32051bf2c08a70dd68d6cb65245 - diff --git a/test/wave_adm/test_mxf_2.md5 b/test/wave_adm/test_mxf_2.md5 index b3fd76fe..b3d45c1b 100644 --- a/test/wave_adm/test_mxf_2.md5 +++ b/test/wave_adm/test_mxf_2.md5 @@ -1 +1 @@ -7389f87f35bdcf26e6f91c83272db8dc - +f523de102f0470006368078b883ce336 - diff --git a/test/wave_adm/test_mxf_3.md5 b/test/wave_adm/test_mxf_3.md5 index 57bf5aed..bd4500a0 100644 --- a/test/wave_adm/test_mxf_3.md5 +++ b/test/wave_adm/test_mxf_3.md5 @@ -1 +1 @@ -ce3cf209d705d8a49ae46a13bd7937f0 - +1c1874b0c57c54871267247164b2fbc3 - diff --git a/test/wave_adm/test_mxf_5.md5 b/test/wave_adm/test_mxf_5.md5 index 59fb9290..747b643f 100644 --- a/test/wave_adm/test_mxf_5.md5 +++ b/test/wave_adm/test_mxf_5.md5 @@ -1 +1 @@ -2dd10102566c1876ae53abc57cf7a1c7 - +6c87c735b0216b18953175df31edd54d - diff --git a/test/wave_adm/test_mxf_6.md5 b/test/wave_adm/test_mxf_6.md5 index c14bfe38..d433280c 100644 --- a/test/wave_adm/test_mxf_6.md5 +++ b/test/wave_adm/test_mxf_6.md5 @@ -1 +1 @@ -51e65315395c9ab6ebcea9ca85fa61cf - +a8e1ee140c56ab8d38418284acab3326 - From fe734114e5d77bdb1317e4910c9edc732bcdd952 Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Fri, 30 Sep 2022 15:27:59 +0000 Subject: [PATCH 27/65] Fix reader missing Wave chunks referenced by non-multipledescriptor A single track source package can have a single file descriptor that is not a multiple descriptor. --- src/mxf_reader/MXFFileTrackReader.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mxf_reader/MXFFileTrackReader.cpp b/src/mxf_reader/MXFFileTrackReader.cpp index eda486d3..905bd7e6 100644 --- a/src/mxf_reader/MXFFileTrackReader.cpp +++ b/src/mxf_reader/MXFFileTrackReader.cpp @@ -79,9 +79,9 @@ MXFFileTrackReader::MXFFileTrackReader(MXFFileReader *file_reader, size_t track_ if (chunk_ref_descriptor) { // Get the chunk descriptors associated with the File Source Package descriptor map chunk_descriptors; - MultipleDescriptor *multi_descriptor = dynamic_cast(file_source_package->getDescriptor()); - if (multi_descriptor && multi_descriptor->haveSubDescriptors()) { - vector fsp_sub_descriptors = multi_descriptor->getSubDescriptors(); + GenericDescriptor *descriptor = dynamic_cast(file_source_package->getDescriptor()); + if (descriptor && descriptor->haveSubDescriptors()) { + vector fsp_sub_descriptors = descriptor->getSubDescriptors(); size_t k; for (k = 0; k < fsp_sub_descriptors.size(); k++) { RIFFChunkDefinitionSubDescriptor *chunk_descriptor = From c0164ad4dace45cf1d9aff4e6bb7918bc8d011cc Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Thu, 19 Jan 2023 09:30:26 +0000 Subject: [PATCH 28/65] test: add wave_adm tests for singlemca and mono tracks --- test/wave_adm/test.sh | 89 +++++++++++++++++++++++++++++++--- test/wave_adm/test_mxf_8.md5 | 1 + test/wave_adm/test_mxf_9.md5 | 1 + test/wave_adm/test_wave_10.md5 | 1 + test/wave_adm/test_wave_9.md5 | 1 + 5 files changed, 86 insertions(+), 7 deletions(-) create mode 100644 test/wave_adm/test_mxf_8.md5 create mode 100644 test/wave_adm/test_mxf_9.md5 create mode 100644 test/wave_adm/test_wave_10.md5 create mode 100644 test/wave_adm/test_wave_9.md5 diff --git a/test/wave_adm/test.sh b/test/wave_adm/test.sh index 87f5e825..1ef33c82 100755 --- a/test/wave_adm/test.sh +++ b/test/wave_adm/test.sh @@ -259,7 +259,6 @@ create_mxf_7() >/dev/null } - create_wave_8() { # Create a Wave file from mxf_7 @@ -272,6 +271,56 @@ create_wave_8() >/dev/null } +create_mxf_8() +{ + # Create a multi-channel track MXF from wave_3 + + $appsdir/raw2bmx/raw2bmx \ + --regtest \ + -t op1a \ + -o $2 \ + --track-map singlemca \ + --wave $1 \ + >/dev/null +} + +create_wave_9() +{ + # Create a Wave file from mxf_8 + + $appsdir/bmxtranswrap/bmxtranswrap \ + --regtest \ + -t wave \ + -o $2 \ + $1 \ + >/dev/null +} + +create_mxf_9() +{ + # Create mono track MXF from wave_3 + + $appsdir/raw2bmx/raw2bmx \ + --regtest \ + -t op1a \ + -o $2 \ + --track-map mono \ + --wave $1 \ + >/dev/null +} + +create_wave_10() +{ + # Create a Wave file from mxf_9 + + $appsdir/bmxtranswrap/bmxtranswrap \ + --regtest \ + -t wave \ + -o $2 \ + $1 \ + >/dev/null +} + check() { @@ -291,8 +340,8 @@ check() create_wave_2 $tmpdir/test_mxf_1.mxf $tmpdir/test.wav && $md5tool < $tmpdir/test.wav > $tmpdir/test.md5 && diff $tmpdir/test.md5 $base/test_wave_2.md5 && - create_wave_3 $tmpdir/test_mxf_3.mxf $tmpdir/test_wav_3.wav && - $md5tool < $tmpdir/test_wav_3.wav > $tmpdir/test.md5 && + create_wave_3 $tmpdir/test_mxf_3.mxf $tmpdir/test_wave_3.wav && + $md5tool < $tmpdir/test_wave_3.wav > $tmpdir/test.md5 && diff $tmpdir/test.md5 $base/test_wave_3.md5 && create_wave_4 $tmpdir/test_mxf_3.mxf $tmpdir/test.wav && $md5tool < $tmpdir/test.wav > $tmpdir/test.md5 && @@ -304,7 +353,7 @@ check() create_wave_6 $base/axml_1.xml $base/chna_1.txt $tmpdir/test.wav && $md5tool < $tmpdir/test.wav > $tmpdir/test.md5 && diff $tmpdir/test.md5 $base/test_wave_6.md5 && - create_mxf_4 $tmpdir/test_wav_3.wav $tmpdir/test.mxf && + create_mxf_4 $tmpdir/test_wave_3.wav $tmpdir/test.mxf && $md5tool < $tmpdir/test.mxf > $tmpdir/test.md5 && diff $tmpdir/test.md5 $base/test_mxf_4.md5 && create_mxf_5 $tmpdir/test.mxf $tmpdir/test.xml && @@ -323,7 +372,21 @@ check() diff $tmpdir/test.md5 $base/test_mxf_7.md5 && create_wave_8 $tmpdir/test_mxf_7.mxf $tmpdir/test.wav && $md5tool < $tmpdir/test.wav > $tmpdir/test.md5 && - diff $tmpdir/test.md5 $base/test_wave_8.md5 + diff $tmpdir/test.md5 $base/test_wave_8.md5 && + create_mxf_8 $tmpdir/test_wave_3.wav $tmpdir/test_mxf_8.mxf && + $md5tool < $tmpdir/test_mxf_8.mxf > $tmpdir/test.md5 && + diff $tmpdir/test.md5 $base/test_mxf_8.md5 && + create_wave_9 $tmpdir/test_mxf_8.mxf $tmpdir/test.wav && + $md5tool < $tmpdir/test.wav > $tmpdir/test.md5 && + diff $tmpdir/test.md5 $base/test_wave_9.md5 && + diff $tmpdir/test.wav $tmpdir/test_wave_3.wav && + create_mxf_9 $tmpdir/test_wave_3.wav $tmpdir/test_mxf_9.mxf && + $md5tool < $tmpdir/test_mxf_9.mxf > $tmpdir/test.md5 && + diff $tmpdir/test.md5 $base/test_mxf_9.md5 && + create_wave_10 $tmpdir/test_mxf_9.mxf $tmpdir/test.wav && + $md5tool < $tmpdir/test.wav > $tmpdir/test.md5 && + diff $tmpdir/test.md5 $base/test_wave_10.md5 && + diff $tmpdir/test.wav $tmpdir/test_wave_3.wav } create_data() @@ -357,7 +420,15 @@ create_data() create_mxf_7 $tmpdir/test_wave_7.wav $tmpdir/test_mxf_7.mxf && $md5tool < $tmpdir/test_mxf_7.mxf > $base/test_mxf_7.md5 && create_wave_8 $tmpdir/test_mxf_7.mxf $tmpdir/test.wav && - $md5tool < $tmpdir/test.wav > $base/test_wave_8.md5 + $md5tool < $tmpdir/test.wav > $base/test_wave_8.md5 && + create_mxf_8 $tmpdir/test_wave_3.wav $tmpdir/test_mxf_8.mxf && + $md5tool < $tmpdir/test_mxf_8.mxf > $base/test_mxf_8.md5 && + create_wave_9 $tmpdir/test_mxf_8.mxf $tmpdir/test.wav && + $md5tool < $tmpdir/test.wav > $base/test_wave_9.md5 && + create_mxf_9 $tmpdir/test_wave_3.wav $tmpdir/test_mxf_9.mxf && + $md5tool < $tmpdir/test_mxf_9.mxf > $base/test_mxf_9.md5 && + create_wave_10 $tmpdir/test_mxf_9.mxf $tmpdir/test.wav && + $md5tool < $tmpdir/test.wav > $base/test_wave_10.md5 } create_samples() @@ -376,7 +447,11 @@ create_samples() create_mxf_6 $sampledir/test_mxf_6.mxf $sampledir/test_mxf_6.xml && create_wave_7 $base/chna_1.txt $sampledir/test_wave_7.wav && create_mxf_7 $sampledir/test_wave_7.wav $sampledir/test_mxf_7.mxf && - create_wave_8 $sampledir/test_mxf_7.mxf $sampledir/test_wave_8.wav + create_wave_8 $sampledir/test_mxf_7.mxf $sampledir/test_wave_8.wav && + create_mxf_8 $sampledir/test_wave_3.wav $sampledir/test_mxf_8.mxf && + create_wave_9 $sampledir/test_mxf_8.mxf $sampledir/test_wave_9.wav && + create_mxf_9 $sampledir/test_wave_3.wav $sampledir/test_mxf_9.mxf && + create_wave_10 $sampledir/test_mxf_9.mxf $sampledir/test_wave_10.wav } diff --git a/test/wave_adm/test_mxf_8.md5 b/test/wave_adm/test_mxf_8.md5 new file mode 100644 index 00000000..e3e5848a --- /dev/null +++ b/test/wave_adm/test_mxf_8.md5 @@ -0,0 +1 @@ +8880bb12c5946f2e683d6440408a605e - diff --git a/test/wave_adm/test_mxf_9.md5 b/test/wave_adm/test_mxf_9.md5 new file mode 100644 index 00000000..bec39d8c --- /dev/null +++ b/test/wave_adm/test_mxf_9.md5 @@ -0,0 +1 @@ +143f89129ca4cae5982a73a1aface1db - diff --git a/test/wave_adm/test_wave_10.md5 b/test/wave_adm/test_wave_10.md5 new file mode 100644 index 00000000..de0a03dc --- /dev/null +++ b/test/wave_adm/test_wave_10.md5 @@ -0,0 +1 @@ +6b65bb005ed842aa5107d5be43af2b5b - diff --git a/test/wave_adm/test_wave_9.md5 b/test/wave_adm/test_wave_9.md5 new file mode 100644 index 00000000..de0a03dc --- /dev/null +++ b/test/wave_adm/test_wave_9.md5 @@ -0,0 +1 @@ +6b65bb005ed842aa5107d5be43af2b5b - From 3988d38396ce34cbb741fdd071753e4ea8b8b013 Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Wed, 22 Nov 2023 10:27:23 +0000 Subject: [PATCH 29/65] Update mxflib dict with ADM data model updates --- meta/extensions_mxflib_dict.xml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/meta/extensions_mxflib_dict.xml b/meta/extensions_mxflib_dict.xml index 9b538fd3..4e861b1c 100644 --- a/meta/extensions_mxflib_dict.xml +++ b/meta/extensions_mxflib_dict.xml @@ -176,10 +176,16 @@ - - - - + + + + + + + + + + From f24b25335d30e896763f887f90bfd7412ba6fbb3 Mon Sep 17 00:00:00 2001 From: Philip de Nier Date: Tue, 25 Oct 2022 16:07:39 +0000 Subject: [PATCH 30/65] raw2bmx: add options to add wave chunks and identify adm chunks --- apps/raw2bmx/raw2bmx.cpp | 232 ++++++++++++++++----------- include/bmx/apps/AppUtils.h | 8 + include/bmx/clip_writer/ClipWriter.h | 1 + include/bmx/mxf_op1a/OP1AFile.h | 7 + include/bmx/wave/WaveReader.h | 3 + include/bmx/wave/WaveWriter.h | 4 + src/apps/AppUtils.cpp | 44 +++++ src/clip_writer/ClipWriter.cpp | 27 ++++ src/mxf_op1a/OP1AFile.cpp | 21 +++ src/wave/WaveReader.cpp | 11 ++ src/wave/WaveWriter.cpp | 34 +++- test/wave_adm/test.sh | 9 ++ 12 files changed, 299 insertions(+), 102 deletions(-) diff --git a/apps/raw2bmx/raw2bmx.cpp b/apps/raw2bmx/raw2bmx.cpp index 5bc97579..bbdc9cbb 100644 --- a/apps/raw2bmx/raw2bmx.cpp +++ b/apps/raw2bmx/raw2bmx.cpp @@ -163,6 +163,8 @@ struct RawInput EssenceFilter *filter; bool set_bs_aspect_ratio; + map *wave_chunk_refs; + // picture BMX_OPT_PROP_DECL(Rational, aspect_ratio); BMX_OPT_PROP_DECL(uint8_t, afd); @@ -345,6 +347,7 @@ static void init_input(RawInput *input) { memset(input, 0, sizeof(*input)); input->timed_text_manifest = new TimedTextManifestParser(); + input->wave_chunk_refs = new map(); BMX_OPT_PROP_DEFAULT(input->aspect_ratio, ASPECT_RATIO_16_9); BMX_OPT_PROP_DEFAULT(input->afd, 0); BMX_OPT_PROP_DEFAULT(input->signal_standard, MXF_SIGNAL_STANDARD_NONE); @@ -388,6 +391,7 @@ static void clear_input(RawInput *input) delete input->wave_reader; delete input->filter; delete input->timed_text_manifest; + delete input->wave_chunk_refs; } static bool parse_avci_guess(const char *str, bool *interlaced, bool *progressive) @@ -713,6 +717,14 @@ static void usage(const char *cmd) printf(" 0: Passthrough input, but add a sequence header if not present, remove duplicate/redundant sequence headers\n"); printf(" and fix any incorrect parse info offsets and picture numbers\n"); printf(" 1: (default) Same as 0, but remove auxiliary and padding data units and complete the sequence in each frame\n"); + printf(" --wave-chunks List of non-builtin WAVE chunk IDs to transfer across from the input\n"); + printf(" The is a comma separated list of chunk IDs. Spaces are automatically appended to IDs if they are less than 4 letters\n"); + printf(" The built-in WAVE chunk IDs are: %s\n", WaveReader::GetBuiltinChunkListString().c_str()); + printf(" --adm-wave-chunk [,