2 Copyright (c) 2005-2012, 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 )
331 bool result = Writer->WriteUi16BE((ui16_t)wcp);
333 if ( result == false )
335 DefaultLogSink().Error("No more space in memory IO writer\n");
346 //------------------------------------------------------------------------------------------
350 ASDCP::MXF::ISO8String::ISO8String(const char* sz)
352 if ( sz != 0 && *sz != 0 )
358 ASDCP::MXF::ISO8String::ISO8String(const std::string& str)
365 const ASDCP::MXF::ISO8String&
366 ASDCP::MXF::ISO8String::operator=(const char* sz)
368 if ( sz == 0 || *sz == 0 )
378 const ASDCP::MXF::ISO8String&
379 ASDCP::MXF::ISO8String::operator=(const std::string& str)
387 ASDCP::MXF::ISO8String::EncodeString(char* str_buf, ui32_t buf_len) const
389 ui32_t write_len = Kumu::xmin(buf_len - 1, (ui32_t)size());
390 strncpy(str_buf, c_str(), write_len);
391 str_buf[write_len] = 0;
397 ASDCP::MXF::ISO8String::Unarchive(Kumu::MemIOReader* Reader)
399 assign((char*)Reader->CurrentData(), Reader->Remainder());
405 ASDCP::MXF::ISO8String::Archive(Kumu::MemIOWriter* Writer) const
407 if ( size() > IdentBufferLen )
409 DefaultLogSink().Error("String length exceeds maximum %u bytes\n", IdentBufferLen);
413 return Writer->WriteRaw((const byte_t*)c_str(), size());
416 //------------------------------------------------------------------------------------------
419 ASDCP::MXF::TLVReader::TLVReader(const byte_t* p, ui32_t c, IPrimerLookup* PrimerLookup) :
420 MemIOReader(p, c), m_Lookup(PrimerLookup)
422 Result_t result = RESULT_OK;
424 while ( Remainder() > 0 && ASDCP_SUCCESS(result) )
429 if ( MemIOReader::ReadUi8(&Tag.a) )
430 if ( MemIOReader::ReadUi8(&Tag.b) )
431 if ( MemIOReader::ReadUi16BE(&pkt_len) )
433 m_ElementMap.insert(TagMap::value_type(Tag, ItemInfo(m_size, pkt_len)));
434 if ( SkipOffset(pkt_len) )
438 DefaultLogSink().Error("Malformed Set\n");
439 m_ElementMap.clear();
440 result = RESULT_KLV_CODING;
446 ASDCP::MXF::TLVReader::FindTL(const MDDEntry& Entry)
450 DefaultLogSink().Error("No Lookup service\n");
456 if ( m_Lookup->TagForKey(Entry.ul, TmpTag) != RESULT_OK )
458 if ( Entry.tag.a == 0 )
460 // DefaultLogSink().Debug("No such UL in this TL list: %s (%02x %02x)\n",
461 // Entry.name, Entry.tag.a, Entry.tag.b);
468 TagMap::iterator e_i = m_ElementMap.find(TmpTag);
470 if ( e_i != m_ElementMap.end() )
472 m_size = (*e_i).second.first;
473 m_capacity = m_size + (*e_i).second.second;
477 // DefaultLogSink().Debug("Not Found (%02x %02x): %s\n", TmpTag.a, TmpTag.b, Entry.name);
483 ASDCP::MXF::TLVReader::ReadObject(const MDDEntry& Entry, Kumu::IArchive* Object)
485 ASDCP_TEST_NULL(Object);
489 if ( m_size < m_capacity ) // don't try to unarchive an empty item
490 return Object->Unarchive(this) ? RESULT_OK : RESULT_KLV_CODING;
498 ASDCP::MXF::TLVReader::ReadUi8(const MDDEntry& Entry, ui8_t* value)
500 ASDCP_TEST_NULL(value);
503 return MemIOReader::ReadUi8(value) ? RESULT_OK : RESULT_KLV_CODING;
510 ASDCP::MXF::TLVReader::ReadUi16(const MDDEntry& Entry, ui16_t* value)
512 ASDCP_TEST_NULL(value);
515 return MemIOReader::ReadUi16BE(value) ? RESULT_OK : RESULT_KLV_CODING;
522 ASDCP::MXF::TLVReader::ReadUi32(const MDDEntry& Entry, ui32_t* value)
524 ASDCP_TEST_NULL(value);
527 return MemIOReader::ReadUi32BE(value) ? RESULT_OK : RESULT_KLV_CODING;
534 ASDCP::MXF::TLVReader::ReadUi64(const MDDEntry& Entry, ui64_t* value)
536 ASDCP_TEST_NULL(value);
539 return MemIOReader::ReadUi64BE(value) ? RESULT_OK : RESULT_KLV_CODING;
544 //------------------------------------------------------------------------------------------
547 ASDCP::MXF::TLVWriter::TLVWriter(byte_t* p, ui32_t c, IPrimerLookup* PrimerLookup) :
548 MemIOWriter(p, c), m_Lookup(PrimerLookup)
555 ASDCP::MXF::TLVWriter::WriteTag(const MDDEntry& Entry)
559 DefaultLogSink().Error("No Primer object available\n");
565 if ( m_Lookup->InsertTag(Entry, TmpTag) != RESULT_OK )
567 DefaultLogSink().Error("No tag for entry %s\n", Entry.name);
571 if ( ! MemIOWriter::WriteUi8(TmpTag.a) ) return RESULT_KLV_CODING;
572 if ( ! MemIOWriter::WriteUi8(TmpTag.b) ) return RESULT_KLV_CODING;
578 ASDCP::MXF::TLVWriter::WriteObject(const MDDEntry& Entry, Kumu::IArchive* Object)
580 ASDCP_TEST_NULL(Object);
582 if ( Entry.optional && ! Object->HasValue() )
585 Result_t result = WriteTag(Entry);
587 if ( ASDCP_SUCCESS(result) )
589 // write a temp length
590 byte_t* l_p = CurrentData();
592 if ( ! MemIOWriter::WriteUi16BE(0) ) return RESULT_KLV_CODING;
594 ui32_t before = Length();
595 if ( ! Object->Archive(this) ) return RESULT_KLV_CODING;
596 if ( (Length() - before) > 0xffffL ) return RESULT_KLV_CODING;
597 Kumu::i2p<ui16_t>(KM_i16_BE(Length() - before), l_p);
605 ASDCP::MXF::TLVWriter::WriteUi8(const MDDEntry& Entry, ui8_t* value)
607 ASDCP_TEST_NULL(value);
608 Result_t result = WriteTag(Entry);
610 if ( ASDCP_SUCCESS(result) )
612 if ( ! MemIOWriter::WriteUi16BE(sizeof(ui8_t)) ) return RESULT_KLV_CODING;
613 if ( ! MemIOWriter::WriteUi8(*value) ) return RESULT_KLV_CODING;
621 ASDCP::MXF::TLVWriter::WriteUi16(const MDDEntry& Entry, ui16_t* value)
623 ASDCP_TEST_NULL(value);
624 Result_t result = WriteTag(Entry);
626 if ( KM_SUCCESS(result) )
628 if ( ! MemIOWriter::WriteUi16BE(sizeof(ui16_t)) ) return RESULT_KLV_CODING;
629 if ( ! MemIOWriter::WriteUi16BE(*value) ) return RESULT_KLV_CODING;
637 ASDCP::MXF::TLVWriter::WriteUi32(const MDDEntry& Entry, ui32_t* value)
639 ASDCP_TEST_NULL(value);
640 Result_t result = WriteTag(Entry);
642 if ( KM_SUCCESS(result) )
644 if ( ! MemIOWriter::WriteUi16BE(sizeof(ui32_t)) ) return RESULT_KLV_CODING;
645 if ( ! MemIOWriter::WriteUi32BE(*value) ) return RESULT_KLV_CODING;
653 ASDCP::MXF::TLVWriter::WriteUi64(const MDDEntry& Entry, ui64_t* value)
655 ASDCP_TEST_NULL(value);
656 Result_t result = WriteTag(Entry);
658 if ( KM_SUCCESS(result) )
660 if ( ! MemIOWriter::WriteUi16BE(sizeof(ui64_t)) ) return RESULT_KLV_CODING;
661 if ( ! MemIOWriter::WriteUi64BE(*value) ) return RESULT_KLV_CODING;
668 //----------------------------------------------------------------------------------------------------
671 ASDCP::MXF::Raw::Raw()
676 ASDCP::MXF::Raw::~Raw()
682 ASDCP::MXF::Raw::Unarchive(Kumu::MemIOReader* Reader)
684 ui32_t payload_size = Reader->Remainder();
685 if ( payload_size == 0 ) return false;
686 if ( KM_FAILURE(Capacity(payload_size)) ) return false;
688 memcpy(Data(), Reader->CurrentData(), payload_size);
689 Length(payload_size);
695 ASDCP::MXF::Raw::Archive(Kumu::MemIOWriter* Writer) const
697 return Writer->WriteRaw(RoData(), Length());
702 ASDCP::MXF::Raw::EncodeString(char* str_buf, ui32_t buf_len) const
705 Kumu::bin2hex(RoData(), Length(), str_buf, buf_len);