X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Fh__Reader.cpp;h=7a1dd12ea43e1dde757d8a99124785866bb73b19;hb=fd73a272189d3d121989b8437b7fbe5402160aaa;hp=38c497f5d99eea7ae878b0ee81079a969248ac20;hpb=d440dbd72e7b3395c589a72e391eb33b6d2109f4;p=asdcplib.git diff --git a/src/h__Reader.cpp b/src/h__Reader.cpp index 38c497f..7a1dd12 100755 --- a/src/h__Reader.cpp +++ b/src/h__Reader.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2004-2005, John Hurst +Copyright (c) 2004-2009, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -31,14 +31,13 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "AS_DCP_internal.h" #include "KLV.h" -#include "MDD.h" -#include using namespace ASDCP; using namespace ASDCP::MXF; // -ASDCP::h__Reader::h__Reader() : m_EssenceStart(0) +ASDCP::h__Reader::h__Reader(const Dictionary& d) : + m_HeaderPart(m_Dict), m_BodyPart(m_Dict), m_FooterPart(m_Dict), m_Dict(&d), m_EssenceStart(0) { } @@ -58,10 +57,19 @@ ASDCP::h__Reader::Close() // Result_t -ASDCP::h__Reader::InitInfo(WriterInfo& Info) +ASDCP::h__Reader::InitInfo() { InterchangeObject* Object; + m_Info.LabelSetType = LS_MXF_UNKNOWN; + UL OPAtomUL(m_Dict->ul(MDD_OPAtom)); + UL Interop_OPAtomUL(m_Dict->ul(MDD_MXFInterop_OPAtom)); + + if ( m_HeaderPart.OperationalPattern == Interop_OPAtomUL ) + m_Info.LabelSetType = LS_MXF_INTEROP; + else if ( m_HeaderPart.OperationalPattern == OPAtomUL ) + m_Info.LabelSetType = LS_MXF_SMPTE; + // Identification Result_t result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(Identification), &Object); @@ -75,7 +83,7 @@ ASDCP::h__Reader::InitInfo(WriterInfo& Info) if( ASDCP_SUCCESS(result) ) { SourcePackage* SP = (SourcePackage*)Object; - memcpy(Info.AssetUUID, SP->PackageUID.Data() + 16, UUIDlen); + memcpy(m_Info.AssetUUID, SP->PackageUID.Value() + 16, UUIDlen); } // optional CryptographicContext @@ -84,7 +92,7 @@ ASDCP::h__Reader::InitInfo(WriterInfo& Info) Result_t cr_result = m_HeaderPart.GetMDObjectByType(OBJ_TYPE_ARGS(CryptographicContext), &Object); if( ASDCP_SUCCESS(cr_result) ) - MD_to_CryptoInfo((CryptographicContext*)Object, m_Info); + MD_to_CryptoInfo((CryptographicContext*)Object, m_Info, *m_Dict); } return result; @@ -95,38 +103,29 @@ ASDCP::h__Reader::InitInfo(WriterInfo& Info) Result_t ASDCP::h__Reader::OpenMXFRead(const char* filename) { + m_LastPosition = 0; Result_t result = m_File.OpenRead(filename); if ( ASDCP_SUCCESS(result) ) result = m_HeaderPart.InitFromFile(m_File); - // OP-Atom states that there will be either two or three partitions, - // one closed header and one closed footer with an optional body - ui32_t test_s = m_HeaderPart.m_RIP.PairArray.size(); - - if ( test_s < 2 || test_s > 3 ) + if ( ASDCP_SUCCESS(result) ) { - DefaultLogSink().Error("RIP count is not 2 or 3: %lu\n", test_s); - return RESULT_FORMAT; - } + // if this is a three partition file, go to the body + // partition and read the partition pack + if ( m_HeaderPart.m_RIP.PairArray.size() > 2 ) + { + Array::iterator r_i = m_HeaderPart.m_RIP.PairArray.begin(); + r_i++; + m_File.Seek((*r_i).ByteOffset); - // it really OP-Atom? - // MDObject* OpPattern = GetMDObjectByType("OperationalPattern"); - // TODO: check the label + result = m_BodyPart.InitFromFile(m_File); + } - // if this is a three partition file, go to the body - // partition and read off the partition pack - if ( test_s == 3 ) - { - DefaultLogSink().Error("RIP count is 3: must write code...\n"); - return RESULT_FORMAT; + m_EssenceStart = m_File.Tell(); } - // TODO: check the partition pack to make sure it is - // really a body with a single essence container - - m_EssenceStart = m_File.Tell(); - return RESULT_OK; + return result; } @@ -145,42 +144,79 @@ ASDCP::h__Reader::InitMXFIndex() result = m_FooterPart.InitFromFile(m_File); } + if ( ASDCP_SUCCESS(result) ) + m_File.Seek(m_EssenceStart); + return result; } +// +Result_t +ASDCP::KLReader::ReadKLFromFile(Kumu::FileReader& Reader) +{ + ui32_t read_count; + ui32_t header_length = SMPTE_UL_LENGTH + MXF_BER_LENGTH; + Result_t result = Reader.Read(m_KeyBuf, header_length, &read_count); + + if ( ASDCP_SUCCESS(result) ) + { + if ( read_count != header_length ) + result = RESULT_READFAIL; + + else + result = InitFromBuffer(m_KeyBuf, header_length); + } + + return result; +} // standard method of reading a plaintext or encrypted frame Result_t -ASDCP::h__Reader::ReadEKLVPacket(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf, - const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC) +ASDCP::h__Reader::ReadEKLVFrame(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf, + const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC) { // look up frame index node IndexTableSegment::IndexEntry TmpEntry; if ( ASDCP_FAILURE(m_FooterPart.Lookup(FrameNum, TmpEntry)) ) { - DefaultLogSink().Error("Frame value out of range: %lu\n", FrameNum); + DefaultLogSink().Error("Frame value out of range: %u\n", FrameNum); return RESULT_RANGE; } // get frame position and go read the frame's key and length - ASDCP::KLVReader Reader; - ASDCP::fpos_t FilePosition = m_EssenceStart + TmpEntry.StreamOffset; + Kumu::fpos_t FilePosition = m_EssenceStart + TmpEntry.StreamOffset; + Result_t result = RESULT_OK; - Result_t result = m_File.Seek(FilePosition); + if ( FilePosition != m_LastPosition ) + { + m_LastPosition = FilePosition; + result = m_File.Seek(FilePosition); + } - if ( ASDCP_SUCCESS(result) ) - result = Reader.ReadKLFromFile(m_File); + if( ASDCP_SUCCESS(result) ) + result = ReadEKLVPacket(FrameNum, FrameNum + 1, FrameBuf, EssenceUL, Ctx, HMAC); + + return result; +} + + +Result_t +ASDCP::h__Reader::ReadEKLVPacket(ui32_t FrameNum, ui32_t SequenceNum, ASDCP::FrameBuffer& FrameBuf, + const byte_t* EssenceUL, AESDecContext* Ctx, HMACContext* HMAC) +{ + KLReader Reader; + Result_t result = Reader.ReadKLFromFile(m_File); if ( ASDCP_FAILURE(result) ) return result; UL Key(Reader.Key()); - UL InteropRef(CryptEssenceUL_Data); - UL SMPTERef(CryptEssenceUL_Data); ui64_t PacketLength = Reader.Length(); + m_LastPosition = m_LastPosition + Reader.KLLength() + PacketLength; - if ( Key == InteropRef || Key == SMPTERef ) + if ( memcmp(Key.Value(), m_Dict->ul(MDD_CryptEssence), Key.Size() - 1) == 0 // ignore the stream numbers + || memcmp(Key.Value(), m_Dict->ul(MDD_MXFInterop_CryptEssence), Key.Size() - 1) == 0 ) { if ( ! m_Info.EncryptedEssence ) { @@ -189,9 +225,11 @@ ASDCP::h__Reader::ReadEKLVPacket(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf, } // read encrypted triplet value into internal buffer - m_CtFrameBuf.Capacity(PacketLength); + assert(PacketLength <= 0xFFFFFFFFL); + m_CtFrameBuf.Capacity((ui32_t) PacketLength); ui32_t read_count; - result = m_File.Read(m_CtFrameBuf.Data(), PacketLength, &read_count); + result = m_File.Read(m_CtFrameBuf.Data(), (ui32_t) PacketLength, + &read_count); if ( ASDCP_FAILURE(result) ) return result; @@ -202,13 +240,13 @@ ASDCP::h__Reader::ReadEKLVPacket(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf, return RESULT_FORMAT; } - m_CtFrameBuf.Size(PacketLength); + m_CtFrameBuf.Size((ui32_t) PacketLength); // should be const but mxflib::ReadBER is not byte_t* ess_p = m_CtFrameBuf.Data(); // read context ID length - if ( ! read_test_BER(&ess_p, UUIDlen) ) + if ( ! Kumu::read_test_BER(&ess_p, UUIDlen) ) return RESULT_FORMAT; // test the context ID @@ -220,39 +258,49 @@ ASDCP::h__Reader::ReadEKLVPacket(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf, ess_p += UUIDlen; // read PlaintextOffset length - if ( ! read_test_BER(&ess_p, sizeof(ui64_t)) ) + if ( ! Kumu::read_test_BER(&ess_p, sizeof(ui64_t)) ) return RESULT_FORMAT; - ui32_t PlaintextOffset = (ui32_t)ASDCP_i64_BE(cp2i(ess_p)); + ui32_t PlaintextOffset = (ui32_t)KM_i64_BE(Kumu::cp2i(ess_p)); ess_p += sizeof(ui64_t); // read essence UL length - if ( ! read_test_BER(&ess_p, klv_key_size) ) + if ( ! Kumu::read_test_BER(&ess_p, SMPTE_UL_LENGTH) ) return RESULT_FORMAT; - // TODO: test essence UL - ess_p += klv_key_size; + // test essence UL + if ( memcmp(ess_p, EssenceUL, SMPTE_UL_LENGTH - 1) != 0 ) // ignore the stream number + { + char strbuf[IntBufferLen]; + const MDDEntry* Entry = m_Dict->FindUL(Key.Value()); + if ( Entry == 0 ) + DefaultLogSink().Warn("Unexpected Essence UL found: %s.\n", Key.EncodeString(strbuf, IntBufferLen)); + else + DefaultLogSink().Warn("Unexpected Essence UL found: %s.\n", Entry->name); + return RESULT_FORMAT; + } + ess_p += SMPTE_UL_LENGTH; // read SourceLength length - if ( ! read_test_BER(&ess_p, sizeof(ui64_t)) ) + if ( ! Kumu::read_test_BER(&ess_p, sizeof(ui64_t)) ) return RESULT_FORMAT; - ui32_t SourceLength = (ui32_t)ASDCP_i64_BE(cp2i(ess_p)); + ui32_t SourceLength = (ui32_t)KM_i64_BE(Kumu::cp2i(ess_p)); ess_p += sizeof(ui64_t); assert(SourceLength); if ( FrameBuf.Capacity() < SourceLength ) { - DefaultLogSink().Error("FrameBuf.Capacity: %lu SourceLength: %lu\n", FrameBuf.Capacity(), SourceLength); + DefaultLogSink().Error("FrameBuf.Capacity: %u SourceLength: %u\n", FrameBuf.Capacity(), SourceLength); return RESULT_SMALLBUF; } ui32_t esv_length = calc_esv_length(SourceLength, PlaintextOffset); // read ESV length - if ( ! read_test_BER(&ess_p, esv_length) ) + if ( ! Kumu::read_test_BER(&ess_p, esv_length) ) { - DefaultLogSink().Error("read_test_BER did not return %lu\n", esv_length); + DefaultLogSink().Error("read_test_BER did not return %u\n", esv_length); return RESULT_FORMAT; } @@ -281,13 +329,18 @@ ASDCP::h__Reader::ReadEKLVPacket(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf, if ( ASDCP_SUCCESS(result) && m_Info.UsesHMAC && HMAC ) { IntegrityPack IntPack; - result = IntPack.TestValues(TmpWrapper, m_Info.AssetUUID, FrameNum + 1, HMAC); + result = IntPack.TestValues(TmpWrapper, m_Info.AssetUUID, SequenceNum, HMAC); } } else // return ciphertext to caller { if ( FrameBuf.Capacity() < tmp_len ) - return RESULT_SMALLBUF; + { + char intbuf[IntBufferLen]; + DefaultLogSink().Error("FrameBuf.Capacity: %u FrameLength: %s\n", + FrameBuf.Capacity(), ui64sz(PacketLength, intbuf)); + return RESULT_SMALLBUF; + } memcpy(FrameBuf.Data(), ess_p, tmp_len); FrameBuf.Size(tmp_len); @@ -295,19 +348,20 @@ ASDCP::h__Reader::ReadEKLVPacket(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf, FrameBuf.PlaintextOffset(PlaintextOffset); } } - else if ( Key == EssenceUL ) + else if ( memcmp(Key.Value(), EssenceUL, Key.Size() - 1) == 0 ) // ignore the stream number { // read plaintext frame if ( FrameBuf.Capacity() < PacketLength ) { char intbuf[IntBufferLen]; - DefaultLogSink().Error("FrameBuf.Capacity: %lu FrameLength: %s\n", + DefaultLogSink().Error("FrameBuf.Capacity: %u FrameLength: %s\n", FrameBuf.Capacity(), ui64sz(PacketLength, intbuf)); return RESULT_SMALLBUF; } // read the data into the supplied buffer ui32_t read_count; - result = m_File.Read(FrameBuf.Data(), PacketLength, &read_count); + assert(PacketLength <= 0xFFFFFFFFL); + result = m_File.Read(FrameBuf.Data(), (ui32_t) PacketLength, &read_count); if ( ASDCP_FAILURE(result) ) return result; @@ -328,7 +382,12 @@ ASDCP::h__Reader::ReadEKLVPacket(ui32_t FrameNum, ASDCP::FrameBuffer& FrameBuf, } else { - DefaultLogSink().Error("Unexpected UL found.\n"); + char strbuf[IntBufferLen]; + const MDDEntry* Entry = m_Dict->FindUL(Key.Value()); + if ( Entry == 0 ) + DefaultLogSink().Warn("Unexpected Essence UL found: %s.\n", Key.EncodeString(strbuf, IntBufferLen)); + else + DefaultLogSink().Warn("Unexpected Essence UL found: %s.\n", Entry->name); return RESULT_FORMAT; }