X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Fsound_asset.cc;h=0cc7cdbae4e9ecfda4b15ffb09ab02ffc139cd91;hb=bf59c288798851808359575662f202d390032aa7;hp=08ca71e513e980381bb832269b44ea9dbedebdbb;hpb=c21da9cdd8284e8d36a08bc7976744a3cd74bede;p=libdcp.git diff --git a/src/sound_asset.cc b/src/sound_asset.cc index 08ca71e5..0cc7cdba 100644 --- a/src/sound_asset.cc +++ b/src/sound_asset.cc @@ -25,6 +25,7 @@ #include #include #include +#include #include "KM_fileio.h" #include "AS_DCP.h" #include "sound_asset.h" @@ -41,53 +42,32 @@ using boost::shared_ptr; using boost::lexical_cast; using namespace libdcp; -SoundAsset::SoundAsset ( - vector const & files, - string directory, - string mxf_name, - boost::signals2::signal* progress, - int fps, int intrinsic_duration, int start_frame - ) - : MXFAsset (directory, mxf_name, progress, fps, intrinsic_duration) - , _channels (files.size ()) +SoundAsset::SoundAsset (boost::filesystem::path directory, boost::filesystem::path mxf_name) + : MXFAsset (directory, mxf_name) + , _channels (0) , _sampling_rate (0) - , _start_frame (start_frame) { - assert (_channels); - - construct (boost::bind (&SoundAsset::path_from_channel, this, _1, files)); + } -SoundAsset::SoundAsset ( - boost::function get_path, - string directory, - string mxf_name, - boost::signals2::signal* progress, - int fps, int intrinsic_duration, int start_frame, int channels - ) - : MXFAsset (directory, mxf_name, progress, fps, intrinsic_duration) - , _channels (channels) - , _sampling_rate (0) - , _start_frame (start_frame) +void +SoundAsset::create (vector const & files) { - assert (_channels); - - construct (get_path); + create (boost::bind (&SoundAsset::path_from_channel, this, _1, files)); } -SoundAsset::SoundAsset (string directory, string mxf_name) - : MXFAsset (directory, mxf_name) - , _channels (0) - , _start_frame (0) +void +SoundAsset::read () { ASDCP::PCM::MXFReader reader; - if (ASDCP_FAILURE (reader.OpenRead (path().string().c_str()))) { - throw MXFFileError ("could not open MXF file for reading", path().string()); + Kumu::Result_t r = reader.OpenRead (path().string().c_str()); + if (ASDCP_FAILURE (r)) { + boost::throw_exception (MXFFileError ("could not open MXF file for reading", path().string(), r)); } ASDCP::PCM::AudioDescriptor desc; if (ASDCP_FAILURE (reader.FillAudioDescriptor (desc))) { - throw DCPReadError ("could not read audio MXF information"); + boost::throw_exception (DCPReadError ("could not read audio MXF information")); } _sampling_rate = desc.AudioSamplingRate.Numerator / desc.AudioSamplingRate.Denominator; @@ -97,17 +77,8 @@ SoundAsset::SoundAsset (string directory, string mxf_name) _intrinsic_duration = desc.ContainerDuration; } -SoundAsset::SoundAsset (string directory, string mxf_name, int fps, int channels, int sampling_rate) - : MXFAsset (directory, mxf_name, 0, fps, 0) - , _channels (channels) - , _sampling_rate (sampling_rate) - , _start_frame (0) -{ - -} - -string -SoundAsset::path_from_channel (Channel channel, vector const & files) +boost::filesystem::path +SoundAsset::path_from_channel (Channel channel, vector const & files) { unsigned int const c = int (channel); assert (c < files.size ()); @@ -115,17 +86,23 @@ SoundAsset::path_from_channel (Channel channel, vector const & files) } void -SoundAsset::construct (boost::function get_path) +SoundAsset::create (boost::function get_path) { ASDCP::Rational asdcp_edit_rate (_edit_rate, 1); - ASDCP::PCM::WAVParser pcm_parser_channel[_channels]; - if (pcm_parser_channel[0].OpenRead (get_path(LEFT).c_str(), asdcp_edit_rate)) { - throw FileError ("could not open WAV file for reading", get_path(LEFT)); + assert (_channels > 0); + ASDCP::PCM::WAVParser* pcm_parser_channel[_channels]; + for (int i = 0; i < _channels; ++i) { + pcm_parser_channel[i] = new ASDCP::PCM::WAVParser (); + } + + Kumu::Result_t r = pcm_parser_channel[0]->OpenRead (get_path(LEFT).string().c_str(), asdcp_edit_rate); + if (ASDCP_FAILURE (r)) { + boost::throw_exception (FileError ("could not open WAV file for reading", get_path(LEFT), r)); } ASDCP::PCM::AudioDescriptor audio_desc; - pcm_parser_channel[0].FillAudioDescriptor (audio_desc); + pcm_parser_channel[0]->FillAudioDescriptor (audio_desc); audio_desc.ChannelCount = 0; audio_desc.BlockAlign = 0; audio_desc.EditRate = asdcp_edit_rate; @@ -145,22 +122,27 @@ SoundAsset::construct (boost::function get_path) assert (int(_channels) <= int(sizeof(channels) / sizeof(Channel))); - ASDCP::PCM::FrameBuffer frame_buffer_channel[_channels]; - ASDCP::PCM::AudioDescriptor audio_desc_channel[_channels]; + ASDCP::PCM::FrameBuffer* frame_buffer_channel[_channels]; + ASDCP::PCM::AudioDescriptor* audio_desc_channel[_channels]; + for (int i = 0; i < _channels; ++i) { + frame_buffer_channel[i] = new ASDCP::PCM::FrameBuffer (); + audio_desc_channel[i] = new ASDCP::PCM::AudioDescriptor (); + } for (int i = 0; i < _channels; ++i) { - string const path = get_path (channels[i]); + boost::filesystem::path const path = get_path (channels[i]); - if (ASDCP_FAILURE (pcm_parser_channel[i].OpenRead (path.c_str(), asdcp_edit_rate))) { - throw FileError ("could not open WAV file for reading", path); + Kumu::Result_t r = pcm_parser_channel[i]->OpenRead (path.string().c_str(), asdcp_edit_rate); + if (ASDCP_FAILURE (r)) { + boost::throw_exception (FileError ("could not open WAV file for reading", path, r)); } - pcm_parser_channel[i].FillAudioDescriptor (audio_desc_channel[i]); - frame_buffer_channel[i].Capacity (ASDCP::PCM::CalcFrameBufferSize (audio_desc_channel[i])); + pcm_parser_channel[i]->FillAudioDescriptor (*audio_desc_channel[i]); + frame_buffer_channel[i]->Capacity (ASDCP::PCM::CalcFrameBufferSize (*audio_desc_channel[i])); - audio_desc.ChannelCount += audio_desc_channel[i].ChannelCount; - audio_desc.BlockAlign += audio_desc_channel[i].BlockAlign; + audio_desc.ChannelCount += audio_desc_channel[i]->ChannelCount; + audio_desc.BlockAlign += audio_desc_channel[i]->BlockAlign; } ASDCP::PCM::FrameBuffer frame_buffer; @@ -168,47 +150,39 @@ SoundAsset::construct (boost::function get_path) frame_buffer.Size (ASDCP::PCM::CalcFrameBufferSize (audio_desc)); ASDCP::WriterInfo writer_info; - MXFAsset::fill_writer_info (&writer_info, _uuid); + MXFAsset::fill_writer_info (&writer_info, _uuid, _metadata); ASDCP::PCM::MXFWriter mxf_writer; - if (ASDCP_FAILURE (mxf_writer.OpenWrite (path().string().c_str(), writer_info, audio_desc))) { - throw FileError ("could not open audio MXF for writing", path().string()); - } - - /* Skip through up to our _start_frame; this is pretty inefficient... */ - for (int i = 0; i < _start_frame; ++i) { - for (int j = 0; j < _channels; ++j) { - if (ASDCP_FAILURE (pcm_parser_channel[j].ReadFrame (frame_buffer_channel[j]))) { - throw MiscError ("could not read audio frame"); - } - } + r = mxf_writer.OpenWrite (path().string().c_str(), writer_info, audio_desc); + if (ASDCP_FAILURE (r)) { + boost::throw_exception (FileError ("could not open audio MXF for writing", path().string(), r)); } for (int i = 0; i < _intrinsic_duration; ++i) { for (int j = 0; j < _channels; ++j) { - memset (frame_buffer_channel[j].Data(), 0, frame_buffer_channel[j].Capacity()); - if (ASDCP_FAILURE (pcm_parser_channel[j].ReadFrame (frame_buffer_channel[j]))) { - throw MiscError ("could not read audio frame"); + memset (frame_buffer_channel[j]->Data(), 0, frame_buffer_channel[j]->Capacity()); + if (ASDCP_FAILURE (pcm_parser_channel[j]->ReadFrame (*frame_buffer_channel[j]))) { + boost::throw_exception (MiscError ("could not read audio frame")); } } byte_t *data_s = frame_buffer.Data(); byte_t *data_e = data_s + frame_buffer.Capacity(); - byte_t sample_size = ASDCP::PCM::CalcSampleSize (audio_desc_channel[0]); + byte_t sample_size = ASDCP::PCM::CalcSampleSize (*audio_desc_channel[0]); int offset = 0; while (data_s < data_e) { for (int j = 0; j < _channels; ++j) { - byte_t* frame = frame_buffer_channel[j].Data() + offset; + byte_t* frame = frame_buffer_channel[j]->Data() + offset; memcpy (data_s, frame, sample_size); data_s += sample_size; } offset += sample_size; } - if (ASDCP_FAILURE (mxf_writer.WriteFrame (frame_buffer, 0, 0))) { - throw MiscError ("could not write audio MXF frame"); + if (ASDCP_FAILURE (mxf_writer.WriteFrame (frame_buffer, _encryption_context, 0))) { + boost::throw_exception (MiscError ("could not write audio MXF frame")); } if (_progress) { @@ -216,48 +190,51 @@ SoundAsset::construct (boost::function get_path) } } - if (ASDCP_FAILURE (mxf_writer.Finalize())) { - throw MiscError ("could not finalise audio MXF"); + bool const failed = ASDCP_FAILURE (mxf_writer.Finalize()); + + for (int i = 0; i < _channels; ++i) { + delete pcm_parser_channel[i]; + delete frame_buffer_channel[i]; + delete audio_desc_channel[i]; + } + + if (failed) { + boost::throw_exception (MiscError ("could not finalise audio MXF")); } } -void -SoundAsset::write_to_cpl (ostream& s) const +string +SoundAsset::cpl_node_name () const { - s << " \n" - << " urn:uuid:" << _uuid << "\n" - << " " << _file_name << "\n" - << " " << _edit_rate << " 1\n" - << " " << _intrinsic_duration << "\n" - << " " << _entry_point << "\n" - << " " << _duration << "\n" - << " \n"; + return "MainSound"; } bool -SoundAsset::equals (shared_ptr other, EqualityOptions opt, list& notes) const +SoundAsset::equals (shared_ptr other, EqualityOptions opt, boost::function note) const { - if (!MXFAsset::equals (other, opt, notes)) { + if (!MXFAsset::equals (other, opt, note)) { return false; } ASDCP::PCM::MXFReader reader_A; - if (ASDCP_FAILURE (reader_A.OpenRead (path().string().c_str()))) { - throw MXFFileError ("could not open MXF file for reading", path().string()); + Kumu::Result_t r = reader_A.OpenRead (path().string().c_str()); + if (ASDCP_FAILURE (r)) { + boost::throw_exception (MXFFileError ("could not open MXF file for reading", path().string(), r)); } ASDCP::PCM::MXFReader reader_B; - if (ASDCP_FAILURE (reader_B.OpenRead (other->path().string().c_str()))) { - throw MXFFileError ("could not open MXF file for reading", path().string()); + r = reader_B.OpenRead (other->path().string().c_str()); + if (ASDCP_FAILURE (r)) { + boost::throw_exception (MXFFileError ("could not open MXF file for reading", path().string(), r)); } ASDCP::PCM::AudioDescriptor desc_A; if (ASDCP_FAILURE (reader_A.FillAudioDescriptor (desc_A))) { - throw DCPReadError ("could not read audio MXF information"); + boost::throw_exception (DCPReadError ("could not read audio MXF information")); } ASDCP::PCM::AudioDescriptor desc_B; if (ASDCP_FAILURE (reader_B.FillAudioDescriptor (desc_B))) { - throw DCPReadError ("could not read audio MXF information"); + boost::throw_exception (DCPReadError ("could not read audio MXF information")); } if ( @@ -273,7 +250,7 @@ SoundAsset::equals (shared_ptr other, EqualityOptions opt, list other, EqualityOptions opt, list(i) + " differ"); + note (ERROR, "sizes of audio data for frame " + lexical_cast(i) + " differ"); return false; } @@ -298,7 +275,7 @@ SoundAsset::equals (shared_ptr other, EqualityOptions opt, list opt.max_audio_sample_error) { - notes.push_back ("PCM data difference of " + lexical_cast (d)); + note (ERROR, "PCM data difference of " + lexical_cast (d)); return false; } } @@ -311,7 +288,8 @@ SoundAsset::equals (shared_ptr other, EqualityOptions opt, list SoundAsset::get_frame (int n) const { - return shared_ptr (new SoundFrame (path().string(), n + _entry_point)); + /* XXX: should add on entry point here? */ + return shared_ptr (new SoundFrame (path().string(), n, _decryption_context)); } shared_ptr @@ -327,6 +305,7 @@ struct SoundAssetWriter::ASDCPState ASDCP::PCM::FrameBuffer frame_buffer; ASDCP::WriterInfo writer_info; ASDCP::PCM::AudioDescriptor audio_desc; + ASDCP::AESEncContext* encryption_context; }; SoundAssetWriter::SoundAssetWriter (SoundAsset* a) @@ -336,6 +315,8 @@ SoundAssetWriter::SoundAssetWriter (SoundAsset* a) , _frames_written (0) , _frame_buffer_offset (0) { + _state->encryption_context = a->encryption_context (); + /* Derived from ASDCP::Wav::SimpleWaveHeader::FillADesc */ _state->audio_desc.EditRate = ASDCP::Rational (_asset->edit_rate(), 1); _state->audio_desc.AudioSamplingRate = ASDCP::Rational (_asset->sampling_rate(), 1); @@ -351,10 +332,11 @@ SoundAssetWriter::SoundAssetWriter (SoundAsset* a) _state->frame_buffer.Size (ASDCP::PCM::CalcFrameBufferSize (_state->audio_desc)); memset (_state->frame_buffer.Data(), 0, _state->frame_buffer.Capacity()); - MXFAsset::fill_writer_info (&_state->writer_info, _asset->uuid ()); + _asset->fill_writer_info (&_state->writer_info, _asset->uuid (), _asset->metadata()); - if (ASDCP_FAILURE (_state->mxf_writer.OpenWrite (_asset->path().c_str(), _state->writer_info, _state->audio_desc))) { - throw FileError ("could not open audio MXF for writing", _asset->path().string()); + Kumu::Result_t r = _state->mxf_writer.OpenWrite (_asset->path().string().c_str(), _state->writer_info, _state->audio_desc); + if (ASDCP_FAILURE (r)) { + boost::throw_exception (FileError ("could not open audio MXF for writing", _asset->path().string(), r)); } } @@ -388,8 +370,9 @@ SoundAssetWriter::write (float const * const * data, int frames) void SoundAssetWriter::write_current_frame () { - if (ASDCP_FAILURE (_state->mxf_writer.WriteFrame (_state->frame_buffer, 0, 0))) { - throw MiscError ("could not write audio MXF frame"); + ASDCP::Result_t const r = _state->mxf_writer.WriteFrame (_state->frame_buffer, _state->encryption_context, 0); + if (ASDCP_FAILURE (r)) { + boost::throw_exception (MiscError ("could not write audio MXF frame (" + lexical_cast (int (r)) + ")")); } ++_frames_written; @@ -403,7 +386,7 @@ SoundAssetWriter::finalize () } if (ASDCP_FAILURE (_state->mxf_writer.Finalize())) { - throw MiscError ("could not finalise audio MXF"); + boost::throw_exception (MiscError ("could not finalise audio MXF")); } _finalized = true; @@ -411,7 +394,8 @@ SoundAssetWriter::finalize () _asset->set_duration (_frames_written); } -SoundAssetWriter::~SoundAssetWriter () +string +SoundAsset::key_type () const { - assert (_finalized); + return "MDAK"; }