/*
-Copyright (c) 2005-2007, John Hurst
+Copyright (c) 2005-2008, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
*/
#include "MXF.h"
+#include "Metadata.h"
#include <KM_log.h>
+
using Kumu::DefaultLogSink;
+using Kumu::GenRandomValue;
// index segments must be < 64K
// NOTE: this value may too high if advanced index entry elements are used.
return result;
}
+//
+ASDCP::Result_t
+ASDCP::MXF::RIP::GetPairBySID(ui32_t SID, Pair& outPair) const
+{
+ Array<Pair>::const_iterator pi = PairArray.begin();
+ for ( ; pi != PairArray.end(); pi++ )
+ {
+ if ( (*pi).BodySID == SID )
+ {
+ outPair = *pi;
+ return RESULT_OK;
+ }
+ }
+
+ return RESULT_FAIL;
+}
+
//
ASDCP::Result_t
ASDCP::MXF::RIP::InitFromFile(const Kumu::FileReader& Reader)
KLVFilePacket::Dump(stream, false);
PairArray.Dump(stream, false);
-
- fputs("==========================================================================\n", stream);
}
//------------------------------------------------------------------------------------------
m_List.push_back(ThePacket);
}
+ //
+ Result_t GetMDObjectByID(const UUID& ObjectID, InterchangeObject** Object)
+ {
+ ASDCP_TEST_NULL(Object);
+
+ std::map<UUID, InterchangeObject*>::iterator mi = m_Map.find(ObjectID);
+
+ if ( mi == m_Map.end() )
+ {
+ *Object = 0;
+ return RESULT_FAIL;
+ }
+
+ *Object = (*mi).second;
+ return RESULT_OK;
+ }
+
//
Result_t GetMDObjectByType(const byte_t* ObjectID, InterchangeObject** Object)
{
return RESULT_FAIL;
}
+
+ //
+ Result_t GetMDObjectsByType(const byte_t* ObjectID, std::list<InterchangeObject*>& ObjectList)
+ {
+ ASDCP_TEST_NULL(ObjectID);
+ std::list<InterchangeObject*>::iterator li;
+
+ for ( li = m_List.begin(); li != m_List.end(); li++ )
+ {
+ if ( (*li)->HasUL(ObjectID) )
+ ObjectList.push_back(*li);
+ }
+
+ return ObjectList.empty() ? RESULT_FAIL : RESULT_OK;
+ }
};
//------------------------------------------------------------------------------------------
Result_t result = KLVFilePacket::InitFromFile(Reader);
// test the UL
// could be one of several values
-
if ( ASDCP_SUCCESS(result) )
- {
- Kumu::MemIOReader MemRDR(m_ValueStart, m_ValueLength);
- result = RESULT_KLV_CODING;
+ result = ASDCP::MXF::Partition::InitFromBuffer(m_ValueStart, m_ValueLength);
+
+ return result;
+}
- if ( MemRDR.ReadUi16BE(&MajorVersion) )
- if ( MemRDR.ReadUi16BE(&MinorVersion) )
- if ( MemRDR.ReadUi32BE(&KAGSize) )
- if ( MemRDR.ReadUi64BE(&ThisPartition) )
- if ( MemRDR.ReadUi64BE(&PreviousPartition) )
- if ( MemRDR.ReadUi64BE(&FooterPartition) )
- if ( MemRDR.ReadUi64BE(&HeaderByteCount) )
- if ( MemRDR.ReadUi64BE(&IndexByteCount) )
- if ( MemRDR.ReadUi32BE(&IndexSID) )
- if ( MemRDR.ReadUi64BE(&BodyOffset) )
- if ( MemRDR.ReadUi32BE(&BodySID) )
- if ( OperationalPattern.Unarchive(&MemRDR) )
- if ( EssenceContainers.Unarchive(&MemRDR) )
- result = RESULT_OK;
- }
+//
+ASDCP::Result_t
+ASDCP::MXF::Partition::InitFromBuffer(const byte_t* p, ui32_t l)
+{
+ Kumu::MemIOReader MemRDR(p, l);
+ Result_t result = RESULT_KLV_CODING;
+
+ if ( MemRDR.ReadUi16BE(&MajorVersion) )
+ if ( MemRDR.ReadUi16BE(&MinorVersion) )
+ if ( MemRDR.ReadUi32BE(&KAGSize) )
+ if ( MemRDR.ReadUi64BE(&ThisPartition) )
+ if ( MemRDR.ReadUi64BE(&PreviousPartition) )
+ if ( MemRDR.ReadUi64BE(&FooterPartition) )
+ if ( MemRDR.ReadUi64BE(&HeaderByteCount) )
+ if ( MemRDR.ReadUi64BE(&IndexByteCount) )
+ if ( MemRDR.ReadUi32BE(&IndexSID) )
+ if ( MemRDR.ReadUi64BE(&BodyOffset) )
+ if ( MemRDR.ReadUi32BE(&BodySID) )
+ if ( OperationalPattern.Unarchive(&MemRDR) )
+ if ( EssenceContainers.Unarchive(&MemRDR) )
+ result = RESULT_OK;
if ( ASDCP_FAILURE(result) )
DefaultLogSink().Error("Failed to initialize Partition\n");
fprintf(stream, " BodySID = %u\n", BodySID);
fprintf(stream, " OperationalPattern = %s\n", OperationalPattern.EncodeString(identbuf, IdentBufferLen));
fputs("Essence Containers:\n", stream); EssenceContainers.Dump(stream, false);
-
- fputs("==========================================================================\n", stream);
}
KLVPacket::Dump(stream, false);
fprintf(stream, "Primer: %u %s\n",
- LocalTagEntryBatch.size(),
+ (ui32_t)LocalTagEntryBatch.size(),
( LocalTagEntryBatch.size() == 1 ? "entry" : "entries" ));
Batch<LocalTagEntry>::iterator i = LocalTagEntryBatch.begin();
const MDDEntry* Entry = Dict::FindUL((*i).UL.Value());
fprintf(stream, " %s %s\n", (*i).EncodeString(identbuf, IdentBufferLen), (Entry ? Entry->name : "Unknown"));
}
-
- fputs("==========================================================================\n", stream);
}
DefaultLogSink().Error("RIP contains no Pairs.\n");
result = RESULT_FORMAT;
}
- else if ( test_s < 2 || test_s > 3 )
- {
- // OP-Atom states that there will be either two or three partitions,
- // one closed header and one closed footer with an optional body
- DefaultLogSink().Error("RIP count is not 2 or 3: %u\n", test_s);
- return RESULT_FORMAT;
- }
else
{
+ if ( test_s < 2 )
+ {
+ // OP-Atom states that there will be either two or three partitions:
+ // one closed header and one closed footer with an optional body
+ // SMPTE 429-5 files may have many partitions, see SMPTE 410M
+ DefaultLogSink().Warn("RIP count is less than 2: %u\n", test_s);
+ }
+
m_HasRIP = true;
if ( m_RIP.PairArray.front().ByteOffset != 0 )
if ( HeaderByteCount < 1024 )
DefaultLogSink().Warn("Improbably small HeaderByteCount value: %u\n", HeaderByteCount);
- result = m_Buffer.Capacity(HeaderByteCount);
+ assert (HeaderByteCount <= 0xFFFFFFFFL);
+ result = m_Buffer.Capacity((ui32_t) HeaderByteCount);
if ( ASDCP_SUCCESS(result) )
{
}
}
- const byte_t* p = m_Buffer.RoData();
- const byte_t* end_p = p + m_Buffer.Capacity();
+ result = InitFromBuffer(m_Buffer.RoData(), m_Buffer.Capacity());
+}
+
+//
+ASDCP::Result_t
+ASDCP::MXF::OPAtomHeader::InitFromPartitionBuffer(const byte_t* p, ui32_t l)
+{
+ Result_t result = KLVPacket::InitFromBuffer(p, l);
+
+ if ( ASDCP_SUCCESS(result) )
+ result = Partition::InitFromBuffer(m_ValueStart, m_ValueLength); // test UL and OP
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ ui32_t pp_len = KLVPacket::PacketLength();
+ result = InitFromBuffer(p + pp_len, l - pp_len);
+ }
+
+ return result;
+}
+
+//
+ASDCP::Result_t
+ASDCP::MXF::OPAtomHeader::InitFromBuffer(const byte_t* p, ui32_t l)
+{
+ Result_t result = RESULT_OK;
+ const byte_t* end_p = p + l;
while ( ASDCP_SUCCESS(result) && p < end_p )
{
delete object;
result = m_Primer.InitFromBuffer(redo_p, end_p - redo_p);
}
- else if ( object->IsA(Dict::ul(MDD_Preface)) )
- {
- assert(m_Preface == 0);
- m_Preface = (Preface*)object;
- }
- else
+ else
{
m_PacketList->AddPacket(object);
+
+ if ( object->IsA(Dict::ul(MDD_Preface)) && m_Preface == 0 )
+ m_Preface = (Preface*)object;
}
}
else
return result;
}
+ASDCP::Result_t
+ASDCP::MXF::OPAtomHeader::GetMDObjectByID(const UUID& ObjectID, InterchangeObject** Object)
+{
+ return m_PacketList->GetMDObjectByID(ObjectID, Object);
+}
+
//
ASDCP::Result_t
ASDCP::MXF::OPAtomHeader::GetMDObjectByType(const byte_t* ObjectID, InterchangeObject** Object)
return m_PacketList->GetMDObjectByType(ObjectID, Object);
}
+//
+ASDCP::Result_t
+ASDCP::MXF::OPAtomHeader::GetMDObjectsByType(const byte_t* ObjectID, std::list<InterchangeObject*>& ObjectList)
+{
+ return m_PacketList->GetMDObjectsByType(ObjectID, ObjectList);
+}
+
//
ASDCP::MXF::Identification*
ASDCP::MXF::OPAtomHeader::GetIdentification()
ASDCP::FrameBuffer HeaderBuffer;
HeaderByteCount = HeaderSize - ArchiveSize();
- Result_t result = HeaderBuffer.Capacity(HeaderByteCount);
+ assert (HeaderByteCount <= 0xFFFFFFFFL);
+ Result_t result = HeaderBuffer.Capacity((ui32_t) HeaderByteCount);
m_Preface->m_Lookup = &m_Primer;
std::list<InterchangeObject*>::iterator pl_i = m_PacketList->m_List.begin();
if ( stream == 0 )
stream = stderr;
- if ( m_HasRIP )
- m_RIP.Dump(stream);
-
Partition::Dump(stream);
m_Primer.Dump(stream);
if ( m_Preface == 0 )
fputs("No Preface loaded\n", stream);
- else
- m_Preface->Dump(stream);
std::list<InterchangeObject*>::iterator i = m_PacketList->m_List.begin();
for ( ; i != m_PacketList->m_List.end(); i++ )
ASDCP::MXF::OPAtomIndexFooter::~OPAtomIndexFooter() {}
-
+//
ASDCP::Result_t
ASDCP::MXF::OPAtomIndexFooter::InitFromFile(const Kumu::FileReader& Reader)
{
ui32_t read_count;
if ( ASDCP_SUCCESS(result) )
- result = m_Buffer.Capacity(IndexByteCount);
+ {
+ assert (IndexByteCount <= 0xFFFFFFFFL);
+ result = m_Buffer.Capacity((ui32_t) IndexByteCount);
+ }
if ( ASDCP_SUCCESS(result) )
result = Reader.Read(m_Buffer.Data(), m_Buffer.Capacity(), &read_count);
return RESULT_FAIL;
}
- const byte_t* p = m_Buffer.RoData();
- const byte_t* end_p = p + m_Buffer.Capacity();
+ if ( ASDCP_SUCCESS(result) )
+ result = InitFromBuffer(m_Buffer.RoData(), m_Buffer.Capacity());
+
+ return result;
+}
+
+//
+ASDCP::Result_t
+ASDCP::MXF::OPAtomIndexFooter::InitFromPartitionBuffer(const byte_t* p, ui32_t l)
+{
+ Result_t result = KLVPacket::InitFromBuffer(p, l);
+
+ if ( ASDCP_SUCCESS(result) )
+ result = Partition::InitFromBuffer(m_ValueStart, m_ValueLength); // test UL and OP
+
+ if ( ASDCP_SUCCESS(result) )
+ {
+ ui32_t pp_len = KLVPacket::PacketLength();
+ result = InitFromBuffer(p + pp_len, l - pp_len);
+ }
+
+ return result;
+}
+
+//
+ASDCP::Result_t
+ASDCP::MXF::OPAtomIndexFooter::InitFromBuffer(const byte_t* p, ui32_t l)
+{
+ Result_t result = RESULT_OK;
+ const byte_t* end_p = p + l;
while ( ASDCP_SUCCESS(result) && p < end_p )
{
if ( ASDCP_SUCCESS(result) )
{
- ui32_t write_count;
- Writer.Write(FooterBuffer.RoData(), FooterBuffer.Size(), &write_count);
+ ui32_t write_count = 0;
+ result = Writer.Write(FooterBuffer.RoData(), FooterBuffer.Size(), &write_count);
assert(write_count == FooterBuffer.Size());
}
//
ASDCP::Result_t
-ASDCP::MXF::OPAtomIndexFooter::Lookup(ui32_t frame_num, IndexTableSegment::IndexEntry& Entry)
+ASDCP::MXF::OPAtomIndexFooter::Lookup(ui32_t frame_num, IndexTableSegment::IndexEntry& Entry) const
{
std::list<InterchangeObject*>::iterator li;
for ( li = m_PacketList->m_List.begin(); li != m_PacketList->m_List.end(); li++ )
else if ( (ui64_t)frame_num >= start_pos
&& (ui64_t)frame_num < (start_pos + Segment->IndexDuration) )
{
- Entry = Segment->IndexEntryArray[frame_num-start_pos];
+ ui64_t tmp = frame_num - start_pos;
+ assert(tmp <= 0xFFFFFFFFL);
+ Entry = Segment->IndexEntryArray[(ui32_t) tmp];
return RESULT_OK;
}
}
}
+//------------------------------------------------------------------------------------------
+
+
+typedef std::map<ASDCP::UL, ASDCP::MXF::MXFObjectFactory_t>FactoryMap_t;
+typedef FactoryMap_t::iterator FLi_t;
+
+//
+class FactoryList : public FactoryMap_t
+{
+ Kumu::Mutex m_Lock;
+
+public:
+ FactoryList() {}
+ ~FactoryList() {}
+
+ bool Empty() {
+ Kumu::AutoMutex BlockLock(m_Lock);
+ return empty();
+ }
+
+ FLi_t Find(const byte_t* label) {
+ Kumu::AutoMutex BlockLock(m_Lock);
+ return find(label);
+ }
+
+ FLi_t End() {
+ Kumu::AutoMutex BlockLock(m_Lock);
+ return end();
+ }
+
+ void Insert(ASDCP::UL label, ASDCP::MXF::MXFObjectFactory_t factory) {
+ Kumu::AutoMutex BlockLock(m_Lock);
+ insert(FactoryList::value_type(label, factory));
+ }
+};
+
+//
+static FactoryList s_FactoryList;
+static Kumu::Mutex s_InitLock;
+static bool s_TypesInit = false;
+
+
+//
+void
+ASDCP::MXF::SetObjectFactory(ASDCP::UL label, ASDCP::MXF::MXFObjectFactory_t factory)
+{
+ s_FactoryList.Insert(label, factory);
+}
+
+
+//
+ASDCP::MXF::InterchangeObject*
+ASDCP::MXF::CreateObject(const byte_t* label)
+{
+ if ( label == 0 )
+ return 0;
+
+ if ( ! s_TypesInit )
+ {
+ Kumu::AutoMutex BlockLock(s_InitLock);
+
+ if ( ! s_TypesInit )
+ {
+ MXF::Metadata_InitTypes();
+ s_TypesInit = true;
+ }
+ }
+
+ FLi_t i = s_FactoryList.find(label);
+
+ if ( i == s_FactoryList.end() )
+ return new InterchangeObject;
+
+ return i->second();
+}
+
+
+
//
// end MXF.cpp
//