Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add provisional support for ADM and other audio metadata RIFF chunks in MXF #51

Merged
merged 65 commits into from
Dec 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
4aad03c
libmxf: Add ADM sets and items to data model
philipnbbc Nov 22, 2023
33f8ae0
libmxf: Add Wave chunk generic stream key
philipnbbc Nov 22, 2023
f1e6551
libmxf: Add ITU 2076 ADM audio metadata profiles and levels label
philipnbbc Nov 22, 2023
e64d40e
libmxf: Add MGA sound descriptors and labels
philipnbbc Nov 22, 2023
d424232
libmxfpp: Add ADM classes
philipnbbc Nov 22, 2023
30f18c0
libmxfpp: Include mxf.h where it's required in headers
philipnbbc Nov 22, 2023
3b4926f
libmxfpp: Add missing include for msvc 2019 build
philipnbbc Nov 22, 2023
a4e7a9a
libmxfpp: Add MGA sound descriptors
philipnbbc Nov 22, 2023
cc741e7
libmxfpp: cmake: add ADM files to source and header lists
philipnbbc Nov 22, 2023
d09e193
Add ADM definitions to mxflib extensions dictionary
philipnbbc Nov 22, 2023
935d612
Add GenericStreamReader class
philipnbbc Jan 19, 2023
5862a41
Add initial support for Wave ADM
philipnbbc Jan 19, 2023
58889db
Add initial Wave ADM regression tests
philipnbbc Jan 19, 2023
eee2b71
Add support for ADM in raw2bmx wave -> wave
philipnbbc Jan 19, 2023
10ccc59
Add readme for ADM support
philipnbbc Jan 19, 2023
f8fe581
test: update checksums after ADM data model was updated
philipnbbc Jul 25, 2022
f60abb5
Update ADM data model in mxflib dict
philipnbbc Nov 22, 2023
e720e0c
Prevent null ADM audio mappings in MXF descriptor
philipnbbc Jul 26, 2022
59ad19d
Additional checks for audio mappings
philipnbbc Jul 26, 2022
785aa5a
Implement support for ADM MCA labelling
philipnbbc Jan 19, 2023
b7fce02
Update how ADM SG Label Subdescriptor is processed
philipnbbc Jan 19, 2023
8dff699
Support ADM with only a chna
philipnbbc Jan 19, 2023
fa0783b
Lint updates for audio_definition_model.md
philipnbbc Jul 28, 2022
7b110e7
ADMSoundfieldGroupLabelSubDescriptor prop names and set UL changed
philipnbbc Sep 30, 2022
b4fd6ed
tests wav_adm: fix location of input file
philipnbbc Sep 30, 2022
26aa5a5
Fix missing RIFFChunkDefinitionSubDescriptor for a single track / fil…
philipnbbc Sep 30, 2022
fe73411
Fix reader missing Wave chunks referenced by non-multipledescriptor
philipnbbc Sep 30, 2022
c0164ad
test: add wave_adm tests for singlemca and mono tracks
philipnbbc Jan 19, 2023
3988d38
Update mxflib dict with ADM data model updates
philipnbbc Nov 22, 2023
f24b253
raw2bmx: add options to add wave chunks and identify adm chunks
philipnbbc Oct 25, 2022
033b959
adm test: channels not included in chna still reference chunks
philipnbbc Oct 26, 2022
38341ab
adm tests: identify axml chunk as adm, which adds the descriptor
philipnbbc Oct 26, 2022
8068989
raw2bmx: warn if mapping chna but no chunks even when known ones are …
philipnbbc Oct 26, 2022
f712132
bmxtranswrap: map chunks and chna independently to wave
philipnbbc Oct 26, 2022
2f7912f
Set required ADM SG stream ID using chunk_id label property
philipnbbc Oct 26, 2022
cc220d8
Update READMEs with new ADM label chunk_id property
philipnbbc Oct 26, 2022
dcc0e90
Check one-to-one chunk id to stream id for ADM SG label link
philipnbbc Oct 27, 2022
4c807d5
Update audio_definition_model.md following implementation changes
philipnbbc Oct 27, 2022
55387c7
Add section to ADM doc explaing Wave to MXF mapping
philipnbbc Oct 27, 2022
2f1e0c8
Various ADM doc fixups
philipnbbc Oct 27, 2022
ecc8e82
Follow ADM spec's example and use <tag> notation for wave chunks
philipnbbc Oct 28, 2022
83b39e9
Rename chunk 'tag' to 'id' to follow RIFF spec naming
philipnbbc Oct 28, 2022
eb8b13c
Warn if writing chunks with the same ID to a Wave file
philipnbbc Oct 28, 2022
f5c4ea9
Add options to not transfer wave chunks, including chna
philipnbbc Jan 19, 2023
5b32085
Fix msvc 2019 build error
philipnbbc Nov 1, 2022
9da95c8
Fix msvc 2019 type conversion warnings
philipnbbc Nov 1, 2022
ab88f4d
Fix msvc 2019 result discard warning
philipnbbc Nov 1, 2022
6c71479
raw2bmx: Fix resize of chunk id with less than 4 chars
philipnbbc Nov 4, 2022
780d8bd
docs: fixup adm doc
philipnbbc Nov 4, 2022
54bcfc4
docs: update the ADM prop names and sg label name
philipnbbc Nov 4, 2022
bcc0299
Add basic read support for MGA / S-ADM
philipnbbc Jan 19, 2023
4dc57f3
mxf2raw: options to extract wave chunks
philipnbbc Jan 19, 2023
8f28f1c
mxf2raw: options to extract ADM CHNA as text file
philipnbbc Nov 22, 2023
3c2d064
cmake: add new files to source and header lists
philipnbbc Jan 19, 2023
67ae490
cmake: convert Wave ADM tests
philipnbbc Jan 20, 2023
1c2fb3f
Fix memory leaks spotted by valgrind
philipnbbc Jan 20, 2023
309b997
Explicit type casts for MSVC
philipnbbc Jan 20, 2023
c68f24c
Ignore MSVC inherits via dominance warning C4250
philipnbbc Jan 20, 2023
a341f1b
Update mxflib dict with RIFFChunkHashSHA1
philipnbbc Feb 8, 2023
3c92981
test: update wave adm checksums following code rebase
philipnbbc Nov 22, 2023
3b34da5
adm: fix name match failure for MCA labels with st2131 suffix
philipnbbc Dec 7, 2023
8d27b75
mca: clarify warning about SG and GSG descriptors not being linked
philipnbbc Dec 7, 2023
632e4c6
adm/mca: usei just chunk_id prop to decide to create ADM SG descriptor
philipnbbc Dec 7, 2023
5d768c1
adm: don't have _st2131 suffix on adm property names
philipnbbc Dec 7, 2023
de57903
Update documentation re ADM-related features
thomasheritage Dec 8, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
* [(Beta) Audio Definition Model (ADM) & metadata RIFF chunks](./docs/audio_definition_model.md)

## Build, Test and Install

Expand Down
94 changes: 93 additions & 1 deletion apps/bmxtranswrap/bmxtranswrap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
#include <bmx/clip_writer/ClipWriter.h>
#include <bmx/as02/AS02PictureTrack.h>
#include <bmx/wave/WaveFileIO.h>
#include <bmx/wave/WaveChunk.h>
#include <bmx/st436/ST436Element.h>
#include <bmx/st436/RDD6Metadata.h>
#include <bmx/URI.h>
Expand Down Expand Up @@ -689,7 +690,9 @@ 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 <name> Set originator in the Wave bext chunk. Default '%s'\n", DEFAULT_BEXT_ORIGINATOR);
printf(" --orig <name> Set originator in the Wave bext chunk. Default '%s'\n", DEFAULT_BEXT_ORIGINATOR);
printf(" --exclude-wave-chunks <ids> Don't transfer non-builtin or <chna> Wave chunks with ID in the comma-separated list of chunk <ids>\n");
printf(" Set <ids> to 'all' to exclude all Wave chunks\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");
Expand All @@ -702,6 +705,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 <scheme> <file> Insert audio labels defined in <file>. The 'as11' <scheme> will add an override and otherwise <scheme> is ignored\n");
printf(" The format of <file> is described in bmx/docs/mca_labels_format.md\n");
printf(" All tag symbols registered in the bmx code are available for use\n");
Expand Down Expand Up @@ -871,6 +875,8 @@ int main(int argc, const char** argv)
uint8_t d10_mute_sound_flags = 0;
uint8_t d10_invalid_sound_flags = 0;
const char *originator = DEFAULT_BEXT_ORIGINATOR;
set<WaveChunkId> exclude_wave_chunks;
bool exclude_all_wave_chunks = false;
AvidUMIDType avid_umid_type = AAFSDK_UMID_TYPE;
UMID mp_uid = g_Null_UMID;
bool mp_uid_set = false;
Expand Down Expand Up @@ -2647,6 +2653,22 @@ int main(int argc, const char** argv)
originator = argv[cmdln_index + 1];
cmdln_index++;
}
else if (strcmp(argv[cmdln_index], "--exclude-wave-chunks") == 0)
{
if (cmdln_index + 1 >= argc)
{
usage(argv[0]);
fprintf(stderr, "Missing argument for Option '%s'\n", argv[cmdln_index]);
return 1;
}
if (!parse_wave_chunk_ids(argv[cmdln_index + 1], &exclude_wave_chunks, &exclude_all_wave_chunks))
{
usage(argv[0]);
fprintf(stderr, "Invalid value '%s' for Option '%s'\n", argv[cmdln_index + 1], argv[cmdln_index]);
return 1;
}
cmdln_index++;
}
else if (strcmp(argv[cmdln_index], "--track-map") == 0)
{
if (cmdln_index + 1 >= argc)
Expand Down Expand Up @@ -4263,6 +4285,8 @@ int main(int argc, const char** argv)
break;
}
case D10_AES3_PCM:
case MGA:
case MGA_SADM:
case PICTURE_ESSENCE:
case SOUND_ESSENCE:
case DATA_ESSENCE:
Expand Down Expand Up @@ -4384,6 +4408,72 @@ int main(int argc, const char** argv)
}


// Add wave chunks

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<uint32_t> unique_chunk_stream_ids;

// Loop over the wave output tracks
for (size_t 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, where each has a mapping from an input track channel
const map<uint32_t, OutputTrack::InputMap> &input_maps = output_track->GetInputMaps();
map<uint32_t, OutputTrack::InputMap>::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<MXFInputTrack*>(input_track)->GetTrackReader();

// Add all referenced chunks if not already present
for (size_t k = 0; k < input_track_reader->GetNumWaveChunks(); k++) {
MXFWaveChunk *wave_chunk = input_track_reader->GetWaveChunk(k);

// Don't write chunks in the exclusion list
if (exclude_all_wave_chunks || exclude_wave_chunks.count(wave_chunk->Id()) > 0)
continue;

if (!unique_chunk_stream_ids.count(wave_chunk->GetStreamId())) {
if (wave_clip->HaveChunk(wave_chunk->Id())) {
// E.g. this can happen if multiple <axml> chunks exist that came from different Wave files
// and the <axml> chunks may or may not be identical or equivalent.
// The assumption is that only 1 chunk with a given ID can exist in a BWF64 / Wave file.
// The exception is probably <JUNK>, but that shouldn't be transferred between Wave or MXF.
log_warn("Replaced chunk <%s> with another with the same ID in the output\n",
get_wave_chunk_id_str(wave_chunk->Id()).c_str());
}
wave_clip->AddChunk(wave_chunk, false);
unique_chunk_stream_ids.insert(wave_chunk->GetStreamId());
}
}

if (!exclude_all_wave_chunks && exclude_wave_chunks.count(WAVE_CHUNK_ID("chna")) == 0) {
// Add audio IDs for the ADM <chna> chunk
vector<WaveCHNA::AudioID> audio_ids = input_track_reader->GetCHNAAudioIDs(input_channel_index);
for (size_t k = 0; k < audio_ids.size(); k++) {
WaveCHNA::AudioID &audio_id = audio_ids[k];

// Change the input channel track_index to the output channel track_index
// + 1 because the <chna> track_index starts at 1
audio_id.track_index = output_channel_index + 1;
wave_track->AddADMAudioID(audio_id);
}
}
}
}
}


// prepare the clip's header metadata and update file descriptors from input where supported

clip->PrepareHeaderMetadata();
Expand Down Expand Up @@ -4428,6 +4518,8 @@ int main(int argc, const char** argv)


// insert MCA labels
// Note: this must happen after processing wave chunks because the ADM soundfield group label requires
// the MXF stream ID for a given wave chunk ID

for (i = 0; i < track_mca_labels.size(); i++) {
const string &scheme = track_mca_labels[i].first;
Expand Down
Loading