megasubs
[asdcplib.git] / src / MXFTypes.cpp
1 /*
2 Copyright (c) 2005-2015, 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         {
330           break;
331         }
332
333       bool result = Writer->WriteUi16BE((ui16_t)wcp);
334
335       if ( result == false )
336         {
337           DefaultLogSink().Error("No more space in memory IO writer\n");
338           return false;
339         }
340
341       i += count;
342       remainder -= count;
343     }
344
345   return true;
346 }
347
348 //------------------------------------------------------------------------------------------
349 //
350
351 //
352 ASDCP::MXF::ISO8String::ISO8String(const char* sz)
353 {
354   if ( sz != 0 && *sz != 0 )
355     {
356       this->assign(sz);
357     }
358 }
359
360 ASDCP::MXF::ISO8String::ISO8String(const std::string& str)
361 {
362   this->assign(str);
363 }
364
365
366 //
367 const ASDCP::MXF::ISO8String&
368 ASDCP::MXF::ISO8String::operator=(const char* sz)
369 {
370   if ( sz == 0 || *sz == 0 )
371     erase();
372
373   else
374     this->assign(sz);
375   
376   return *this;
377 }
378
379 //
380 const ASDCP::MXF::ISO8String&
381 ASDCP::MXF::ISO8String::operator=(const std::string& str)
382 {
383   this->assign(str);
384   return *this;
385 }
386
387 //
388 const char*
389 ASDCP::MXF::ISO8String::EncodeString(char* str_buf, ui32_t buf_len) const
390 {
391   ui32_t write_len = Kumu::xmin(buf_len - 1, (ui32_t)size());
392   strncpy(str_buf, c_str(), write_len);
393   str_buf[write_len] = 0;
394   return str_buf;
395 }
396
397 //
398 bool
399 ASDCP::MXF::ISO8String::Unarchive(Kumu::MemIOReader* Reader)
400 {
401   assign((char*)Reader->CurrentData(), Reader->Remainder());
402   return true;
403 }
404
405 //
406 bool
407 ASDCP::MXF::ISO8String::Archive(Kumu::MemIOWriter* Writer) const
408 {
409   if ( size() > IdentBufferLen )
410     {
411       DefaultLogSink().Error("String length exceeds maximum %u bytes\n", IdentBufferLen);
412       return false;
413     }
414
415   return Writer->WriteRaw((const byte_t*)c_str(), size());
416 }
417
418 //------------------------------------------------------------------------------------------
419 //
420
421 ASDCP::MXF::TLVReader::TLVReader(const byte_t* p, ui32_t c, IPrimerLookup* PrimerLookup) :
422   MemIOReader(p, c), m_Lookup(PrimerLookup)
423 {
424   Result_t result = RESULT_OK;
425
426   while ( Remainder() > 0 && ASDCP_SUCCESS(result) )
427     {
428       TagValue Tag;
429       ui16_t pkt_len = 0;
430
431       if ( MemIOReader::ReadUi8(&Tag.a) )
432         if ( MemIOReader::ReadUi8(&Tag.b) )
433           if ( MemIOReader::ReadUi16BE(&pkt_len) )
434             {
435               m_ElementMap.insert(TagMap::value_type(Tag, ItemInfo(m_size, pkt_len)));
436               if ( SkipOffset(pkt_len) )
437                 continue;;
438             }
439
440       DefaultLogSink().Error("Malformed Set\n");
441       m_ElementMap.clear();
442       result = RESULT_KLV_CODING;
443     }
444 }
445
446 //
447 bool
448 ASDCP::MXF::TLVReader::FindTL(const MDDEntry& Entry)
449 {
450   if ( m_Lookup == 0 )
451     {
452       DefaultLogSink().Error("No Lookup service\n");
453       return false;
454     }
455   
456   TagValue TmpTag;
457
458   if ( m_Lookup->TagForKey(Entry.ul, TmpTag) != RESULT_OK )
459     {
460       if ( Entry.tag.a == 0 )
461         {
462           //      DefaultLogSink().Debug("No such UL in this TL list: %s (%02x %02x)\n",
463           //                             Entry.name, Entry.tag.a, Entry.tag.b);
464           return false;
465         }
466
467       TmpTag = Entry.tag;
468     }
469
470   TagMap::iterator e_i = m_ElementMap.find(TmpTag);
471
472   if ( e_i != m_ElementMap.end() )
473     {
474       m_size = (*e_i).second.first;
475       m_capacity = m_size + (*e_i).second.second;
476       return true;
477     }
478
479   //  DefaultLogSink().Debug("Not Found (%02x %02x): %s\n", TmpTag.a, TmpTag.b, Entry.name);
480   return false;
481 }
482
483 //
484 ASDCP::Result_t
485 ASDCP::MXF::TLVReader::ReadObject(const MDDEntry& Entry, Kumu::IArchive* Object)
486 {
487   ASDCP_TEST_NULL(Object);
488
489   if ( FindTL(Entry) )
490     {
491       if ( m_size < m_capacity ) // don't try to unarchive an empty item
492         return Object->Unarchive(this) ? RESULT_OK : RESULT_KLV_CODING;
493     }
494
495   return RESULT_FALSE;
496 }
497
498 //
499 ASDCP::Result_t
500 ASDCP::MXF::TLVReader::ReadUi8(const MDDEntry& Entry, ui8_t* value)
501 {
502   ASDCP_TEST_NULL(value);
503
504   if ( FindTL(Entry) )
505     return MemIOReader::ReadUi8(value) ? RESULT_OK : RESULT_KLV_CODING;
506
507   return RESULT_FALSE;
508 }
509
510 //
511 ASDCP::Result_t
512 ASDCP::MXF::TLVReader::ReadUi16(const MDDEntry& Entry, ui16_t* value)
513 {
514   ASDCP_TEST_NULL(value);
515
516   if ( FindTL(Entry) )
517     return MemIOReader::ReadUi16BE(value) ? RESULT_OK : RESULT_KLV_CODING;
518
519   return RESULT_FALSE;
520 }
521
522 //
523 ASDCP::Result_t
524 ASDCP::MXF::TLVReader::ReadUi32(const MDDEntry& Entry, ui32_t* value)
525 {
526   ASDCP_TEST_NULL(value);
527
528   if ( FindTL(Entry) )
529     return MemIOReader::ReadUi32BE(value) ? RESULT_OK : RESULT_KLV_CODING;
530
531   return RESULT_FALSE;
532 }
533
534 //
535 ASDCP::Result_t
536 ASDCP::MXF::TLVReader::ReadUi64(const MDDEntry& Entry, ui64_t* value)
537 {
538   ASDCP_TEST_NULL(value);
539
540   if ( FindTL(Entry) )
541     return MemIOReader::ReadUi64BE(value) ? RESULT_OK : RESULT_KLV_CODING;
542
543   return RESULT_FALSE;
544 }
545
546 //------------------------------------------------------------------------------------------
547 //
548
549 ASDCP::MXF::TLVWriter::TLVWriter(byte_t* p, ui32_t c, IPrimerLookup* PrimerLookup) :
550   MemIOWriter(p, c), m_Lookup(PrimerLookup)
551 {
552   assert(c > 3);
553 }
554
555 //
556 ASDCP::Result_t
557 ASDCP::MXF::TLVWriter::WriteTag(const MDDEntry& Entry)
558 {
559   if ( m_Lookup == 0 )
560     {
561       DefaultLogSink().Error("No Primer object available\n");
562       return RESULT_FAIL;
563     }
564
565   TagValue TmpTag;
566
567   if ( m_Lookup->InsertTag(Entry, TmpTag) != RESULT_OK )
568     {
569       DefaultLogSink().Error("No tag for entry %s\n", Entry.name);
570       return RESULT_FAIL;
571     }
572
573   if ( ! MemIOWriter::WriteUi8(TmpTag.a) ) return RESULT_KLV_CODING;
574   if ( ! MemIOWriter::WriteUi8(TmpTag.b) ) return RESULT_KLV_CODING;
575   return RESULT_OK;
576 }
577
578 //
579 ASDCP::Result_t
580 ASDCP::MXF::TLVWriter::WriteObject(const MDDEntry& Entry, Kumu::IArchive* Object)
581 {
582   ASDCP_TEST_NULL(Object);
583
584   if ( Entry.optional && ! Object->HasValue() )
585     return RESULT_OK;
586
587   Result_t result = WriteTag(Entry);
588
589   if ( ASDCP_SUCCESS(result) )
590     {
591       // write a temp length
592       byte_t* l_p = CurrentData();
593
594       if ( ! MemIOWriter::WriteUi16BE(0) ) return RESULT_KLV_CODING;
595
596       ui32_t before = Length();
597       if ( ! Object->Archive(this) ) return RESULT_KLV_CODING;
598       if ( (Length() - before) > 0xffffL ) return RESULT_KLV_CODING;
599       Kumu::i2p<ui16_t>(KM_i16_BE(Length() - before), l_p);
600     }
601
602   return result;
603 }
604
605 //
606 ASDCP::Result_t
607 ASDCP::MXF::TLVWriter::WriteUi8(const MDDEntry& Entry, ui8_t* value)
608 {
609   ASDCP_TEST_NULL(value);
610   Result_t result = WriteTag(Entry);
611
612   if ( ASDCP_SUCCESS(result) )
613     {
614       if ( ! MemIOWriter::WriteUi16BE(sizeof(ui8_t)) ) return RESULT_KLV_CODING;
615       if ( ! MemIOWriter::WriteUi8(*value) ) return RESULT_KLV_CODING;
616     }
617   
618   return result;
619 }
620
621 //
622 ASDCP::Result_t
623 ASDCP::MXF::TLVWriter::WriteUi16(const MDDEntry& Entry, ui16_t* value)
624 {
625   ASDCP_TEST_NULL(value);
626   Result_t result = WriteTag(Entry);
627
628   if ( KM_SUCCESS(result) )
629     {
630       if ( ! MemIOWriter::WriteUi16BE(sizeof(ui16_t)) ) return RESULT_KLV_CODING;
631       if ( ! MemIOWriter::WriteUi16BE(*value) ) return RESULT_KLV_CODING;
632     }
633
634   return result;
635 }
636
637 //
638 ASDCP::Result_t
639 ASDCP::MXF::TLVWriter::WriteUi32(const MDDEntry& Entry, ui32_t* value)
640 {
641   ASDCP_TEST_NULL(value);
642   Result_t result = WriteTag(Entry);
643
644   if ( KM_SUCCESS(result) )
645     {
646       if ( ! MemIOWriter::WriteUi16BE(sizeof(ui32_t)) ) return RESULT_KLV_CODING;
647       if ( ! MemIOWriter::WriteUi32BE(*value) ) return RESULT_KLV_CODING;
648     }
649
650   return result;
651 }
652
653 //
654 ASDCP::Result_t
655 ASDCP::MXF::TLVWriter::WriteUi64(const MDDEntry& Entry, ui64_t* value)
656 {
657   ASDCP_TEST_NULL(value);
658   Result_t result = WriteTag(Entry);
659
660   if ( KM_SUCCESS(result) )
661     {
662       if ( ! MemIOWriter::WriteUi16BE(sizeof(ui64_t)) ) return RESULT_KLV_CODING;
663       if ( ! MemIOWriter::WriteUi64BE(*value) ) return RESULT_KLV_CODING;
664     }
665
666   return result;
667 }
668
669
670 //----------------------------------------------------------------------------------------------------
671 //
672
673
674 ASDCP::MXF::RGBALayout::RGBALayout()
675 {
676   memset(m_value, 0, RGBAValueLength);
677 }
678
679 ASDCP::MXF::RGBALayout::RGBALayout(const byte_t* value)
680 {
681   memcpy(m_value, value, RGBAValueLength);
682 }
683
684 ASDCP::MXF::RGBALayout::~RGBALayout()
685 {
686 }
687
688 static char
689 get_char_for_code(byte_t c)
690 {
691   for ( int i = 0; ASDCP::MXF::RGBALayoutTable[i].code != 0; ++i )
692     {
693       if ( ASDCP::MXF::RGBALayoutTable[i].code == c )
694         {
695           return ASDCP::MXF::RGBALayoutTable[i].symbol;
696         }
697     }
698
699   return '_';
700 }
701
702 //
703 const char*
704 ASDCP::MXF::RGBALayout::EncodeString(char* buf, ui32_t buf_len) const
705 {
706   std::string tmp_str;
707   char tmp_buf[64];
708
709   for ( int i = 0; i < RGBAValueLength && m_value[i] != 0; i += 2 )
710     {
711       snprintf(tmp_buf, 64, "%c(%d)", get_char_for_code(m_value[i]), m_value[i+1]);
712
713       if ( ! tmp_str.empty() )
714         {
715           tmp_str += " ";
716         }
717
718       tmp_str += tmp_buf;
719     }
720
721   assert(tmp_str.size() < buf_len);
722   strncpy(buf, tmp_str.c_str(), tmp_str.size());
723   return buf;
724 }
725
726
727 //----------------------------------------------------------------------------------------------------
728 //
729
730 ASDCP::MXF::Raw::Raw()
731 {
732   Capacity(256);
733 }
734
735 ASDCP::MXF::Raw::~Raw()
736 {
737 }
738
739 //
740 bool
741 ASDCP::MXF::Raw::Unarchive(Kumu::MemIOReader* Reader)
742 {
743   ui32_t payload_size = Reader->Remainder();
744   if ( payload_size == 0 ) return false;
745   if ( KM_FAILURE(Capacity(payload_size)) ) return false;
746
747   memcpy(Data(), Reader->CurrentData(), payload_size);
748   Length(payload_size);
749   return true;
750 }
751
752 //
753 bool
754 ASDCP::MXF::Raw::Archive(Kumu::MemIOWriter* Writer) const
755 {
756   return Writer->WriteRaw(RoData(), Length());
757 }
758
759 //
760 const char*
761 ASDCP::MXF::Raw::EncodeString(char* str_buf, ui32_t buf_len) const
762 {
763   *str_buf = 0;
764   Kumu::bin2hex(RoData(), Length(), str_buf, buf_len);
765   return str_buf;
766 }
767
768 //
769 // end MXFTypes.cpp
770 //