missing TimedText_transform.h
[asdcplib.git] / src / MXFTypes.cpp
1 /*
2 Copyright (c) 2005-2012, John Hurst
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
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.
15
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.
26 */
27 /*! \file    MXFTypes.cpp
28     \version $Id$
29     \brief   MXF objects
30 */
31
32 #include <KM_prng.h>
33 #include <KM_tai.h>
34 #include "MXFTypes.h"
35 #include <KM_log.h>
36
37 using Kumu::DefaultLogSink;
38
39 //------------------------------------------------------------------------------------------
40 //
41
42 //
43 bool
44 ASDCP::UL::operator==(const UL& rhs) const
45 {
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]
62        )
63     return true;
64
65   return false;
66 }
67
68 //
69 bool
70 ASDCP::UL::MatchIgnoreStream(const UL& rhs) const
71 {
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
88        )
89     return true;
90
91   return false;
92 }
93
94 //
95 bool
96 ASDCP::UL::ExactMatch(const UL& rhs) const
97 {
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]
114        )
115     return true;
116
117   return false;
118 }
119
120 const char*
121 ASDCP::UL::EncodeString(char* str_buf, ui32_t buf_len) const
122 {
123   if ( buf_len > 38 ) // room for dotted notation?
124     {
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]
131                );
132
133       return str_buf;
134     }
135   else if ( buf_len > 32 ) // room for compact?
136     {
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]
143                );
144
145       return str_buf;
146     }
147
148   return 0;
149 }
150
151 //
152 void
153 ASDCP::UMID::MakeUMID(int Type)
154 {
155   UUID AssetID;
156   Kumu::GenRandomValue(AssetID);
157   MakeUMID(Type, AssetID);
158 }
159
160 //
161 void
162 ASDCP::UMID::MakeUMID(int Type, const UUID& AssetID)
163 {
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
169
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
173
174   // Instance Number
175   m_Value[13] = m_Value[14] = m_Value[15] = 0;
176   
177   memcpy(&m_Value[16], AssetID.Value(), AssetID.Size());
178   m_HasValue = true;
179 }
180
181
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]
184 // or
185 //   [00000000.0000.0000.00000000],00,00,00,00,00000000-0000-0000-0000-000000000000]
186 // returns 0 if the buffer is smaller than DateTimeLen
187 const char*
188 ASDCP::UMID::EncodeString(char* str_buf, ui32_t buf_len) const
189 {
190   assert(str_buf);
191
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]
197            );
198
199   ui32_t offset = strlen(str_buf);
200
201   if ( ( m_Value[8] & 0x80 ) == 0 )
202     {
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]
210                );
211     }
212   else
213     {
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]
221                );
222     }
223
224   return str_buf;
225 }
226
227 //------------------------------------------------------------------------------------------
228 //
229
230 //
231 ASDCP::MXF::UTF16String::UTF16String(const char* sz)
232 {
233   if ( sz != 0 && *sz != 0 )
234     {
235       this->assign(sz);
236     }
237 }
238
239 ASDCP::MXF::UTF16String::UTF16String(const std::string& str)
240 {
241   this->assign(str);
242 }
243
244 //
245 const ASDCP::MXF::UTF16String&
246 ASDCP::MXF::UTF16String::operator=(const char* sz)
247 {
248   if ( sz == 0 || *sz == 0 )
249     erase();
250
251   else
252     this->assign(sz);
253   
254   return *this;
255 }
256
257 //
258 const ASDCP::MXF::UTF16String&
259 ASDCP::MXF::UTF16String::operator=(const std::string& str)
260 {
261   this->assign(str);
262   return *this;
263 }
264
265 //
266 const char*
267 ASDCP::MXF::UTF16String::EncodeString(char* str_buf, ui32_t buf_len) const
268 {
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;
272   return str_buf;
273 }
274
275 //
276 bool
277 ASDCP::MXF::UTF16String::Unarchive(Kumu::MemIOReader* Reader)
278 {
279   erase();
280   const ui16_t* p = (ui16_t*)Reader->CurrentData();
281   ui32_t length = Reader->Remainder() / 2;
282   char mb_buf[MB_LEN_MAX+1];
283
284   for ( ui32_t i = 0; i < length; i++ )
285     {
286       int count = wctomb(mb_buf, KM_i16_BE(p[i]));
287
288       if ( count == -1 )
289         {
290           DefaultLogSink().Error("Unable to decode wide character 0x%04hx\n", p[i]);
291           return false;
292         }
293
294       assert(count <= MB_LEN_MAX);
295       mb_buf[count] = 0;
296       this->append(mb_buf);
297     }
298
299   Reader->SkipOffset(length*2);
300   return true;
301 }
302
303 //
304 bool
305 ASDCP::MXF::UTF16String::Archive(Kumu::MemIOWriter* Writer) const
306 {
307   if ( size() > IdentBufferLen )
308     {
309       DefaultLogSink().Error("String length exceeds maximum %u bytes\n", IdentBufferLen);
310       return false;
311     }
312
313   const char* mbp = c_str();
314   wchar_t wcp;
315   ui32_t remainder = size();
316   ui32_t length = size();
317   ui32_t i = 0;
318
319   while ( i < length )
320     {
321       int count = mbtowc(&wcp, mbp+i, remainder);
322
323       if ( count == -1 )
324         {
325           DefaultLogSink().Error("Error decoding multi-byte sequence starting at offset %u\n", i);
326           return false;
327         }
328       else if ( count  == 0 )
329         break;
330
331       bool result = Writer->WriteUi16BE((ui16_t)wcp);
332
333       if ( result == false )
334         {
335           DefaultLogSink().Error("No more space in memory IO writer\n");
336           return false;
337         }
338
339       i += count;
340       remainder -= count;
341     }
342
343   return true;
344 }
345
346 //------------------------------------------------------------------------------------------
347 //
348
349 //
350 ASDCP::MXF::ISO8String::ISO8String(const char* sz)
351 {
352   if ( sz != 0 && *sz != 0 )
353     {
354       this->assign(sz);
355     }
356 }
357
358 ASDCP::MXF::ISO8String::ISO8String(const std::string& str)
359 {
360   this->assign(str);
361 }
362
363
364 //
365 const ASDCP::MXF::ISO8String&
366 ASDCP::MXF::ISO8String::operator=(const char* sz)
367 {
368   if ( sz == 0 || *sz == 0 )
369     erase();
370
371   else
372     this->assign(sz);
373   
374   return *this;
375 }
376
377 //
378 const ASDCP::MXF::ISO8String&
379 ASDCP::MXF::ISO8String::operator=(const std::string& str)
380 {
381   this->assign(str);
382   return *this;
383 }
384
385 //
386 const char*
387 ASDCP::MXF::ISO8String::EncodeString(char* str_buf, ui32_t buf_len) const
388 {
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;
392   return str_buf;
393 }
394
395 //
396 bool
397 ASDCP::MXF::ISO8String::Unarchive(Kumu::MemIOReader* Reader)
398 {
399   assign((char*)Reader->CurrentData(), Reader->Remainder());
400   return true;
401 }
402
403 //
404 bool
405 ASDCP::MXF::ISO8String::Archive(Kumu::MemIOWriter* Writer) const
406 {
407   if ( size() > IdentBufferLen )
408     {
409       DefaultLogSink().Error("String length exceeds maximum %u bytes\n", IdentBufferLen);
410       return false;
411     }
412
413   return Writer->WriteRaw((const byte_t*)c_str(), size());
414 }
415
416 //------------------------------------------------------------------------------------------
417 //
418
419 ASDCP::MXF::TLVReader::TLVReader(const byte_t* p, ui32_t c, IPrimerLookup* PrimerLookup) :
420   MemIOReader(p, c), m_Lookup(PrimerLookup)
421 {
422   Result_t result = RESULT_OK;
423
424   while ( Remainder() > 0 && ASDCP_SUCCESS(result) )
425     {
426       TagValue Tag;
427       ui16_t pkt_len = 0;
428
429       if ( MemIOReader::ReadUi8(&Tag.a) )
430         if ( MemIOReader::ReadUi8(&Tag.b) )
431           if ( MemIOReader::ReadUi16BE(&pkt_len) )
432             {
433               m_ElementMap.insert(TagMap::value_type(Tag, ItemInfo(m_size, pkt_len)));
434               if ( SkipOffset(pkt_len) )
435                 continue;;
436             }
437
438       DefaultLogSink().Error("Malformed Set\n");
439       m_ElementMap.clear();
440       result = RESULT_KLV_CODING;
441     }
442 }
443
444 //
445 bool
446 ASDCP::MXF::TLVReader::FindTL(const MDDEntry& Entry)
447 {
448   if ( m_Lookup == 0 )
449     {
450       DefaultLogSink().Error("No Lookup service\n");
451       return false;
452     }
453   
454   TagValue TmpTag;
455
456   if ( m_Lookup->TagForKey(Entry.ul, TmpTag) != RESULT_OK )
457     {
458       if ( Entry.tag.a == 0 )
459         {
460           //      DefaultLogSink().Debug("No such UL in this TL list: %s (%02x %02x)\n",
461           //                             Entry.name, Entry.tag.a, Entry.tag.b);
462           return false;
463         }
464
465       TmpTag = Entry.tag;
466     }
467
468   TagMap::iterator e_i = m_ElementMap.find(TmpTag);
469
470   if ( e_i != m_ElementMap.end() )
471     {
472       m_size = (*e_i).second.first;
473       m_capacity = m_size + (*e_i).second.second;
474       return true;
475     }
476
477   //  DefaultLogSink().Debug("Not Found (%02x %02x): %s\n", TmpTag.a, TmpTag.b, Entry.name);
478   return false;
479 }
480
481 //
482 ASDCP::Result_t
483 ASDCP::MXF::TLVReader::ReadObject(const MDDEntry& Entry, Kumu::IArchive* Object)
484 {
485   ASDCP_TEST_NULL(Object);
486
487   if ( FindTL(Entry) )
488     {
489       if ( m_size < m_capacity ) // don't try to unarchive an empty item
490         return Object->Unarchive(this) ? RESULT_OK : RESULT_KLV_CODING;
491     }
492
493   return RESULT_FALSE;
494 }
495
496 //
497 ASDCP::Result_t
498 ASDCP::MXF::TLVReader::ReadUi8(const MDDEntry& Entry, ui8_t* value)
499 {
500   ASDCP_TEST_NULL(value);
501
502   if ( FindTL(Entry) )
503     return MemIOReader::ReadUi8(value) ? RESULT_OK : RESULT_KLV_CODING;
504
505   return RESULT_FALSE;
506 }
507
508 //
509 ASDCP::Result_t
510 ASDCP::MXF::TLVReader::ReadUi16(const MDDEntry& Entry, ui16_t* value)
511 {
512   ASDCP_TEST_NULL(value);
513
514   if ( FindTL(Entry) )
515     return MemIOReader::ReadUi16BE(value) ? RESULT_OK : RESULT_KLV_CODING;
516
517   return RESULT_FALSE;
518 }
519
520 //
521 ASDCP::Result_t
522 ASDCP::MXF::TLVReader::ReadUi32(const MDDEntry& Entry, ui32_t* value)
523 {
524   ASDCP_TEST_NULL(value);
525
526   if ( FindTL(Entry) )
527     return MemIOReader::ReadUi32BE(value) ? RESULT_OK : RESULT_KLV_CODING;
528
529   return RESULT_FALSE;
530 }
531
532 //
533 ASDCP::Result_t
534 ASDCP::MXF::TLVReader::ReadUi64(const MDDEntry& Entry, ui64_t* value)
535 {
536   ASDCP_TEST_NULL(value);
537
538   if ( FindTL(Entry) )
539     return MemIOReader::ReadUi64BE(value) ? RESULT_OK : RESULT_KLV_CODING;
540
541   return RESULT_FALSE;
542 }
543
544 //------------------------------------------------------------------------------------------
545 //
546
547 ASDCP::MXF::TLVWriter::TLVWriter(byte_t* p, ui32_t c, IPrimerLookup* PrimerLookup) :
548   MemIOWriter(p, c), m_Lookup(PrimerLookup)
549 {
550   assert(c > 3);
551 }
552
553 //
554 ASDCP::Result_t
555 ASDCP::MXF::TLVWriter::WriteTag(const MDDEntry& Entry)
556 {
557   if ( m_Lookup == 0 )
558     {
559       DefaultLogSink().Error("No Primer object available\n");
560       return RESULT_FAIL;
561     }
562
563   TagValue TmpTag;
564
565   if ( m_Lookup->InsertTag(Entry, TmpTag) != RESULT_OK )
566     {
567       DefaultLogSink().Error("No tag for entry %s\n", Entry.name);
568       return RESULT_FAIL;
569     }
570
571   if ( ! MemIOWriter::WriteUi8(TmpTag.a) ) return RESULT_KLV_CODING;
572   if ( ! MemIOWriter::WriteUi8(TmpTag.b) ) return RESULT_KLV_CODING;
573   return RESULT_OK;
574 }
575
576 //
577 ASDCP::Result_t
578 ASDCP::MXF::TLVWriter::WriteObject(const MDDEntry& Entry, Kumu::IArchive* Object)
579 {
580   ASDCP_TEST_NULL(Object);
581
582   if ( Entry.optional && ! Object->HasValue() )
583     return RESULT_OK;
584
585   Result_t result = WriteTag(Entry);
586
587   if ( ASDCP_SUCCESS(result) )
588     {
589       // write a temp length
590       byte_t* l_p = CurrentData();
591
592       if ( ! MemIOWriter::WriteUi16BE(0) ) return RESULT_KLV_CODING;
593
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);
598     }
599
600   return result;
601 }
602
603 //
604 ASDCP::Result_t
605 ASDCP::MXF::TLVWriter::WriteUi8(const MDDEntry& Entry, ui8_t* value)
606 {
607   ASDCP_TEST_NULL(value);
608   Result_t result = WriteTag(Entry);
609
610   if ( ASDCP_SUCCESS(result) )
611     {
612       if ( ! MemIOWriter::WriteUi16BE(sizeof(ui8_t)) ) return RESULT_KLV_CODING;
613       if ( ! MemIOWriter::WriteUi8(*value) ) return RESULT_KLV_CODING;
614     }
615   
616   return result;
617 }
618
619 //
620 ASDCP::Result_t
621 ASDCP::MXF::TLVWriter::WriteUi16(const MDDEntry& Entry, ui16_t* value)
622 {
623   ASDCP_TEST_NULL(value);
624   Result_t result = WriteTag(Entry);
625
626   if ( KM_SUCCESS(result) )
627     {
628       if ( ! MemIOWriter::WriteUi16BE(sizeof(ui16_t)) ) return RESULT_KLV_CODING;
629       if ( ! MemIOWriter::WriteUi16BE(*value) ) return RESULT_KLV_CODING;
630     }
631
632   return result;
633 }
634
635 //
636 ASDCP::Result_t
637 ASDCP::MXF::TLVWriter::WriteUi32(const MDDEntry& Entry, ui32_t* value)
638 {
639   ASDCP_TEST_NULL(value);
640   Result_t result = WriteTag(Entry);
641
642   if ( KM_SUCCESS(result) )
643     {
644       if ( ! MemIOWriter::WriteUi16BE(sizeof(ui32_t)) ) return RESULT_KLV_CODING;
645       if ( ! MemIOWriter::WriteUi32BE(*value) ) return RESULT_KLV_CODING;
646     }
647
648   return result;
649 }
650
651 //
652 ASDCP::Result_t
653 ASDCP::MXF::TLVWriter::WriteUi64(const MDDEntry& Entry, ui64_t* value)
654 {
655   ASDCP_TEST_NULL(value);
656   Result_t result = WriteTag(Entry);
657
658   if ( KM_SUCCESS(result) )
659     {
660       if ( ! MemIOWriter::WriteUi16BE(sizeof(ui64_t)) ) return RESULT_KLV_CODING;
661       if ( ! MemIOWriter::WriteUi64BE(*value) ) return RESULT_KLV_CODING;
662     }
663
664   return result;
665 }
666
667
668 //----------------------------------------------------------------------------------------------------
669 //
670
671 ASDCP::MXF::Raw::Raw()
672 {
673   Capacity(256);
674 }
675
676 ASDCP::MXF::Raw::~Raw()
677 {
678 }
679
680 //
681 bool
682 ASDCP::MXF::Raw::Unarchive(Kumu::MemIOReader* Reader)
683 {
684   ui32_t payload_size = Reader->Remainder();
685   if ( payload_size == 0 ) return false;
686   if ( KM_FAILURE(Capacity(payload_size)) ) return false;
687
688   memcpy(Data(), Reader->CurrentData(), payload_size);
689   Length(payload_size);
690   return true;
691 }
692
693 //
694 bool
695 ASDCP::MXF::Raw::Archive(Kumu::MemIOWriter* Writer) const
696 {
697   return Writer->WriteRaw(RoData(), Length());
698 }
699
700 //
701 const char*
702 ASDCP::MXF::Raw::EncodeString(char* str_buf, ui32_t buf_len) const
703 {
704   *str_buf = 0;
705   Kumu::bin2hex(RoData(), Length(), str_buf, buf_len);
706   return str_buf;
707 }
708
709 //
710 // end MXFTypes.cpp
711 //