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
28 \version $Id: MXFTypes.cpp,v 1.27 2012/02/21 02:09:31 jhurst Exp $
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 const ASDCP::MXF::UTF16String&
232 ASDCP::MXF::UTF16String::operator=(const char* sz)
234 if ( sz == 0 || *sz == 0 )
244 const ASDCP::MXF::UTF16String&
245 ASDCP::MXF::UTF16String::operator=(const std::string& str)
253 ASDCP::MXF::UTF16String::EncodeString(char* str_buf, ui32_t buf_len) const
255 ui32_t write_len = Kumu::xmin(buf_len - 1, (ui32_t)size());
256 strncpy(str_buf, c_str(), write_len);
257 str_buf[write_len] = 0;
263 ASDCP::MXF::UTF16String::Unarchive(Kumu::MemIOReader* Reader)
266 const ui16_t* p = (ui16_t*)Reader->CurrentData();
267 ui32_t length = Reader->Remainder() / 2;
268 char mb_buf[MB_LEN_MAX+1];
270 for ( ui32_t i = 0; i < length; i++ )
272 int count = wctomb(mb_buf, KM_i16_BE(p[i]));
276 DefaultLogSink().Error("Unable to decode wide character 0x%04hx\n", p[i]);
280 assert(count <= MB_LEN_MAX);
282 this->append(mb_buf);
285 Reader->SkipOffset(length*2);
291 ASDCP::MXF::UTF16String::Archive(Kumu::MemIOWriter* Writer) const
293 if ( size() > IdentBufferLen )
295 DefaultLogSink().Error("String length exceeds maximum %u bytes\n", IdentBufferLen);
299 const char* mbp = c_str();
301 ui32_t remainder = size();
302 ui32_t length = size();
307 int count = mbtowc(&wcp, mbp+i, remainder);
311 DefaultLogSink().Error("Error decoding multi-byte sequence starting at offset %u\n", i);
314 else if ( count == 0 )
317 bool result = Writer->WriteUi16BE((ui16_t)wcp);
319 if ( result == false )
321 DefaultLogSink().Error("No more space in memory IO writer\n");
332 //------------------------------------------------------------------------------------------
336 const ASDCP::MXF::ISO8String&
337 ASDCP::MXF::ISO8String::operator=(const char* sz)
339 if ( sz == 0 || *sz == 0 )
349 const ASDCP::MXF::ISO8String&
350 ASDCP::MXF::ISO8String::operator=(const std::string& str)
358 ASDCP::MXF::ISO8String::EncodeString(char* str_buf, ui32_t buf_len) const
360 ui32_t write_len = Kumu::xmin(buf_len - 1, (ui32_t)size());
361 strncpy(str_buf, c_str(), write_len);
362 str_buf[write_len] = 0;
368 ASDCP::MXF::ISO8String::Unarchive(Kumu::MemIOReader* Reader)
370 assign((char*)Reader->CurrentData(), Reader->Remainder());
376 ASDCP::MXF::ISO8String::Archive(Kumu::MemIOWriter* Writer) const
378 if ( size() > IdentBufferLen )
380 DefaultLogSink().Error("String length exceeds maximum %u bytes\n", IdentBufferLen);
384 return Writer->WriteString(*this);
387 //------------------------------------------------------------------------------------------
390 ASDCP::MXF::TLVReader::TLVReader(const byte_t* p, ui32_t c, IPrimerLookup* PrimerLookup) :
391 MemIOReader(p, c), m_Lookup(PrimerLookup)
393 Result_t result = RESULT_OK;
395 while ( Remainder() > 0 && ASDCP_SUCCESS(result) )
400 if ( MemIOReader::ReadUi8(&Tag.a) )
401 if ( MemIOReader::ReadUi8(&Tag.b) )
402 if ( MemIOReader::ReadUi16BE(&pkt_len) )
404 m_ElementMap.insert(TagMap::value_type(Tag, ItemInfo(m_size, pkt_len)));
405 if ( SkipOffset(pkt_len) )
409 DefaultLogSink().Error("Malformed Set\n");
410 m_ElementMap.clear();
411 result = RESULT_KLV_CODING;
417 ASDCP::MXF::TLVReader::FindTL(const MDDEntry& Entry)
421 DefaultLogSink().Error("No Lookup service\n");
427 if ( m_Lookup->TagForKey(Entry.ul, TmpTag) != RESULT_OK )
429 if ( Entry.tag.a == 0 )
431 // DefaultLogSink().Debug("No such UL in this TL list: %s (%02x %02x)\n",
432 // Entry.name, Entry.tag.a, Entry.tag.b);
439 TagMap::iterator e_i = m_ElementMap.find(TmpTag);
441 if ( e_i != m_ElementMap.end() )
443 m_size = (*e_i).second.first;
444 m_capacity = m_size + (*e_i).second.second;
448 // DefaultLogSink().Debug("Not Found (%02x %02x): %s\n", TmpTag.a, TmpTag.b, Entry.name);
454 ASDCP::MXF::TLVReader::ReadObject(const MDDEntry& Entry, Kumu::IArchive* Object)
456 ASDCP_TEST_NULL(Object);
460 if ( m_size < m_capacity ) // don't try to unarchive an empty item
461 return Object->Unarchive(this) ? RESULT_OK : RESULT_KLV_CODING;
469 ASDCP::MXF::TLVReader::ReadUi8(const MDDEntry& Entry, ui8_t* value)
471 ASDCP_TEST_NULL(value);
474 return MemIOReader::ReadUi8(value) ? RESULT_OK : RESULT_KLV_CODING;
481 ASDCP::MXF::TLVReader::ReadUi16(const MDDEntry& Entry, ui16_t* value)
483 ASDCP_TEST_NULL(value);
486 return MemIOReader::ReadUi16BE(value) ? RESULT_OK : RESULT_KLV_CODING;
493 ASDCP::MXF::TLVReader::ReadUi32(const MDDEntry& Entry, ui32_t* value)
495 ASDCP_TEST_NULL(value);
498 return MemIOReader::ReadUi32BE(value) ? RESULT_OK : RESULT_KLV_CODING;
505 ASDCP::MXF::TLVReader::ReadUi64(const MDDEntry& Entry, ui64_t* value)
507 ASDCP_TEST_NULL(value);
510 return MemIOReader::ReadUi64BE(value) ? RESULT_OK : RESULT_KLV_CODING;
515 //------------------------------------------------------------------------------------------
518 ASDCP::MXF::TLVWriter::TLVWriter(byte_t* p, ui32_t c, IPrimerLookup* PrimerLookup) :
519 MemIOWriter(p, c), m_Lookup(PrimerLookup)
526 ASDCP::MXF::TLVWriter::WriteTag(const MDDEntry& Entry)
530 DefaultLogSink().Error("No Primer object available\n");
536 if ( m_Lookup->InsertTag(Entry, TmpTag) != RESULT_OK )
538 DefaultLogSink().Error("No tag for entry %s\n", Entry.name);
542 if ( ! MemIOWriter::WriteUi8(TmpTag.a) ) return RESULT_KLV_CODING;
543 if ( ! MemIOWriter::WriteUi8(TmpTag.b) ) return RESULT_KLV_CODING;
549 ASDCP::MXF::TLVWriter::WriteObject(const MDDEntry& Entry, Kumu::IArchive* Object)
551 ASDCP_TEST_NULL(Object);
553 if ( Entry.optional && ! Object->HasValue() )
556 Result_t result = WriteTag(Entry);
558 if ( ASDCP_SUCCESS(result) )
560 // write a temp length
561 byte_t* l_p = CurrentData();
563 if ( ! MemIOWriter::WriteUi16BE(0) ) return RESULT_KLV_CODING;
565 ui32_t before = Length();
566 if ( ! Object->Archive(this) ) return RESULT_KLV_CODING;
567 if ( (Length() - before) > 0xffffL ) return RESULT_KLV_CODING;
568 Kumu::i2p<ui16_t>(KM_i16_BE(Length() - before), l_p);
576 ASDCP::MXF::TLVWriter::WriteUi8(const MDDEntry& Entry, ui8_t* value)
578 ASDCP_TEST_NULL(value);
579 Result_t result = WriteTag(Entry);
581 if ( ASDCP_SUCCESS(result) )
583 if ( ! MemIOWriter::WriteUi16BE(sizeof(ui8_t)) ) return RESULT_KLV_CODING;
584 if ( ! MemIOWriter::WriteUi8(*value) ) return RESULT_KLV_CODING;
592 ASDCP::MXF::TLVWriter::WriteUi16(const MDDEntry& Entry, ui16_t* value)
594 ASDCP_TEST_NULL(value);
595 Result_t result = WriteTag(Entry);
597 if ( KM_SUCCESS(result) )
599 if ( ! MemIOWriter::WriteUi16BE(sizeof(ui16_t)) ) return RESULT_KLV_CODING;
600 if ( ! MemIOWriter::WriteUi16BE(*value) ) return RESULT_KLV_CODING;
608 ASDCP::MXF::TLVWriter::WriteUi32(const MDDEntry& Entry, ui32_t* value)
610 ASDCP_TEST_NULL(value);
611 Result_t result = WriteTag(Entry);
613 if ( KM_SUCCESS(result) )
615 if ( ! MemIOWriter::WriteUi16BE(sizeof(ui32_t)) ) return RESULT_KLV_CODING;
616 if ( ! MemIOWriter::WriteUi32BE(*value) ) return RESULT_KLV_CODING;
624 ASDCP::MXF::TLVWriter::WriteUi64(const MDDEntry& Entry, ui64_t* value)
626 ASDCP_TEST_NULL(value);
627 Result_t result = WriteTag(Entry);
629 if ( KM_SUCCESS(result) )
631 if ( ! MemIOWriter::WriteUi16BE(sizeof(ui64_t)) ) return RESULT_KLV_CODING;
632 if ( ! MemIOWriter::WriteUi64BE(*value) ) return RESULT_KLV_CODING;
639 //----------------------------------------------------------------------------------------------------
642 ASDCP::MXF::Raw::Raw()
647 ASDCP::MXF::Raw::~Raw()
653 ASDCP::MXF::Raw::Unarchive(Kumu::MemIOReader* Reader)
655 ui32_t payload_size = Reader->Remainder();
656 if ( payload_size == 0 ) return false;
657 if ( KM_FAILURE(Capacity(payload_size)) ) return false;
659 memcpy(Data(), Reader->CurrentData(), payload_size);
660 Length(payload_size);
666 ASDCP::MXF::Raw::Archive(Kumu::MemIOWriter* Writer) const
668 return Writer->WriteRaw(RoData(), Length());
673 ASDCP::MXF::Raw::EncodeString(char* str_buf, ui32_t buf_len) const
676 Kumu::bin2hex(RoData(), Length(), str_buf, buf_len);