summaryrefslogtreecommitdiff
path: root/src/sound_asset_writer.cc
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2020-09-06 20:10:13 +0200
committerCarl Hetherington <cth@carlh.net>2020-09-21 21:57:18 +0200
commitcdc8bc6a7da0b4f8c3dbfcf560fea61473cf1ca3 (patch)
tree6f6fc0c6b7897e6d3bd48fcc27e0e5eb08fc92b9 /src/sound_asset_writer.cc
parent445f2495fbb0885132d3a6c8e7a1e135cbac3cce (diff)
Support MCA sound channel tags in MXF/CPL.
Diffstat (limited to 'src/sound_asset_writer.cc')
-rw-r--r--src/sound_asset_writer.cc76
1 files changed, 68 insertions, 8 deletions
diff --git a/src/sound_asset_writer.cc b/src/sound_asset_writer.cc
index ff1d02c2..3980dc62 100644
--- a/src/sound_asset_writer.cc
+++ b/src/sound_asset_writer.cc
@@ -39,6 +39,8 @@
#include "compose.hpp"
#include "crypto_context.h"
#include <asdcp/AS_DCP.h>
+#include <asdcp/Metadata.h>
+#include <boost/foreach.hpp>
#include <iostream>
using std::min;
@@ -48,6 +50,13 @@ using std::string;
using std::vector;
using namespace dcp;
+
+/* Some ASDCP objects store this as a *&, for reasons which are not
+ * at all clear, so we have to keep this around forever.
+ */
+static ASDCP::Dictionary const* smpte_dict = &ASDCP::DefaultSMPTEDict();
+
+
struct SoundAssetWriter::ASDCPState
{
ASDCP::PCM::MXFWriter mxf_writer;
@@ -56,13 +65,14 @@ struct SoundAssetWriter::ASDCPState
ASDCP::PCM::AudioDescriptor desc;
};
-SoundAssetWriter::SoundAssetWriter (SoundAsset* asset, boost::filesystem::path file, bool sync)
+SoundAssetWriter::SoundAssetWriter (SoundAsset* asset, boost::filesystem::path file, vector<Channel> active_channels, bool sync)
: AssetWriter (asset, file)
, _state (new SoundAssetWriter::ASDCPState)
, _asset (asset)
, _frame_buffer_offset (0)
, _sync (sync)
, _sync_packet (0)
+ , _active_channels (active_channels)
{
DCP_ASSERT (!_sync || _asset->channels() >= 14);
DCP_ASSERT (!_sync || _asset->standard() == SMPTE);
@@ -101,6 +111,62 @@ SoundAssetWriter::SoundAssetWriter (SoundAsset* asset, boost::filesystem::path f
}
}
+
+void
+SoundAssetWriter::start ()
+{
+ Kumu::Result_t r = _state->mxf_writer.OpenWrite (_file.string().c_str(), _state->writer_info, _state->desc);
+ if (ASDCP_FAILURE (r)) {
+ boost::throw_exception (FileError ("could not open audio MXF for writing", _file.string(), r));
+ }
+
+ if (_asset->standard() == dcp::SMPTE && !_active_channels.empty()) {
+
+ ASDCP::MXF::WaveAudioDescriptor* essence_descriptor = 0;
+ _state->mxf_writer.OP1aHeader().GetMDObjectByType(
+ smpte_dict->ul(ASDCP::MDD_WaveAudioDescriptor), reinterpret_cast<ASDCP::MXF::InterchangeObject**>(&essence_descriptor)
+ );
+ DCP_ASSERT (essence_descriptor);
+ essence_descriptor->ChannelAssignment = smpte_dict->ul(ASDCP::MDD_DCAudioChannelCfg_MCA);
+
+ ASDCP::MXF::SoundfieldGroupLabelSubDescriptor* soundfield = new ASDCP::MXF::SoundfieldGroupLabelSubDescriptor(smpte_dict);
+ GenRandomValue (soundfield->MCALinkID);
+ soundfield->RFC5646SpokenLanguage = _asset->language().to_string();
+
+ const MCASoundField field = _asset->channels() > 10 ? SEVEN_POINT_ONE : FIVE_POINT_ONE;
+
+ if (field == SEVEN_POINT_ONE) {
+ soundfield->MCATagSymbol = "sg71";
+ soundfield->MCATagName = "7.1DS";
+ soundfield->MCALabelDictionaryID = smpte_dict->ul(ASDCP::MDD_DCAudioSoundfield_71);
+ } else {
+ soundfield->MCATagSymbol = "sg51";
+ soundfield->MCATagName = "5.1";
+ soundfield->MCALabelDictionaryID = smpte_dict->ul(ASDCP::MDD_DCAudioSoundfield_51);
+ }
+
+ _state->mxf_writer.OP1aHeader().AddChildObject(soundfield);
+ essence_descriptor->SubDescriptors.push_back(soundfield->InstanceUID);
+
+ BOOST_FOREACH (Channel i, _active_channels) {
+ ASDCP::MXF::AudioChannelLabelSubDescriptor* channel = new ASDCP::MXF::AudioChannelLabelSubDescriptor(smpte_dict);
+ GenRandomValue (channel->MCALinkID);
+ channel->SoundfieldGroupLinkID = soundfield->MCALinkID;
+ channel->MCAChannelID = static_cast<int>(i) + 1;
+ channel->MCATagSymbol = "ch" + channel_to_mca_id(i, field);
+ channel->MCATagName = channel_to_mca_name(i, field);
+ channel->RFC5646SpokenLanguage = _asset->language().to_string();
+ channel->MCALabelDictionaryID = channel_to_mca_universal_label(i, field, smpte_dict);
+ _state->mxf_writer.OP1aHeader().AddChildObject(channel);
+ essence_descriptor->SubDescriptors.push_back(channel->InstanceUID);
+ }
+ }
+
+ _asset->set_file (_file);
+ _started = true;
+}
+
+
void
SoundAssetWriter::write (float const * const * data, int frames)
{
@@ -110,13 +176,7 @@ SoundAssetWriter::write (float const * const * data, int frames)
static float const clip = 1.0f - (1.0f / pow (2, 23));
if (!_started) {
- Kumu::Result_t r = _state->mxf_writer.OpenWrite (_file.string().c_str(), _state->writer_info, _state->desc);
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (FileError ("could not open audio MXF for writing", _file.string(), r));
- }
-
- _asset->set_file (_file);
- _started = true;
+ start ();
}
int const ch = _asset->channels ();