ec4f2d75ba24fd755f52f73fda6cb21ed63e25fc
[asdcplib.git] / src / MXFTypes.cpp
1 /*
2 Copyright (c) 2005-2006, 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 "MXFTypes.h"
33 #include "FortunaRNG.h"
34
35 //------------------------------------------------------------------------------------------
36 //
37
38
39 //
40 void
41 ASDCP::UMID::MakeUMID(int Type)
42 {
43   UUID AssetID;
44   AssetID.GenRandomValue();
45   MakeUMID(Type, AssetID);
46 }
47
48 //
49 void
50 ASDCP::UMID::MakeUMID(int Type, const UUID& AssetID)
51 {
52   // Set the non-varying base of the UMID
53   static const byte_t UMIDBase[10] = { 0x06, 0x0a, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };
54   memcpy(m_Value, UMIDBase, 10);
55   m_Value[10] = Type;  // Material Type
56   m_Value[12] = 0x13;  // length
57
58   // preserved for compatibility with mfxlib
59   if( Type > 4 ) m_Value[7] = 5;
60   m_Value[11] = 0x20; // UUID/UL method, number gen undefined
61
62   // Instance Number
63   m_Value[13] = m_Value[14] = m_Value[15] = 0;
64   
65   memcpy(&m_Value[16], AssetID.Value(), AssetID.Size());
66 }
67
68
69 // Write the timestamp value to the given buffer in the form 2004-05-01 13:20:00.000
70 // returns 0 if the buffer is smaller than DateTimeLen
71 const char*
72 ASDCP::UMID::ToString(char* str_buf) const
73 {
74   assert(str_buf);
75
76   snprintf(str_buf, IdentBufferLen, "[%02x%02x%02x%02x.%02x%02x.%02x%02x.%02x%02x%02x%02x],%02x,%02x,%02x,%02x,",
77            m_Value[0],  m_Value[1],  m_Value[2],  m_Value[3],
78            m_Value[4],  m_Value[5],  m_Value[6],  m_Value[7],
79            m_Value[8],  m_Value[9],  m_Value[10], m_Value[11],
80            m_Value[12], m_Value[13], m_Value[14], m_Value[15]
81            );
82
83   ui32_t offset = strlen(str_buf);
84
85   if ( ( m_Value[8] & 0x80 ) == 0 )
86     {
87       // half-swapped UL, use [bbaa9988.ddcc.ffee.00010203.04050607]
88       snprintf(str_buf + offset, IdentBufferLen - offset,
89                "[%02x%02x%02x%02x.%02x%02x.%02x%02x.%02x%02x%02x%02x.%02x%02x%02x%02x]",
90                m_Value[24], m_Value[25], m_Value[26], m_Value[27],
91                m_Value[28], m_Value[29], m_Value[30], m_Value[31],
92                m_Value[16], m_Value[17], m_Value[18], m_Value[19],
93                m_Value[20], m_Value[21], m_Value[22], m_Value[23]
94                );
95     }
96   else
97     {
98       // UUID, use {00112233-4455-6677-8899-aabbccddeeff}
99       snprintf(str_buf + offset, IdentBufferLen - offset,
100                "{%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
101                m_Value[16], m_Value[17], m_Value[18], m_Value[19],
102                m_Value[20], m_Value[21], m_Value[22], m_Value[23],
103                m_Value[24], m_Value[25], m_Value[26], m_Value[27],
104                m_Value[28], m_Value[29], m_Value[30], m_Value[31]
105                );
106     }
107
108   return str_buf;
109 }
110
111 //
112 void
113 ASDCP::UUID::GenRandomValue()
114 {
115   FortunaRNG RNG;
116   RNG.FillRandom(m_Value, UUIDlen);
117   m_Value[6] &= 0x0f; // clear bits 4-7
118   m_Value[6] |= 0x40; // set UUID version
119   m_Value[8] &= 0x3f; // clear bits 6&7
120   m_Value[8] |= 0x80; // set bit 7
121   //  m_HasValue = true;
122 }
123
124
125 //------------------------------------------------------------------------------------------
126 //
127
128 const ASDCP::MXF::UTF16String&
129 ASDCP::MXF::UTF16String::operator=(const char* sz)
130 {
131   if ( sz == 0 || *sz == 0 )
132     {
133       m_length = 0;
134       *m_buffer = 0;
135     }
136   else
137     {
138       ui32_t len = xmin((ui32_t)strlen(sz), (IdentBufferLen - 1));
139       m_length = len;
140       memcpy(m_buffer, sz, m_length);
141       m_buffer[m_length] = 0;
142     }
143   
144   return *this;
145 }
146
147
148 //
149 ASDCP::Result_t
150 ASDCP::MXF::UTF16String::Unarchive(ASDCP::MemIOReader& Reader)
151 {
152   const byte_t* p = Reader.CurrentData();
153   m_length = Reader.Remainder();
154   assert(m_length % 2 == 0);
155   m_length /= 2;
156   assert(IdentBufferLen >= m_length);
157   ui32_t i = 0;
158
159   for ( i = 0; i < m_length; i++ )
160     m_buffer[i] = p[(i*2)+1];
161
162   m_buffer[i] = 0;
163
164   Reader.SkipOffset(m_length*2);
165   return RESULT_OK;
166 }
167
168 //
169 ASDCP::Result_t
170 ASDCP::MXF::UTF16String::Archive(ASDCP::MemIOWriter& Writer) const
171 {
172   byte_t* p = Writer.Data() + Writer.Size();
173   ui32_t i = 0;
174   memset(p, 0, (m_length*2)+2);
175
176   for ( i = 0; i < m_length; i++ )
177     p[(i*2)+1] = m_buffer[i];
178
179   Writer.AddOffset(m_length * 2);
180   return RESULT_OK;
181 }
182
183
184 //------------------------------------------------------------------------------------------
185 //
186
187 #ifdef WIN32
188
189 #define TIMESTAMP_TO_SYSTIME(ts, t) \
190   (t)->wYear    = (ts).Year;   /* year */ \
191   (t)->wMonth   = (ts).Month;  /* month of year (1 - 12) */ \
192   (t)->wDay     = (ts).Day;    /* day of month (1 - 31) */ \
193   (t)->wHour    = (ts).Hour;   /* hours (0 - 23) */ \
194   (t)->wMinute  = (ts).Minute; /* minutes (0 - 59) */ \
195   (t)->wSecond  = (ts).Second; /* seconds (0 - 60) */ \
196   (t)->wDayOfWeek = 0; \
197   (t)->wMilliseconds = ((ts).Tick * 4);
198
199 #define SYSTIME_TO_TIMESTAMP(t, ts) \
200   (ts).Year   = (t)->wYear;    /* year */ \
201   (ts).Month  = (t)->wMonth;   /* month of year (1 - 12) */ \
202   (ts).Day    = (t)->wDay;     /* day of month (1 - 31) */ \
203   (ts).Hour   = (t)->wHour;    /* hours (0 - 23) */ \
204   (ts).Minute = (t)->wMinute;  /* minutes (0 - 59) */ \
205   (ts).Second = (t)->wSecond;  /* seconds (0 - 60) */ \
206   (ts).Tick   = (t)->wMilliseconds / 4;
207
208 //
209 ASDCP::MXF::Timestamp::Timestamp() :
210   Year(0), Month(0),  Day(0), Hour(0), Minute(0), Second(0), Tick(0)
211 {
212   SYSTEMTIME sys_time;
213   GetSystemTime(&sys_time);
214   SYSTIME_TO_TIMESTAMP(&sys_time, *this);
215 }
216
217 //
218 bool
219 ASDCP::MXF::Timestamp::operator<(const Timestamp& rhs) const
220 {
221   SYSTEMTIME lhst, rhst;
222   FILETIME lft, rft;
223
224   TIMESTAMP_TO_SYSTIME(*this, &lhst);
225   TIMESTAMP_TO_SYSTIME(rhs, &rhst);
226   SystemTimeToFileTime(&lhst, &lft);
227   SystemTimeToFileTime(&rhst, &rft);
228   return ( CompareFileTime(&lft, &rft) == -1 );
229 }
230
231 inline ui64_t
232 seconds_to_ns100(ui32_t seconds)
233 {
234   return ((ui64_t)seconds * 10000000);
235 }
236
237 //
238 void
239 ASDCP::MXF::Timestamp::AddDays(i32_t days)
240 {
241   SYSTEMTIME current_st;
242   FILETIME current_ft;
243   ULARGE_INTEGER current_ul;
244
245   if ( days != 0 )
246     {
247       TIMESTAMP_TO_SYSTIME(*this, &current_st);
248       SystemTimeToFileTime(&current_st, &current_ft);
249       memcpy(&current_ul, &current_ft, sizeof(current_ul));
250       current_ul.QuadPart += ( seconds_to_ns100(86400) * (ui64_t)days );
251       memcpy(&current_ft, &current_ul, sizeof(current_ft));
252       FileTimeToSystemTime(&current_ft, &current_st);
253       SYSTIME_TO_TIMESTAMP(&current_st, *this);
254     }
255 }
256
257 //
258 void
259 ASDCP::MXF::Timestamp::AddHours(i32_t hours)
260 {
261   SYSTEMTIME current_st;
262   FILETIME current_ft;
263   ULARGE_INTEGER current_ul;
264
265   if ( hours != 0 )
266     {
267       TIMESTAMP_TO_SYSTIME(*this, &current_st);
268       SystemTimeToFileTime(&current_st, &current_ft);
269       memcpy(&current_ul, &current_ft, sizeof(current_ul));
270       current_ul.QuadPart += ( seconds_to_ns100(3600) * (ui64_t)hours );
271       memcpy(&current_ft, &current_ul, sizeof(current_ft));
272       FileTimeToSystemTime(&current_ft, &current_st);
273       SYSTIME_TO_TIMESTAMP(&current_st, *this);
274     }
275 }
276
277 #else // WM_WIN32
278
279 #include <time.h>
280
281 #define TIMESTAMP_TO_TM(ts, t) \
282   (t)->tm_year = (ts).Year - 1900;   /* year - 1900 */ \
283   (t)->tm_mon  = (ts).Month - 1;     /* month of year (0 - 11) */ \
284   (t)->tm_mday = (ts).Day;           /* day of month (1 - 31) */ \
285   (t)->tm_hour = (ts).Hour;          /* hours (0 - 23) */ \
286   (t)->tm_min  = (ts).Minute;        /* minutes (0 - 59) */ \
287   (t)->tm_sec  = (ts).Second;        /* seconds (0 - 60) */
288
289 #define TM_TO_TIMESTAMP(t, ts) \
290   (ts).Year   = (t)->tm_year + 1900;    /* year - 1900 */ \
291   (ts).Month  = (t)->tm_mon + 1;     /* month of year (0 - 11) */ \
292   (ts).Day    = (t)->tm_mday;    /* day of month (1 - 31) */ \
293   (ts).Hour   = (t)->tm_hour;    /* hours (0 - 23) */ \
294   (ts).Minute = (t)->tm_min;     /* minutes (0 - 59) */ \
295   (ts).Second = (t)->tm_sec;     /* seconds (0 - 60) */
296
297 //
298 ASDCP::MXF::Timestamp::Timestamp() :
299   Year(0), Month(0),  Day(0), Hour(0), Minute(0), Second(0)
300 {
301   time_t t_now = time(0);
302   struct tm*  now = gmtime(&t_now);
303   TM_TO_TIMESTAMP(now, *this);
304 }
305
306 //
307 bool
308 ASDCP::MXF::Timestamp::operator<(const Timestamp& rhs) const
309 {
310   struct tm lhtm, rhtm;
311   TIMESTAMP_TO_TM(*this, &lhtm);
312   TIMESTAMP_TO_TM(rhs, &rhtm);
313   return ( timegm(&lhtm) < timegm(&rhtm) );
314 }
315
316 //
317 void
318 ASDCP::MXF::Timestamp::AddDays(i32_t days)
319 {
320   struct tm current;
321
322   if ( days != 0 )
323     {
324       TIMESTAMP_TO_TM(*this, &current);
325       time_t adj_time = timegm(&current);
326       adj_time += 86400 * days;
327       struct tm*  now = gmtime(&adj_time);
328       TM_TO_TIMESTAMP(now, *this);
329     }
330 }
331
332 //
333 void
334 ASDCP::MXF::Timestamp::AddHours(i32_t hours)
335 {
336   struct tm current;
337
338   if ( hours != 0 )
339     {
340       TIMESTAMP_TO_TM(*this, &current);
341       time_t adj_time = timegm(&current);
342       adj_time += 3600 * hours;
343       struct tm*  now = gmtime(&adj_time);
344       TM_TO_TIMESTAMP(now, *this);
345     }
346 }
347
348 #endif // WM_WIN32
349
350
351 ASDCP::MXF::Timestamp::Timestamp(const Timestamp& rhs)
352 {
353   Year   = rhs.Year;
354   Month  = rhs.Month;
355   Day    = rhs.Day;
356   Hour   = rhs.Hour;
357   Minute = rhs.Minute;
358   Second = rhs.Second;
359 }
360
361 ASDCP::MXF::Timestamp::~Timestamp()
362 {
363 }
364
365 //
366 const ASDCP::MXF::Timestamp&
367 ASDCP::MXF::Timestamp::operator=(const Timestamp& rhs)
368 {
369   Year   = rhs.Year;
370   Month  = rhs.Month;
371   Day    = rhs.Day;
372   Hour   = rhs.Hour;
373   Minute = rhs.Minute;
374   Second = rhs.Second;
375   return *this;
376 }
377
378 //
379 bool
380 ASDCP::MXF::Timestamp::operator==(const Timestamp& rhs) const
381 {
382   if ( Year == rhs.Year
383        && Month  == rhs.Month
384        && Day    == rhs.Day
385        && Hour   == rhs.Hour
386        && Minute == rhs.Minute
387        && Second == rhs.Second )
388     return true;
389
390   return false;
391 }
392
393 //
394 bool
395 ASDCP::MXF::Timestamp::operator!=(const Timestamp& rhs) const
396 {
397   if ( Year != rhs.Year
398        || Month  != rhs.Month
399        || Day    != rhs.Day
400        || Hour   != rhs.Hour
401        || Minute != rhs.Minute
402        || Second != rhs.Second )
403     return true;
404
405   return false;
406 }
407
408 //
409 const char*
410 ASDCP::MXF::Timestamp::ToString(char* str_buf) const
411 {
412   // 2004-05-01 13:20:00.000
413   snprintf(str_buf, IntBufferLen,
414            "%04hu-%02hu-%02hu %02hu:%02hu:%02hu.000",
415            Year, Month, Day, Hour, Minute, Second, Tick);
416   
417   return str_buf;
418 }
419
420 //------------------------------------------------------------------------------------------
421 //
422
423 ASDCP::MXF::TLVReader::TLVReader(const byte_t* p, ui32_t c, IPrimerLookup* PrimerLookup) :
424   MemIOReader(p, c), m_Lookup(PrimerLookup)
425 {
426   Result_t result = RESULT_OK;
427
428   while ( Remainder() > 0 && ASDCP_SUCCESS(result) )
429     {
430       TagValue Tag;
431       ui16_t pkt_len = 0;
432
433       result = MemIOReader::ReadUi8(&Tag.a);
434
435       if ( ASDCP_SUCCESS(result) )
436         result = MemIOReader::ReadUi8(&Tag.b);
437
438       if ( ASDCP_SUCCESS(result) )
439         result = MemIOReader::ReadUi16BE(&pkt_len);
440
441       if ( ASDCP_SUCCESS(result) )
442         {
443           m_ElementMap.insert(TagMap::value_type(Tag, ItemInfo(m_size, pkt_len)));
444           result = SkipOffset(pkt_len);
445         }
446       
447       if ( ASDCP_FAILURE(result) )
448         {
449           DefaultLogSink().Error("Malformed Set\n");
450           m_ElementMap.clear();
451           break;
452         }
453     }
454 }
455
456 //
457 bool
458 ASDCP::MXF::TLVReader::FindTL(const MDDEntry& Entry)
459 {
460   if ( m_Lookup == 0 )
461     {
462       DefaultLogSink().Error("No Lookup service\n");
463       return false;
464     }
465   
466   TagValue TmpTag;
467
468   if ( m_Lookup->TagForKey(Entry.ul, TmpTag) != RESULT_OK )
469     {
470       if ( Entry.tag.a == 0 )
471         {
472           DefaultLogSink().Info("No such UL in this TL list: %s (%02x %02x)\n",
473                                 Entry.name, Entry.tag.a, Entry.tag.b);
474           return false;
475         }
476
477       TmpTag = Entry.tag;
478     }
479
480   TagMap::iterator e_i = m_ElementMap.find(TmpTag);
481
482   if ( e_i != m_ElementMap.end() )
483     {
484       m_size = (*e_i).second.first;
485       m_capacity = m_size + (*e_i).second.second;
486       return true;
487     }
488
489   DefaultLogSink().Info("Not Found (%02x %02x): %s\n", TmpTag.a, TmpTag.b, Entry.name);
490   return false;
491 }
492
493 //
494 ASDCP::Result_t
495 ASDCP::MXF::TLVReader::ReadObject(const MDDEntry& Entry, IArchive* Object)
496 {
497   ASDCP_TEST_NULL(Object);
498
499   if ( FindTL(Entry) )
500     {
501       if ( m_size < m_capacity ) // don't try to unarchive an empty item
502         return Object->Unarchive(*this);
503     }
504
505   return RESULT_FALSE;
506 }
507
508 //
509 ASDCP::Result_t
510 ASDCP::MXF::TLVReader::ReadUi8(const MDDEntry& Entry, ui8_t* value)
511 {
512   ASDCP_TEST_NULL(value);
513
514   if ( FindTL(Entry) )
515     return MemIOReader::ReadUi8(value);
516
517   return RESULT_FALSE;
518 }
519
520 //
521 ASDCP::Result_t
522 ASDCP::MXF::TLVReader::ReadUi16(const MDDEntry& Entry, ui16_t* value)
523 {
524   ASDCP_TEST_NULL(value);
525
526   if ( FindTL(Entry) )
527     return MemIOReader::ReadUi16BE(value);
528
529   return RESULT_FALSE;
530 }
531
532 //
533 ASDCP::Result_t
534 ASDCP::MXF::TLVReader::ReadUi32(const MDDEntry& Entry, ui32_t* value)
535 {
536   ASDCP_TEST_NULL(value);
537
538   if ( FindTL(Entry) )
539     return MemIOReader::ReadUi32BE(value);
540
541   return RESULT_FALSE;
542 }
543
544 //
545 ASDCP::Result_t
546 ASDCP::MXF::TLVReader::ReadUi64(const MDDEntry& Entry, ui64_t* value)
547 {
548   ASDCP_TEST_NULL(value);
549
550   if ( FindTL(Entry) )
551     return MemIOReader::ReadUi64BE(value);
552
553   return RESULT_FALSE;
554 }
555
556 //------------------------------------------------------------------------------------------
557 //
558
559 ASDCP::MXF::TLVWriter::TLVWriter(byte_t* p, ui32_t c, IPrimerLookup* PrimerLookup) :
560   MemIOWriter(p, c), m_Lookup(PrimerLookup)
561 {
562   assert(c > 3);
563 }
564
565 //
566 ASDCP::Result_t
567 ASDCP::MXF::TLVWriter::WriteTag(const MDDEntry& Entry)
568 {
569   if ( m_Lookup == 0 )
570     {
571       DefaultLogSink().Error("No Primer object available\n");
572       return RESULT_FAIL;
573     }
574
575   TagValue TmpTag;
576
577   if ( m_Lookup->InsertTag(Entry, TmpTag) != RESULT_OK )
578     {
579       DefaultLogSink().Error("No tag for entry %s\n", Entry.name);
580       return RESULT_FAIL;
581     }
582
583   Result_t result = MemIOWriter::WriteUi8(TmpTag.a);
584   if ( ASDCP_SUCCESS(result) ) MemIOWriter::WriteUi8(TmpTag.b);
585
586   return result;
587 }
588
589 //
590 ASDCP::Result_t
591 ASDCP::MXF::TLVWriter::WriteObject(const MDDEntry& Entry, IArchive* Object)
592 {
593   ASDCP_TEST_NULL(Object);
594
595   if ( Entry.optional && ! Object->HasValue() )
596     return RESULT_OK;
597
598   Result_t result = WriteTag(Entry);
599
600   // write a temp length
601   byte_t* l_p = CurrentData();
602
603   if ( ASDCP_SUCCESS(result) )
604     MemIOWriter::WriteUi16BE(0);
605
606   if ( ASDCP_SUCCESS(result) )
607     {
608       ui32_t before = Size();
609       result = Object->Archive(*this);
610
611       if ( ASDCP_SUCCESS(result) ) 
612         i2p<ui16_t>(ASDCP_i16_BE( Size() - before), l_p);
613     }
614
615   return result;
616 }
617
618 //
619 ASDCP::Result_t
620 ASDCP::MXF::TLVWriter::WriteUi8(const MDDEntry& Entry, ui8_t* value)
621 {
622   ASDCP_TEST_NULL(value);
623   Result_t result = WriteTag(Entry);
624   if ( ASDCP_SUCCESS(result) ) MemIOWriter::WriteUi16BE(sizeof(ui8_t));
625   if ( ASDCP_SUCCESS(result) ) MemIOWriter::WriteUi8(*value);
626   return result;
627 }
628
629 //
630 ASDCP::Result_t
631 ASDCP::MXF::TLVWriter::WriteUi16(const MDDEntry& Entry, ui16_t* value)
632 {
633   ASDCP_TEST_NULL(value);
634   Result_t result = WriteTag(Entry);
635   if ( ASDCP_SUCCESS(result) ) MemIOWriter::WriteUi16BE(sizeof(ui16_t));
636   if ( ASDCP_SUCCESS(result) ) MemIOWriter::WriteUi16BE(*value);
637   return result;
638 }
639
640 //
641 ASDCP::Result_t
642 ASDCP::MXF::TLVWriter::WriteUi32(const MDDEntry& Entry, ui32_t* value)
643 {
644   ASDCP_TEST_NULL(value);
645   Result_t result = WriteTag(Entry);
646   if ( ASDCP_SUCCESS(result) ) MemIOWriter::WriteUi16BE(sizeof(ui32_t));
647   if ( ASDCP_SUCCESS(result) ) MemIOWriter::WriteUi32BE(*value);
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   if ( ASDCP_SUCCESS(result) ) MemIOWriter::WriteUi16BE(sizeof(ui64_t));
658   if ( ASDCP_SUCCESS(result) ) MemIOWriter::WriteUi64BE(*value);
659   return result;
660 }
661
662
663 //----------------------------------------------------------------------------------------------------
664 //
665
666 ASDCP::MXF::Raw::Raw()
667 {
668   Capacity(256);
669 }
670
671 ASDCP::MXF::Raw::~Raw()
672 {
673 }
674
675 //
676 ASDCP::Result_t
677 ASDCP::MXF::Raw::Unarchive(ASDCP::MemIOReader& Reader)
678 {
679   ui32_t payload_size = Reader.Remainder();
680
681   if ( payload_size == 0 )
682     return RESULT_OK;
683
684   Result_t result = Capacity(payload_size);
685
686   if ( ASDCP_SUCCESS(result) )
687     {
688       memcpy(Data(), Reader.CurrentData(), payload_size);
689       Size(payload_size);
690     }
691
692   return result;
693 }
694
695 //
696 ASDCP::Result_t
697 ASDCP::MXF::Raw::Archive(ASDCP::MemIOWriter& Writer) const
698 {
699   return Writer.WriteRaw(RoData(), Size());
700 }
701
702 //
703 const char*
704 ASDCP::MXF::Raw::ToString(char* str_buf) const
705 {
706   *str_buf = 0;
707   bin2hex(RoData(), Size(), str_buf, IdentBufferLen);
708   snprintf(str_buf, IdentBufferLen, "%s\n", str_buf);
709   return str_buf;
710 }
711
712 //
713 // end MXFTypes.cpp
714 //