X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2FAS_DCP_PCM.cpp;h=3956c71ed51b9948d376ad0227a9c709ea4bd1c6;hb=80463afc197c90372d3f4c7890c6520f1040aedc;hp=1db626c68a4384b38bea3ed6bb0e52ed158aead9;hpb=75319c36f1ce313cadac1a67d504312229204f0e;p=asdcplib.git diff --git a/src/AS_DCP_PCM.cpp b/src/AS_DCP_PCM.cpp index 1db626c..3956c71 100755 --- a/src/AS_DCP_PCM.cpp +++ b/src/AS_DCP_PCM.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2004-2006, John Hurst +Copyright (c) 2004-2012, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -31,9 +31,15 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "AS_DCP_internal.h" #include +#include +#include //------------------------------------------------------------------------------------------ +static const ASDCP::Dictionary *sg_dict = &DefaultSMPTEDict(); +static MXF::OPAtomHeader sg_OPAtomHeader(sg_dict); +static MXF::OPAtomIndexFooter sg_OPAtomIndexFooter(sg_dict); + static std::string PCM_PACKAGE_LABEL = "File Package: SMPTE 382M frame wrapping of wave audio"; static std::string SOUND_DEF_LABEL = "Sound Track"; @@ -42,7 +48,7 @@ Result_t PCM_ADesc_to_MD(PCM::AudioDescriptor& ADesc, MXF::WaveAudioDescriptor* ADescObj) { ASDCP_TEST_NULL(ADescObj); - ADescObj->SampleRate = ADesc.SampleRate; + ADescObj->SampleRate = ADesc.EditRate; ADescObj->AudioSamplingRate = ADesc.AudioSamplingRate; ADescObj->Locked = ADesc.Locked; ADescObj->ChannelCount = ADesc.ChannelCount; @@ -51,6 +57,32 @@ PCM_ADesc_to_MD(PCM::AudioDescriptor& ADesc, MXF::WaveAudioDescriptor* ADescObj) ADescObj->AvgBps = ADesc.AvgBps; ADescObj->LinkedTrackID = ADesc.LinkedTrackID; ADescObj->ContainerDuration = ADesc.ContainerDuration; + + ADescObj->ChannelAssignment.Reset(); + + switch ( ADesc.ChannelFormat ) + { + case PCM::CF_CFG_1: + ADescObj->ChannelAssignment = DefaultSMPTEDict().Type(MDD_DCAudioChannelCfg_1_5p1).ul; + break; + + case PCM::CF_CFG_2: + ADescObj->ChannelAssignment = DefaultSMPTEDict().Type(MDD_DCAudioChannelCfg_2_6p1).ul; + break; + + case PCM::CF_CFG_3: + ADescObj->ChannelAssignment = DefaultSMPTEDict().Type(MDD_DCAudioChannelCfg_3_7p1).ul; + break; + + case PCM::CF_CFG_4: + ADescObj->ChannelAssignment = DefaultSMPTEDict().Type(MDD_DCAudioChannelCfg_4_WTF).ul; + break; + + case PCM::CF_CFG_5: + ADescObj->ChannelAssignment = DefaultSMPTEDict().Type(MDD_DCAudioChannelCfg_5_7p1_DS).ul; + break; + } + return RESULT_OK; } @@ -59,7 +91,7 @@ ASDCP::Result_t MD_to_PCM_ADesc(MXF::WaveAudioDescriptor* ADescObj, PCM::AudioDescriptor& ADesc) { ASDCP_TEST_NULL(ADescObj); - ADesc.SampleRate = ADescObj->SampleRate; + ADesc.EditRate = ADescObj->SampleRate; ADesc.AudioSamplingRate = ADescObj->AudioSamplingRate; ADesc.Locked = ADescObj->Locked; ADesc.ChannelCount = ADescObj->ChannelCount; @@ -67,10 +99,50 @@ MD_to_PCM_ADesc(MXF::WaveAudioDescriptor* ADescObj, PCM::AudioDescriptor& ADesc) ADesc.BlockAlign = ADescObj->BlockAlign; ADesc.AvgBps = ADescObj->AvgBps; ADesc.LinkedTrackID = ADescObj->LinkedTrackID; - ADesc.ContainerDuration = ADescObj->ContainerDuration; + assert(ADescObj->ContainerDuration <= 0xFFFFFFFFL); + ADesc.ContainerDuration = (ui32_t) ADescObj->ContainerDuration; + + ADesc.ChannelFormat = PCM::CF_NONE; + + if ( ADescObj->ChannelAssignment.HasValue() ) + { + if ( ADescObj->ChannelAssignment == DefaultSMPTEDict().Type(MDD_DCAudioChannelCfg_1_5p1).ul ) + ADesc.ChannelFormat = PCM::CF_CFG_1; + + else if ( ADescObj->ChannelAssignment == DefaultSMPTEDict().Type(MDD_DCAudioChannelCfg_2_6p1).ul ) + ADesc.ChannelFormat = PCM::CF_CFG_2; + + else if ( ADescObj->ChannelAssignment == DefaultSMPTEDict().Type(MDD_DCAudioChannelCfg_3_7p1).ul ) + ADesc.ChannelFormat = PCM::CF_CFG_3; + + else if ( ADescObj->ChannelAssignment == DefaultSMPTEDict().Type(MDD_DCAudioChannelCfg_4_WTF).ul ) + ADesc.ChannelFormat = PCM::CF_CFG_4; + + else if ( ADescObj->ChannelAssignment == DefaultSMPTEDict().Type(MDD_DCAudioChannelCfg_5_7p1_DS).ul ) + ADesc.ChannelFormat = PCM::CF_CFG_5; + } + return RESULT_OK; } +// +std::ostream& +ASDCP::PCM::operator << (std::ostream& strm, const AudioDescriptor& ADesc) +{ + strm << " SampleRate: " << ADesc.EditRate.Numerator << "/" << ADesc.EditRate.Denominator << std::endl; + strm << " AudioSamplingRate: " << ADesc.AudioSamplingRate.Numerator << "/" << ADesc.AudioSamplingRate.Denominator << std::endl; + strm << " Locked: " << (unsigned) ADesc.Locked << std::endl; + strm << " ChannelCount: " << (unsigned) ADesc.ChannelCount << std::endl; + strm << " QuantizationBits: " << (unsigned) ADesc.QuantizationBits << std::endl; + strm << " BlockAlign: " << (unsigned) ADesc.BlockAlign << std::endl; + strm << " AvgBps: " << (unsigned) ADesc.AvgBps << std::endl; + strm << " LinkedTrackID: " << (unsigned) ADesc.LinkedTrackID << std::endl; + strm << " ContainerDuration: " << (unsigned) ADesc.ContainerDuration << std::endl; + + return strm; +} + +// void ASDCP::PCM::AudioDescriptorDump(const AudioDescriptor& ADesc, FILE* stream) { @@ -78,7 +150,7 @@ ASDCP::PCM::AudioDescriptorDump(const AudioDescriptor& ADesc, FILE* stream) stream = stderr; fprintf(stream, "\ - SampleRate: %d/%d\n\ + EditRate: %d/%d\n\ AudioSamplingRate: %d/%d\n\ Locked: %u\n\ ChannelCount: %u\n\ @@ -87,8 +159,8 @@ ASDCP::PCM::AudioDescriptorDump(const AudioDescriptor& ADesc, FILE* stream) AvgBps: %u\n\ LinkedTrackID: %u\n\ ContainerDuration: %u\n", - ADesc.SampleRate.Numerator ,ADesc.SampleRate.Denominator, - ADesc.AudioSamplingRate.Numerator ,ADesc.AudioSamplingRate.Denominator, + ADesc.EditRate.Numerator, ADesc.EditRate.Denominator, + ADesc.AudioSamplingRate.Numerator, ADesc.AudioSamplingRate.Denominator, ADesc.Locked, ADesc.ChannelCount, ADesc.QuantizationBits, @@ -131,11 +203,12 @@ calc_CBR_frame_size(ASDCP::WriterInfo& Info, const ASDCP::PCM::AudioDescriptor& class ASDCP::PCM::MXFReader::h__Reader : public ASDCP::h__Reader { ASDCP_NO_COPY_CONSTRUCT(h__Reader); + h__Reader(); public: AudioDescriptor m_ADesc; - h__Reader() {} + h__Reader(const Dictionary& d) : ASDCP::h__Reader(d) {} ~h__Reader() {} Result_t OpenRead(const char*); Result_t ReadFrame(ui32_t, FrameBuffer&, AESDecContext*, HMACContext*); @@ -161,19 +234,25 @@ ASDCP::PCM::MXFReader::h__Reader::OpenRead(const char* filename) // check for sample/frame rate sanity if ( ASDCP_SUCCESS(result) - && m_ADesc.SampleRate != EditRate_24 - && m_ADesc.SampleRate != EditRate_48 - && m_ADesc.SampleRate != EditRate_23_98 ) + && m_ADesc.EditRate != EditRate_24 + && m_ADesc.EditRate != EditRate_25 + && m_ADesc.EditRate != EditRate_30 + && m_ADesc.EditRate != EditRate_48 + && m_ADesc.EditRate != EditRate_50 + && m_ADesc.EditRate != EditRate_60 + && m_ADesc.EditRate != EditRate_96 + && m_ADesc.EditRate != EditRate_100 + && m_ADesc.EditRate != EditRate_120 + && m_ADesc.EditRate != EditRate_23_98 ) { - DefaultLogSink().Error("PCM file SampleRate is not 24/1, 48/1 or 24000/1001: %08x/%08x\n", // lu - m_ADesc.SampleRate.Numerator, m_ADesc.SampleRate.Denominator); + DefaultLogSink().Error("PCM file EditRate is not a supported value: %d/%d\n", // lu + m_ADesc.EditRate.Numerator, m_ADesc.EditRate.Denominator); // oh, they gave us the audio sampling rate instead, assume 24/1 - if ( m_ADesc.SampleRate == SampleRate_48k ) + if ( m_ADesc.EditRate == SampleRate_48k ) { - DefaultLogSink().Warn("adjusting SampleRate to 24/1\n"); - m_ADesc.SampleRate.Numerator = 24; - m_ADesc.SampleRate.Denominator = 1; + DefaultLogSink().Warn("adjusting EditRate to 24/1\n"); + m_ADesc.EditRate = EditRate_24; } else { @@ -203,7 +282,8 @@ ASDCP::PCM::MXFReader::h__Reader::ReadFrame(ui32_t FrameNum, FrameBuffer& FrameB if ( ! m_File.IsOpen() ) return RESULT_INIT; - return ReadEKLVFrame(FrameNum, FrameBuf, Dict::ul(MDD_WAVEssence), Ctx, HMAC); + assert(m_Dict); + return ReadEKLVFrame(FrameNum, FrameBuf, m_Dict->ul(MDD_WAVEssence), Ctx, HMAC); } //------------------------------------------------------------------------------------------ @@ -227,7 +307,7 @@ ASDCP::PCM::FrameBuffer::Dump(FILE* stream, ui32_t dump_len) const ASDCP::PCM::MXFReader::MXFReader() { - m_Reader = new h__Reader; + m_Reader = new h__Reader(DefaultCompositeDict()); } @@ -237,6 +317,30 @@ ASDCP::PCM::MXFReader::~MXFReader() m_Reader->Close(); } +// Warning: direct manipulation of MXF structures can interfere +// with the normal operation of the wrapper. Caveat emptor! +// +ASDCP::MXF::OPAtomHeader& +ASDCP::PCM::MXFReader::OPAtomHeader() +{ + if ( m_Reader.empty() ) + return sg_OPAtomHeader; + + return m_Reader->m_HeaderPart; +} + +// Warning: direct manipulation of MXF structures can interfere +// with the normal operation of the wrapper. Caveat emptor! +// +ASDCP::MXF::OPAtomIndexFooter& +ASDCP::PCM::MXFReader::OPAtomIndexFooter() +{ + if ( m_Reader.empty() ) + return sg_OPAtomIndexFooter; + + return m_Reader->m_FooterPart; +} + // Open the file for reading. The file must exist. Returns error if the // operation cannot be completed. ASDCP::Result_t @@ -305,20 +409,33 @@ ASDCP::PCM::MXFReader::DumpIndex(FILE* stream) const m_Reader->m_FooterPart.Dump(stream); } +// +ASDCP::Result_t +ASDCP::PCM::MXFReader::Close() const +{ + if ( m_Reader && m_Reader->m_File.IsOpen() ) + { + m_Reader->Close(); + return RESULT_OK; + } + + return RESULT_INIT; +} + //------------------------------------------------------------------------------------------ // class ASDCP::PCM::MXFWriter::h__Writer : public ASDCP::h__Writer { + ASDCP_NO_COPY_CONSTRUCT(h__Writer); + h__Writer(); + public: AudioDescriptor m_ADesc; byte_t m_EssenceUL[SMPTE_UL_LENGTH]; - - - ASDCP_NO_COPY_CONSTRUCT(h__Writer); - h__Writer(){ + h__Writer(const Dictionary& d) : ASDCP::h__Writer(d) { memset(m_EssenceUL, 0, SMPTE_UL_LENGTH); } @@ -345,7 +462,7 @@ ASDCP::PCM::MXFWriter::h__Writer::OpenWrite(const char* filename, ui32_t HeaderS if ( ASDCP_SUCCESS(result) ) { m_HeaderSize = HeaderSize; - m_EssenceDescriptor = new WaveAudioDescriptor; + m_EssenceDescriptor = new WaveAudioDescriptor(m_Dict); result = m_State.Goto_INIT(); } @@ -360,37 +477,50 @@ ASDCP::PCM::MXFWriter::h__Writer::SetSourceStream(const AudioDescriptor& ADesc) if ( ! m_State.Test_INIT() ) return RESULT_STATE; - if ( ADesc.SampleRate != EditRate_24 - && ADesc.SampleRate != EditRate_48 - && ADesc.SampleRate != EditRate_23_98 ) + if ( ADesc.EditRate != EditRate_24 + && ADesc.EditRate != EditRate_25 + && ADesc.EditRate != EditRate_30 + && ADesc.EditRate != EditRate_48 + && ADesc.EditRate != EditRate_50 + && ADesc.EditRate != EditRate_60 + && ADesc.EditRate != EditRate_96 + && ADesc.EditRate != EditRate_100 + && ADesc.EditRate != EditRate_120 + && ADesc.EditRate != EditRate_23_98 ) { - DefaultLogSink().Error("AudioDescriptor.SampleRate is not 24/1, 48/1 or 24000/1001: %d/%d\n", - ADesc.SampleRate.Numerator, ADesc.SampleRate.Denominator); + DefaultLogSink().Error("AudioDescriptor.EditRate is not a supported value: %d/%d\n", + ADesc.EditRate.Numerator, ADesc.EditRate.Denominator); return RESULT_RAW_FORMAT; } - if ( ADesc.AudioSamplingRate != SampleRate_48k ) + if ( ADesc.AudioSamplingRate != SampleRate_48k && ADesc.AudioSamplingRate != SampleRate_96k ) { - DefaultLogSink().Error("AudioDescriptor.AudioSamplingRate is not 48000/1: %d/%d\n", + DefaultLogSink().Error("AudioDescriptor.AudioSamplingRate is not 48000/1 or 96000/1: %d/%d\n", ADesc.AudioSamplingRate.Numerator, ADesc.AudioSamplingRate.Denominator); return RESULT_RAW_FORMAT; } + assert(m_Dict); m_ADesc = ADesc; + Result_t result = PCM_ADesc_to_MD(m_ADesc, (WaveAudioDescriptor*)m_EssenceDescriptor); - if ( ASDCP_SUCCESS(result) ) - result = WriteMXFHeader(PCM_PACKAGE_LABEL, UL(Dict::ul(MDD_WAVWrapping)), - SOUND_DEF_LABEL, UL(Dict::ul(MDD_SoundDataDef)), - m_ADesc.SampleRate, 24 /* TCFrameRate */, calc_CBR_frame_size(m_Info, m_ADesc)); - if ( ASDCP_SUCCESS(result) ) { - memcpy(m_EssenceUL, Dict::ul(MDD_WAVEssence), SMPTE_UL_LENGTH); + memcpy(m_EssenceUL, m_Dict->ul(MDD_WAVEssence), SMPTE_UL_LENGTH); m_EssenceUL[SMPTE_UL_LENGTH-1] = 1; // first (and only) essence container result = m_State.Goto_READY(); } + if ( ASDCP_SUCCESS(result) ) + { + ui32_t TCFrameRate = ( m_ADesc.EditRate == EditRate_23_98 ) ? 24 : m_ADesc.EditRate.Numerator; + + result = WriteMXFHeader(PCM_PACKAGE_LABEL, UL(m_Dict->ul(MDD_WAVWrapping)), + SOUND_DEF_LABEL, UL(m_EssenceUL), UL(m_Dict->ul(MDD_SoundDataDef)), + m_ADesc.EditRate, TCFrameRate, calc_CBR_frame_size(m_Info, m_ADesc)); + } + return result; } @@ -442,6 +572,29 @@ ASDCP::PCM::MXFWriter::~MXFWriter() { } +// Warning: direct manipulation of MXF structures can interfere +// with the normal operation of the wrapper. Caveat emptor! +// +ASDCP::MXF::OPAtomHeader& +ASDCP::PCM::MXFWriter::OPAtomHeader() +{ + if ( m_Writer.empty() ) + return sg_OPAtomHeader; + + return m_Writer->m_HeaderPart; +} + +// Warning: direct manipulation of MXF structures can interfere +// with the normal operation of the wrapper. Caveat emptor! +// +ASDCP::MXF::OPAtomIndexFooter& +ASDCP::PCM::MXFWriter::OPAtomIndexFooter() +{ + if ( m_Writer.empty() ) + return sg_OPAtomIndexFooter; + + return m_Writer->m_FooterPart; +} // Open the file for writing. The file must not exist. Returns error if // the operation cannot be completed. @@ -449,7 +602,11 @@ ASDCP::Result_t ASDCP::PCM::MXFWriter::OpenWrite(const char* filename, const WriterInfo& Info, const AudioDescriptor& ADesc, ui32_t HeaderSize) { - m_Writer = new h__Writer; + if ( Info.LabelSetType == LS_MXF_SMPTE ) + m_Writer = new h__Writer(DefaultSMPTEDict()); + else + m_Writer = new h__Writer(DefaultInteropDict()); + m_Writer->m_Info = Info; Result_t result = m_Writer->OpenWrite(filename, HeaderSize);