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