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