X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2FAS_DCP_PCM.cpp;h=9de8d53bd76ec2abb23a5014f3b6a46baa10ab66;hb=80490136d3f872d162670e616827033fdd1be09d;hp=606a6f5d4356fe7a04a90a3762680744c54b7849;hpb=9998b893b47f111f41c4f0fcf1067efe5b7a62f3;p=asdcplib.git diff --git a/src/AS_DCP_PCM.cpp b/src/AS_DCP_PCM.cpp index 606a6f5..9de8d53 100755 --- a/src/AS_DCP_PCM.cpp +++ b/src/AS_DCP_PCM.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2004-2012, John Hurst +Copyright (c) 2004-2013, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -54,7 +54,7 @@ ASDCP::PCM_ADesc_to_MD(PCM::AudioDescriptor& ADesc, MXF::WaveAudioDescriptor* AD ADescObj->LinkedTrackID = ADesc.LinkedTrackID; ADescObj->ContainerDuration = ADesc.ContainerDuration; - ADescObj->ChannelAssignment.Reset(); + ADescObj->ChannelAssignment.get().Reset(); switch ( ADesc.ChannelFormat ) { @@ -77,6 +77,10 @@ ASDCP::PCM_ADesc_to_MD(PCM::AudioDescriptor& ADesc, MXF::WaveAudioDescriptor* AD case PCM::CF_CFG_5: ADescObj->ChannelAssignment = DefaultSMPTEDict().Type(MDD_DCAudioChannelCfg_5_7p1_DS).ul; break; + + case PCM::CF_CFG_6: + ADescObj->ChannelAssignment = DefaultSMPTEDict().Type(MDD_DCAudioChannelCfg_MCA).ul; + break; } return RESULT_OK; @@ -100,7 +104,7 @@ ASDCP::MD_to_PCM_ADesc(MXF::WaveAudioDescriptor* ADescObj, PCM::AudioDescriptor& ADesc.ChannelFormat = PCM::CF_NONE; - if ( ADescObj->ChannelAssignment.HasValue() ) + if ( ! ADescObj->ChannelAssignment.empty() ) { if ( ADescObj->ChannelAssignment == DefaultSMPTEDict().Type(MDD_DCAudioChannelCfg_1_5p1).ul ) ADesc.ChannelFormat = PCM::CF_CFG_1; @@ -116,6 +120,9 @@ ASDCP::MD_to_PCM_ADesc(MXF::WaveAudioDescriptor* ADescObj, PCM::AudioDescriptor& else if ( ADescObj->ChannelAssignment == DefaultSMPTEDict().Type(MDD_DCAudioChannelCfg_5_7p1_DS).ul ) ADesc.ChannelFormat = PCM::CF_CFG_5; + + else if ( ADescObj->ChannelAssignment == DefaultSMPTEDict().Type(MDD_DCAudioChannelCfg_MCA).ul ) + ADesc.ChannelFormat = PCM::CF_CFG_6; } return RESULT_OK; @@ -134,6 +141,39 @@ ASDCP::PCM::operator << (std::ostream& strm, const AudioDescriptor& ADesc) strm << " AvgBps: " << (unsigned) ADesc.AvgBps << std::endl; strm << " LinkedTrackID: " << (unsigned) ADesc.LinkedTrackID << std::endl; strm << " ContainerDuration: " << (unsigned) ADesc.ContainerDuration << std::endl; + strm << " ChannelFormat: "; + switch (ADesc.ChannelFormat) + { + case CF_NONE: + default: + strm << "No Channel Format"; + break; + + case CF_CFG_1: + strm << "Config 1 (5.1 with optional HI/VI)"; + break; + + case CF_CFG_2: + strm << "Config 2 (5.1 + center surround with optional HI/VI)"; + break; + + case CF_CFG_3: + strm << "Config 3 (7.1 with optional HI/VI)"; + break; + + case CF_CFG_4: + strm << "Config 4"; + break; + + case CF_CFG_5: + strm << "Config 5 (7.1 DS with optional HI/VI)"; + break; + + case CF_CFG_6: + strm << "Config 6 (ST 377-1 MCA)"; + break; + } + strm << std::endl; return strm; } @@ -154,7 +194,8 @@ ASDCP::PCM::AudioDescriptorDump(const AudioDescriptor& ADesc, FILE* stream) BlockAlign: %u\n\ AvgBps: %u\n\ LinkedTrackID: %u\n\ - ContainerDuration: %u\n", + ContainerDuration: %u\n\ + ChannelFormat: %u\n", ADesc.EditRate.Numerator, ADesc.EditRate.Denominator, ADesc.AudioSamplingRate.Numerator, ADesc.AudioSamplingRate.Denominator, ADesc.Locked, @@ -163,7 +204,8 @@ ASDCP::PCM::AudioDescriptorDump(const AudioDescriptor& ADesc, FILE* stream) ADesc.BlockAlign, ADesc.AvgBps, ADesc.LinkedTrackID, - ADesc.ContainerDuration + ADesc.ContainerDuration, + ADesc.ChannelFormat ); } @@ -205,8 +247,8 @@ public: AudioDescriptor m_ADesc; h__Reader(const Dictionary& d) : ASDCP::h__ASDCPReader(d) {} - ~h__Reader() {} - Result_t OpenRead(const char*); + virtual ~h__Reader() {} + Result_t OpenRead(const std::string&); Result_t ReadFrame(ui32_t, FrameBuffer&, AESDecContext*, HMACContext*); }; @@ -214,20 +256,32 @@ public: // // ASDCP::Result_t -ASDCP::PCM::MXFReader::h__Reader::OpenRead(const char* filename) +ASDCP::PCM::MXFReader::h__Reader::OpenRead(const std::string& filename) { Result_t result = OpenMXFRead(filename); if( ASDCP_SUCCESS(result) ) { - InterchangeObject* Object; + InterchangeObject* Object = 0 +; if ( ASDCP_SUCCESS(m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(WaveAudioDescriptor), &Object)) ) { - assert(Object); + if ( Object == 0 ) + { + DefaultLogSink().Error("WaveAudioDescriptor object not found.\n"); + return RESULT_FORMAT; + } + result = MD_to_PCM_ADesc((MXF::WaveAudioDescriptor*)Object, m_ADesc); } } + if ( m_ADesc.ContainerDuration == 0 ) + { + DefaultLogSink().Error("ContainerDuration unset.\n"); + return RESULT_FORMAT; + } + // check for sample/frame rate sanity if ( ASDCP_SUCCESS(result) && m_ADesc.EditRate != EditRate_24 @@ -249,24 +303,19 @@ ASDCP::PCM::MXFReader::h__Reader::OpenRead(const char* filename) m_ADesc.EditRate.Numerator, m_ADesc.EditRate.Denominator); // oh, they gave us the audio sampling rate instead, assume 24/1 - if ( m_ADesc.EditRate == SampleRate_48k ) + if ( m_ADesc.EditRate == SampleRate_48k || m_ADesc.EditRate == SampleRate_96k ) { DefaultLogSink().Warn("adjusting EditRate to 24/1\n"); m_ADesc.EditRate = EditRate_24; } else { + DefaultLogSink().Error("PCM EditRate not in expected value range.\n"); // or we just drop the hammer return RESULT_FORMAT; } } - if( ASDCP_SUCCESS(result) ) - result = InitMXFIndex(); - - if( ASDCP_SUCCESS(result) ) - result = InitInfo(); - // TODO: test file for sane CBR index BytesPerEditUnit return result; @@ -282,6 +331,11 @@ ASDCP::PCM::MXFReader::h__Reader::ReadFrame(ui32_t FrameNum, FrameBuffer& FrameB if ( ! m_File.IsOpen() ) return RESULT_INIT; + if ( (FrameNum+1) > m_ADesc.ContainerDuration ) + { + return RESULT_RANGE; + } + assert(m_Dict); return ReadEKLVFrame(FrameNum, FrameBuf, m_Dict->ul(MDD_WAVEssence), Ctx, HMAC); } @@ -320,13 +374,13 @@ ASDCP::PCM::MXFReader::~MXFReader() // Warning: direct manipulation of MXF structures can interfere // with the normal operation of the wrapper. Caveat emptor! // -ASDCP::MXF::OPAtomHeader& -ASDCP::PCM::MXFReader::OPAtomHeader() +ASDCP::MXF::OP1aHeader& +ASDCP::PCM::MXFReader::OP1aHeader() { if ( m_Reader.empty() ) { - assert(g_OPAtomHeader); - return *g_OPAtomHeader; + assert(g_OP1aHeader); + return *g_OP1aHeader; } return m_Reader->m_HeaderPart; @@ -344,13 +398,28 @@ ASDCP::PCM::MXFReader::OPAtomIndexFooter() return *g_OPAtomIndexFooter; } - return m_Reader->m_FooterPart; + return m_Reader->m_IndexAccess; +} + +// Warning: direct manipulation of MXF structures can interfere +// with the normal operation of the wrapper. Caveat emptor! +// +ASDCP::MXF::RIP& +ASDCP::PCM::MXFReader::RIP() +{ + if ( m_Reader.empty() ) + { + assert(g_RIP); + return *g_RIP; + } + + return m_Reader->m_RIP; } // Open the file for reading. The file must exist. Returns error if the // operation cannot be completed. ASDCP::Result_t -ASDCP::PCM::MXFReader::OpenRead(const char* filename) const +ASDCP::PCM::MXFReader::OpenRead(const std::string& filename) const { return m_Reader->OpenRead(filename); } @@ -370,6 +439,12 @@ ASDCP::PCM::MXFReader::ReadFrame(ui32_t FrameNum, FrameBuffer& FrameBuf, } +ASDCP::Result_t +ASDCP::PCM::MXFReader::LocateFrame(ui32_t FrameNum, Kumu::fpos_t& streamOffset, i8_t& temporalOffset, i8_t& keyFrameOffset) const +{ + return m_Reader->LocateFrame(FrameNum, streamOffset, temporalOffset, keyFrameOffset); +} + // Fill the struct with the values from the file's header. // Returns RESULT_INIT if the file is not open. ASDCP::Result_t @@ -412,7 +487,7 @@ void ASDCP::PCM::MXFReader::DumpIndex(FILE* stream) const { if ( m_Reader->m_File.IsOpen() ) - m_Reader->m_FooterPart.Dump(stream); + m_Reader->m_IndexAccess.Dump(stream); } // @@ -432,7 +507,7 @@ ASDCP::PCM::MXFReader::Close() const //------------------------------------------------------------------------------------------ // -class ASDCP::PCM::MXFWriter::h__Writer : public ASDCP::h__Writer +class ASDCP::PCM::MXFWriter::h__Writer : public ASDCP::h__ASDCPWriter { ASDCP_NO_COPY_CONSTRUCT(h__Writer); h__Writer(); @@ -441,13 +516,13 @@ public: AudioDescriptor m_ADesc; byte_t m_EssenceUL[SMPTE_UL_LENGTH]; - h__Writer(const Dictionary& d) : ASDCP::h__Writer(d) { + h__Writer(const Dictionary& d) : ASDCP::h__ASDCPWriter(d) { memset(m_EssenceUL, 0, SMPTE_UL_LENGTH); } - ~h__Writer(){} + virtual ~h__Writer(){} - Result_t OpenWrite(const char*, ui32_t HeaderSize); + Result_t OpenWrite(const std::string&, ui32_t HeaderSize); Result_t SetSourceStream(const AudioDescriptor&); Result_t WriteFrame(const FrameBuffer&, AESEncContext* = 0, HMACContext* = 0); Result_t Finalize(); @@ -458,7 +533,7 @@ public: // Open the file for writing. The file must not exist. Returns error if // the operation cannot be completed. ASDCP::Result_t -ASDCP::PCM::MXFWriter::h__Writer::OpenWrite(const char* filename, ui32_t HeaderSize) +ASDCP::PCM::MXFWriter::h__Writer::OpenWrite(const std::string& filename, ui32_t HeaderSize) { if ( ! m_State.Test_BEGIN() ) return RESULT_STATE; @@ -524,18 +599,10 @@ ASDCP::PCM::MXFWriter::h__Writer::SetSourceStream(const AudioDescriptor& ADesc) if ( ASDCP_SUCCESS(result) ) { - ui32_t TCFrameRate = m_ADesc.EditRate.Numerator; - - if ( m_ADesc.EditRate == EditRate_23_98 ) - TCFrameRate = 24; - else if ( m_ADesc.EditRate == EditRate_18 ) - TCFrameRate = 18; - else if ( m_ADesc.EditRate == EditRate_22 ) - TCFrameRate = 22; - - 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)); + result = WriteASDCPHeader(PCM_PACKAGE_LABEL, UL(m_Dict->ul(MDD_WAVWrappingFrame)), + SOUND_DEF_LABEL, UL(m_EssenceUL), UL(m_Dict->ul(MDD_SoundDataDef)), + m_ADesc.EditRate, derive_timecode_rate_from_edit_rate(m_ADesc.EditRate), + calc_CBR_frame_size(m_Info, m_ADesc)); } return result; @@ -572,7 +639,7 @@ ASDCP::PCM::MXFWriter::h__Writer::Finalize() m_State.Goto_FINAL(); - return WriteMXFFooter(); + return WriteASDCPFooter(); } @@ -592,13 +659,13 @@ 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() +ASDCP::MXF::OP1aHeader& +ASDCP::PCM::MXFWriter::OP1aHeader() { if ( m_Writer.empty() ) { - assert(g_OPAtomHeader); - return *g_OPAtomHeader; + assert(g_OP1aHeader); + return *g_OP1aHeader; } return m_Writer->m_HeaderPart; @@ -619,10 +686,25 @@ ASDCP::PCM::MXFWriter::OPAtomIndexFooter() return m_Writer->m_FooterPart; } +// Warning: direct manipulation of MXF structures can interfere +// with the normal operation of the wrapper. Caveat emptor! +// +ASDCP::MXF::RIP& +ASDCP::PCM::MXFWriter::RIP() +{ + if ( m_Writer.empty() ) + { + assert(g_RIP); + return *g_RIP; + } + + return m_Writer->m_RIP; +} + // Open the file for writing. The file must not exist. Returns error if // the operation cannot be completed. ASDCP::Result_t -ASDCP::PCM::MXFWriter::OpenWrite(const char* filename, const WriterInfo& Info, +ASDCP::PCM::MXFWriter::OpenWrite(const std::string& filename, const WriterInfo& Info, const AudioDescriptor& ADesc, ui32_t HeaderSize) { if ( Info.LabelSetType == LS_MXF_SMPTE )