2 Copyright (c) 2005-2015, John Hurst
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 /*! \file MXFTypes.cpp
37 using Kumu::DefaultLogSink;
39 //------------------------------------------------------------------------------------------
44 ASDCP::UL::operator==(const UL& rhs) const
46 if ( m_Value[0] == rhs.m_Value[0] &&
47 m_Value[1] == rhs.m_Value[1] &&
48 m_Value[2] == rhs.m_Value[2] &&
49 m_Value[3] == rhs.m_Value[3] &&
50 m_Value[4] == rhs.m_Value[4] &&
51 m_Value[5] == rhs.m_Value[5] &&
52 m_Value[6] == rhs.m_Value[6] &&
53 // m_Value[7] == rhs.m_Value[7] && // version is ignored when performing lookups
54 m_Value[8] == rhs.m_Value[8] &&
55 m_Value[9] == rhs.m_Value[9] &&
56 m_Value[10] == rhs.m_Value[10] &&
57 m_Value[11] == rhs.m_Value[11] &&
58 m_Value[12] == rhs.m_Value[12] &&
59 m_Value[13] == rhs.m_Value[13] &&
60 m_Value[14] == rhs.m_Value[14] &&
61 m_Value[15] == rhs.m_Value[15]
70 ASDCP::UL::MatchIgnoreStream(const UL& rhs) const
72 if ( m_Value[0] == rhs.m_Value[0] &&
73 m_Value[1] == rhs.m_Value[1] &&
74 m_Value[2] == rhs.m_Value[2] &&
75 m_Value[3] == rhs.m_Value[3] &&
76 m_Value[4] == rhs.m_Value[4] &&
77 m_Value[5] == rhs.m_Value[5] &&
78 m_Value[6] == rhs.m_Value[6] &&
79 // m_Value[7] == rhs.m_Value[7] && // version is ignored when performing lookups
80 m_Value[8] == rhs.m_Value[8] &&
81 m_Value[9] == rhs.m_Value[9] &&
82 m_Value[10] == rhs.m_Value[10] &&
83 m_Value[11] == rhs.m_Value[11] &&
84 m_Value[12] == rhs.m_Value[12] &&
85 m_Value[13] == rhs.m_Value[13] &&
86 m_Value[14] == rhs.m_Value[14]
87 // m_Value[15] == rhs.m_Value[15] // ignore stream number
96 ASDCP::UL::ExactMatch(const UL& rhs) const
98 if ( m_Value[0] == rhs.m_Value[0] &&
99 m_Value[1] == rhs.m_Value[1] &&
100 m_Value[2] == rhs.m_Value[2] &&
101 m_Value[3] == rhs.m_Value[3] &&
102 m_Value[4] == rhs.m_Value[4] &&
103 m_Value[5] == rhs.m_Value[5] &&
104 m_Value[6] == rhs.m_Value[6] &&
105 m_Value[7] == rhs.m_Value[7] &&
106 m_Value[8] == rhs.m_Value[8] &&
107 m_Value[9] == rhs.m_Value[9] &&
108 m_Value[10] == rhs.m_Value[10] &&
109 m_Value[11] == rhs.m_Value[11] &&
110 m_Value[12] == rhs.m_Value[12] &&
111 m_Value[13] == rhs.m_Value[13] &&
112 m_Value[14] == rhs.m_Value[14] &&
113 m_Value[15] == rhs.m_Value[15]
121 ASDCP::UL::EncodeString(char* str_buf, ui32_t buf_len) const
123 if ( buf_len > 38 ) // room for dotted notation?
125 snprintf(str_buf, buf_len,
126 "%02x%02x%02x%02x.%02x%02x%02x%02x.%02x%02x%02x%02x.%02x%02x%02x%02x",
127 m_Value[0], m_Value[1], m_Value[2], m_Value[3],
128 m_Value[4], m_Value[5], m_Value[6], m_Value[7],
129 m_Value[8], m_Value[9], m_Value[10], m_Value[11],
130 m_Value[12], m_Value[13], m_Value[14], m_Value[15]
135 else if ( buf_len > 32 ) // room for compact?
137 snprintf(str_buf, buf_len,
138 "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
139 m_Value[0], m_Value[1], m_Value[2], m_Value[3],
140 m_Value[4], m_Value[5], m_Value[6], m_Value[7],
141 m_Value[8], m_Value[9], m_Value[10], m_Value[11],
142 m_Value[12], m_Value[13], m_Value[14], m_Value[15]
153 ASDCP::UMID::MakeUMID(int Type)
156 Kumu::GenRandomValue(AssetID);
157 MakeUMID(Type, AssetID);
162 ASDCP::UMID::MakeUMID(int Type, const UUID& AssetID)
164 // Set the non-varying base of the UMID
165 static const byte_t UMIDBase[10] = { 0x06, 0x0a, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };
166 memcpy(m_Value, UMIDBase, 10);
167 m_Value[10] = Type; // Material Type
168 m_Value[12] = 0x13; // length
170 // preserved for compatibility with mfxlib
171 if( Type > 4 ) m_Value[7] = 5;
172 m_Value[11] = 0x20; // UUID/UL method, number gen undefined
175 m_Value[13] = m_Value[14] = m_Value[15] = 0;
177 memcpy(&m_Value[16], AssetID.Value(), AssetID.Size());
182 // Write the UMID value to the given buffer in the form
183 // [00000000.0000.0000.00000000],00,00,00,00,00000000.0000.0000.00000000.00000000]
185 // [00000000.0000.0000.00000000],00,00,00,00,00000000-0000-0000-0000-000000000000]
186 // returns 0 if the buffer is smaller than DateTimeLen
188 ASDCP::UMID::EncodeString(char* str_buf, ui32_t buf_len) const
192 snprintf(str_buf, buf_len, "[%02x%02x%02x%02x.%02x%02x%02x%02x.%02x%02x%02x%02x],%02x,%02x,%02x,%02x,",
193 m_Value[0], m_Value[1], m_Value[2], m_Value[3],
194 m_Value[4], m_Value[5], m_Value[6], m_Value[7],
195 m_Value[8], m_Value[9], m_Value[10], m_Value[11],
196 m_Value[12], m_Value[13], m_Value[14], m_Value[15]
199 ui32_t offset = strlen(str_buf);
201 if ( ( m_Value[8] & 0x80 ) == 0 )
203 // half-swapped UL, use [bbaa9988.ddcc.ffee.00010203.04050607]
204 snprintf(str_buf + offset, buf_len - offset,
205 "[%02x%02x%02x%02x.%02x%02x%02x%02x.%02x%02x%02x%02x.%02x%02x%02x%02x]",
206 m_Value[24], m_Value[25], m_Value[26], m_Value[27],
207 m_Value[28], m_Value[29], m_Value[30], m_Value[31],
208 m_Value[16], m_Value[17], m_Value[18], m_Value[19],
209 m_Value[20], m_Value[21], m_Value[22], m_Value[23]
214 // UUID, use {00112233-4455-6677-8899-aabbccddeeff}
215 snprintf(str_buf + offset, buf_len - offset,
216 "{%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
217 m_Value[16], m_Value[17], m_Value[18], m_Value[19],
218 m_Value[20], m_Value[21], m_Value[22], m_Value[23],
219 m_Value[24], m_Value[25], m_Value[26], m_Value[27],
220 m_Value[28], m_Value[29], m_Value[30], m_Value[31]
227 //------------------------------------------------------------------------------------------
231 ASDCP::MXF::UTF16String::UTF16String(const char* sz)
233 if ( sz != 0 && *sz != 0 )
239 ASDCP::MXF::UTF16String::UTF16String(const std::string& str)
245 const ASDCP::MXF::UTF16String&
246 ASDCP::MXF::UTF16String::operator=(const char* sz)
248 if ( sz == 0 || *sz == 0 )
258 const ASDCP::MXF::UTF16String&
259 ASDCP::MXF::UTF16String::operator=(const std::string& str)
267 ASDCP::MXF::UTF16String::EncodeString(char* str_buf, ui32_t buf_len) const
269 ui32_t write_len = Kumu::xmin(buf_len - 1, (ui32_t)size());
270 strncpy(str_buf, c_str(), write_len);
271 str_buf[write_len] = 0;
277 ASDCP::MXF::UTF16String::Unarchive(Kumu::MemIOReader* Reader)
280 const ui16_t* p = (ui16_t*)Reader->CurrentData();
281 ui32_t length = Reader->Remainder() / 2;
282 char mb_buf[MB_LEN_MAX+1];
284 for ( ui32_t i = 0; i < length; i++ )
286 int count = wctomb(mb_buf, KM_i16_BE(p[i]));
290 DefaultLogSink().Error("Unable to decode wide character 0x%04hx\n", p[i]);
294 assert(count <= MB_LEN_MAX);
296 this->append(mb_buf);
299 Reader->SkipOffset(length*2);
305 ASDCP::MXF::UTF16String::Archive(Kumu::MemIOWriter* Writer) const
307 if ( size() > IdentBufferLen )
309 DefaultLogSink().Error("String length exceeds maximum %u bytes\n", IdentBufferLen);
313 const char* mbp = c_str();
315 ui32_t remainder = size();
316 ui32_t length = size();
321 int count = mbtowc(&wcp, mbp+i, remainder);
325 DefaultLogSink().Error("Error decoding multi-byte sequence starting at offset %u\n", i);
328 else if ( count == 0 )
333 bool result = Writer->WriteUi16BE((ui16_t)wcp);
335 if ( result == false )
337 DefaultLogSink().Error("No more space in memory IO writer\n");
348 //------------------------------------------------------------------------------------------
352 ASDCP::MXF::ISO8String::ISO8String(const char* sz)
354 if ( sz != 0 && *sz != 0 )
360 ASDCP::MXF::ISO8String::ISO8String(const std::string& str)
367 const ASDCP::MXF::ISO8String&
368 ASDCP::MXF::ISO8String::operator=(const char* sz)
370 if ( sz == 0 || *sz == 0 )
380 const ASDCP::MXF::ISO8String&
381 ASDCP::MXF::ISO8String::operator=(const std::string& str)
389 ASDCP::MXF::ISO8String::EncodeString(char* str_buf, ui32_t buf_len) const
391 ui32_t write_len = Kumu::xmin(buf_len - 1, (ui32_t)size());
392 strncpy(str_buf, c_str(), write_len);
393 str_buf[write_len] = 0;
399 ASDCP::MXF::ISO8String::Unarchive(Kumu::MemIOReader* Reader)
401 assign((char*)Reader->CurrentData(), Reader->Remainder());
407 ASDCP::MXF::ISO8String::Archive(Kumu::MemIOWriter* Writer) const
409 if ( size() > IdentBufferLen )
411 DefaultLogSink().Error("String length exceeds maximum %u bytes\n", IdentBufferLen);
415 return Writer->WriteRaw((const byte_t*)c_str(), size());
418 //------------------------------------------------------------------------------------------
421 ASDCP::MXF::TLVReader::TLVReader(const byte_t* p, ui32_t c, IPrimerLookup* PrimerLookup) :
422 MemIOReader(p, c), m_Lookup(PrimerLookup)
424 Result_t result = RESULT_OK;
426 while ( Remainder() > 0 && ASDCP_SUCCESS(result) )
431 if ( MemIOReader::ReadUi8(&Tag.a) )
432 if ( MemIOReader::ReadUi8(&Tag.b) )
433 if ( MemIOReader::ReadUi16BE(&pkt_len) )
435 m_ElementMap.insert(TagMap::value_type(Tag, ItemInfo(m_size, pkt_len)));
436 if ( SkipOffset(pkt_len) )
440 DefaultLogSink().Error("Malformed Set\n");
441 m_ElementMap.clear();
442 result = RESULT_KLV_CODING;
448 ASDCP::MXF::TLVReader::FindTL(const MDDEntry& Entry)
452 DefaultLogSink().Error("No Lookup service\n");
458 if ( m_Lookup->TagForKey(Entry.ul, TmpTag) != RESULT_OK )
460 if ( Entry.tag.a == 0 )
462 // DefaultLogSink().Debug("No such UL in this TL list: %s (%02x %02x)\n",
463 // Entry.name, Entry.tag.a, Entry.tag.b);
470 TagMap::iterator e_i = m_ElementMap.find(TmpTag);
472 if ( e_i != m_ElementMap.end() )
474 m_size = (*e_i).second.first;
475 m_capacity = m_size + (*e_i).second.second;
479 // DefaultLogSink().Debug("Not Found (%02x %02x): %s\n", TmpTag.a, TmpTag.b, Entry.name);
485 ASDCP::MXF::TLVReader::ReadObject(const MDDEntry& Entry, Kumu::IArchive* Object)
487 ASDCP_TEST_NULL(Object);
491 if ( m_size < m_capacity ) // don't try to unarchive an empty item
492 return Object->Unarchive(this) ? RESULT_OK : RESULT_KLV_CODING;
500 ASDCP::MXF::TLVReader::ReadUi8(const MDDEntry& Entry, ui8_t* value)
502 ASDCP_TEST_NULL(value);
505 return MemIOReader::ReadUi8(value) ? RESULT_OK : RESULT_KLV_CODING;
512 ASDCP::MXF::TLVReader::ReadUi16(const MDDEntry& Entry, ui16_t* value)
514 ASDCP_TEST_NULL(value);
517 return MemIOReader::ReadUi16BE(value) ? RESULT_OK : RESULT_KLV_CODING;
524 ASDCP::MXF::TLVReader::ReadUi32(const MDDEntry& Entry, ui32_t* value)
526 ASDCP_TEST_NULL(value);
529 return MemIOReader::ReadUi32BE(value) ? RESULT_OK : RESULT_KLV_CODING;
536 ASDCP::MXF::TLVReader::ReadUi64(const MDDEntry& Entry, ui64_t* value)
538 ASDCP_TEST_NULL(value);
541 return MemIOReader::ReadUi64BE(value) ? RESULT_OK : RESULT_KLV_CODING;
546 //------------------------------------------------------------------------------------------
549 ASDCP::MXF::TLVWriter::TLVWriter(byte_t* p, ui32_t c, IPrimerLookup* PrimerLookup) :
550 MemIOWriter(p, c), m_Lookup(PrimerLookup)
557 ASDCP::MXF::TLVWriter::WriteTag(const MDDEntry& Entry)
561 DefaultLogSink().Error("No Primer object available\n");
567 if ( m_Lookup->InsertTag(Entry, TmpTag) != RESULT_OK )
569 DefaultLogSink().Error("No tag for entry %s\n", Entry.name);
573 if ( ! MemIOWriter::WriteUi8(TmpTag.a) ) return RESULT_KLV_CODING;
574 if ( ! MemIOWriter::WriteUi8(TmpTag.b) ) return RESULT_KLV_CODING;
580 ASDCP::MXF::TLVWriter::WriteObject(const MDDEntry& Entry, Kumu::IArchive* Object)
582 ASDCP_TEST_NULL(Object);
584 if ( Entry.optional && ! Object->HasValue() )
587 Result_t result = WriteTag(Entry);
589 if ( ASDCP_SUCCESS(result) )
591 // write a temp length
592 byte_t* l_p = CurrentData();
594 if ( ! MemIOWriter::WriteUi16BE(0) ) return RESULT_KLV_CODING;
596 ui32_t before = Length();
597 if ( ! Object->Archive(this) ) return RESULT_KLV_CODING;
598 if ( (Length() - before) > 0xffffL ) return RESULT_KLV_CODING;
599 Kumu::i2p<ui16_t>(KM_i16_BE(Length() - before), l_p);
607 ASDCP::MXF::TLVWriter::WriteUi8(const MDDEntry& Entry, ui8_t* value)
609 ASDCP_TEST_NULL(value);
610 Result_t result = WriteTag(Entry);
612 if ( ASDCP_SUCCESS(result) )
614 if ( ! MemIOWriter::WriteUi16BE(sizeof(ui8_t)) ) return RESULT_KLV_CODING;
615 if ( ! MemIOWriter::WriteUi8(*value) ) return RESULT_KLV_CODING;
623 ASDCP::MXF::TLVWriter::WriteUi16(const MDDEntry& Entry, ui16_t* value)
625 ASDCP_TEST_NULL(value);
626 Result_t result = WriteTag(Entry);
628 if ( KM_SUCCESS(result) )
630 if ( ! MemIOWriter::WriteUi16BE(sizeof(ui16_t)) ) return RESULT_KLV_CODING;
631 if ( ! MemIOWriter::WriteUi16BE(*value) ) return RESULT_KLV_CODING;
639 ASDCP::MXF::TLVWriter::WriteUi32(const MDDEntry& Entry, ui32_t* value)
641 ASDCP_TEST_NULL(value);
642 Result_t result = WriteTag(Entry);
644 if ( KM_SUCCESS(result) )
646 if ( ! MemIOWriter::WriteUi16BE(sizeof(ui32_t)) ) return RESULT_KLV_CODING;
647 if ( ! MemIOWriter::WriteUi32BE(*value) ) return RESULT_KLV_CODING;
655 ASDCP::MXF::TLVWriter::WriteUi64(const MDDEntry& Entry, ui64_t* value)
657 ASDCP_TEST_NULL(value);
658 Result_t result = WriteTag(Entry);
660 if ( KM_SUCCESS(result) )
662 if ( ! MemIOWriter::WriteUi16BE(sizeof(ui64_t)) ) return RESULT_KLV_CODING;
663 if ( ! MemIOWriter::WriteUi64BE(*value) ) return RESULT_KLV_CODING;
670 //----------------------------------------------------------------------------------------------------
674 ASDCP::MXF::RGBALayout::RGBALayout()
676 memset(m_value, 0, RGBAValueLength);
679 ASDCP::MXF::RGBALayout::RGBALayout(const byte_t* value)
681 memcpy(m_value, value, RGBAValueLength);
684 ASDCP::MXF::RGBALayout::~RGBALayout()
689 get_char_for_code(byte_t c)
691 for ( int i = 0; ASDCP::MXF::RGBALayoutTable[i].code != 0; ++i )
693 if ( ASDCP::MXF::RGBALayoutTable[i].code == c )
695 return ASDCP::MXF::RGBALayoutTable[i].symbol;
704 ASDCP::MXF::RGBALayout::EncodeString(char* buf, ui32_t buf_len) const
709 for ( int i = 0; i < RGBAValueLength && m_value[i] != 0; i += 2 )
711 snprintf(tmp_buf, 64, "%c(%d)", get_char_for_code(m_value[i]), m_value[i+1]);
713 if ( ! tmp_str.empty() )
721 assert(tmp_str.size() < buf_len);
722 strncpy(buf, tmp_str.c_str(), tmp_str.size());
727 //----------------------------------------------------------------------------------------------------
730 ASDCP::MXF::Raw::Raw()
735 ASDCP::MXF::Raw::~Raw()
741 ASDCP::MXF::Raw::Unarchive(Kumu::MemIOReader* Reader)
743 ui32_t payload_size = Reader->Remainder();
744 if ( payload_size == 0 ) return false;
745 if ( KM_FAILURE(Capacity(payload_size)) ) return false;
747 memcpy(Data(), Reader->CurrentData(), payload_size);
748 Length(payload_size);
754 ASDCP::MXF::Raw::Archive(Kumu::MemIOWriter* Writer) const
756 return Writer->WriteRaw(RoData(), Length());
761 ASDCP::MXF::Raw::EncodeString(char* str_buf, ui32_t buf_len) const
764 Kumu::bin2hex(RoData(), Length(), str_buf, buf_len);