version roll
[asdcplib.git] / src / Dict.cpp
1 /*
2 Copyright (c) 2006-2016, 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    Dict.cpp
28   \version $Id$
29   \brief   MXF dictionary
30 */
31
32
33 #include "KM_mutex.h"
34 #include "KM_log.h"
35 #include "KLV.h"
36 #include "MDD.cpp"
37
38 //------------------------------------------------------------------------------------------
39
40 // The composite dict is the union of the SMPTE and Interop dicts
41 //
42 static ASDCP::Dictionary s_CompositeDict;
43 static Kumu::Mutex s_CompositeDictLock;
44 static bool s_CompositeDictInit = false;
45
46 //
47 const ASDCP::Dictionary&
48 ASDCP::DefaultCompositeDict()
49 {
50   if ( ! s_CompositeDictInit )
51     {
52       Kumu::AutoMutex AL(s_CompositeDictLock);
53
54       if ( ! s_CompositeDictInit )
55         {
56           s_CompositeDict.Init();
57           s_CompositeDictInit = true;
58         }
59     }
60
61   return s_CompositeDict;
62 }
63
64 //
65 //
66 static ASDCP::Dictionary s_InteropDict;
67 static Kumu::Mutex s_InteropDictLock;
68 static bool s_InteropDictInit = false;
69
70 //
71 const ASDCP::Dictionary&
72 ASDCP::DefaultInteropDict()
73 {
74   if ( ! s_InteropDictInit )
75     {
76       Kumu::AutoMutex AL(s_InteropDictLock);
77
78       if ( ! s_InteropDictInit )
79         {
80           s_InteropDict.Init();
81
82           s_InteropDict.DeleteEntry(MDD_MXFInterop_OPAtom);
83           s_InteropDict.DeleteEntry(MDD_MXFInterop_CryptEssence);
84           s_InteropDict.DeleteEntry(MDD_MXFInterop_GenericDescriptor_SubDescriptors);
85
86           s_InteropDict.AddEntry(s_MDD_Table[MDD_MXFInterop_OPAtom], MDD_OPAtom);
87           s_InteropDict.AddEntry(s_MDD_Table[MDD_MXFInterop_CryptEssence], MDD_CryptEssence);
88           s_InteropDict.AddEntry(s_MDD_Table[MDD_MXFInterop_GenericDescriptor_SubDescriptors],
89                                      MDD_GenericDescriptor_SubDescriptors);
90
91           s_InteropDictInit = true;
92         }
93     }
94
95   return s_InteropDict;
96 }
97
98 //
99 //
100 static ASDCP::Dictionary s_SMPTEDict;
101 static Kumu::Mutex s_SMPTEDictLock;
102 static bool s_SMPTEDictInit = false;
103
104 //
105 const ASDCP::Dictionary&
106 ASDCP::DefaultSMPTEDict()
107 {
108   if ( ! s_SMPTEDictInit )
109     {
110       Kumu::AutoMutex AL(s_SMPTEDictLock);
111
112       if ( ! s_SMPTEDictInit )
113         {
114           s_SMPTEDict.Init();
115
116           s_SMPTEDict.DeleteEntry(MDD_MXFInterop_OPAtom);
117           s_SMPTEDict.DeleteEntry(MDD_MXFInterop_CryptEssence);
118           s_SMPTEDict.DeleteEntry(MDD_MXFInterop_GenericDescriptor_SubDescriptors);
119
120           s_SMPTEDictInit = true;
121         }
122     }
123
124   return s_SMPTEDict;
125 }
126
127 //
128 const ASDCP::MDDEntry&
129 ASDCP::MXFInterop_OPAtom_Entry() {
130   return s_MDD_Table[MDD_MXFInterop_OPAtom];
131 }
132
133 //
134 const ASDCP::MDDEntry&
135 ASDCP::SMPTE_390_OPAtom_Entry() {
136   return s_MDD_Table[MDD_OPAtom];
137 }
138
139
140 //------------------------------------------------------------------------------------------
141 //
142
143 ASDCP::Dictionary::Dictionary() {}
144 ASDCP::Dictionary::~Dictionary() {}
145
146 //
147 void
148 ASDCP::Dictionary::Init()
149 {
150   m_md_lookup.clear();
151   memset(m_MDD_Table, 0, sizeof(m_MDD_Table));
152
153   for ( ui32_t x = 0; x < (ui32_t)ASDCP::MDD_Max; ++x )
154     {
155       if ( x == MDD_PartitionMetadata_IndexSID_DEPRECATED  // 30
156            || x == MDD_PartitionMetadata_BodySID_DEPRECATED  // 32
157            || x == MDD_PartitionMetadata_OperationalPattern_DEPRECATED  // 33
158            || x == MDD_PartitionMetadata_EssenceContainers_DEPRECATED  // 34
159            || x == MDD_IndexTableSegmentBase_IndexSID_DEPRECATED  // 56
160            || x == MDD_IndexTableSegmentBase_BodySID_DEPRECATED  // 57
161            || x == MDD_PartitionArray_RandomIndexMetadata_BodySID_DEPRECATED  // 73
162            || x == MDD_Preface_OperationalPattern_DEPRECATED  // 84
163            || x == MDD_Preface_EssenceContainers_DEPRECATED  // 85
164            || x == MDD_EssenceContainerData_IndexSID_DEPRECATED  // 103
165            || x == MDD_EssenceContainerData_BodySID_DEPRECATED  // 104
166            || x == MDD_TimedTextResourceSubDescriptor_EssenceStreamID_DEPRECATED // 264
167            || x == MDD_DMSegment_DataDefinition_DEPRECATED // 266
168            || x == MDD_DMSegment_Duration_DEPRECATED // 267
169            )
170         continue;
171
172       AddEntry(s_MDD_Table[x], x);
173     }
174 }
175
176 //
177 bool
178 ASDCP::Dictionary::AddEntry(const MDDEntry& Entry, ui32_t index)
179 {
180   if ( index >= (ui32_t)MDD_Max )
181     {
182       Kumu::DefaultLogSink().Warn("UL Dictionary: index exceeds maximum: %d\n", index);
183       return false;
184     }
185
186   bool result = true;
187   // is this index already there?
188   std::map<ui32_t, ASDCP::UL>::iterator rii = m_md_rev_lookup.find(index);
189
190   if ( rii != m_md_rev_lookup.end() )
191     {
192       DeleteEntry(index);
193       result = false;
194     }
195
196   UL TmpUL(Entry.ul);
197
198 #define MDD_AUTHORING_MODE
199 #ifdef MDD_AUTHORING_MODE
200   char buf[64];
201   std::map<ASDCP::UL, ui32_t>::iterator ii = m_md_lookup.find(TmpUL);
202   if ( ii != m_md_lookup.end() )
203     {
204       fprintf(stderr, "DUPE! %s (%02x, %02x) %s | (%02x, %02x) %s\n",
205               TmpUL.EncodeString(buf, 64),
206               m_MDD_Table[ii->second].tag.a, m_MDD_Table[ii->second].tag.b,
207               m_MDD_Table[ii->second].name,
208               Entry.tag.a, Entry.tag.b, Entry.name);
209     }
210 #endif
211
212   m_md_lookup.insert(std::map<UL, ui32_t>::value_type(TmpUL, index));
213   m_md_rev_lookup.insert(std::map<ui32_t, UL>::value_type(index, TmpUL));
214   m_md_sym_lookup.insert(std::map<std::string, ui32_t>::value_type(Entry.name, index));
215   m_MDD_Table[index] = Entry;
216
217   return result;
218 }
219
220 //
221 bool
222 ASDCP::Dictionary::DeleteEntry(ui32_t index)
223 {
224   std::map<ui32_t, ASDCP::UL>::iterator rii = m_md_rev_lookup.find(index);
225   if ( rii != m_md_rev_lookup.end() )
226     {
227       std::map<ASDCP::UL, ui32_t>::iterator ii = m_md_lookup.find(rii->second);
228       assert(ii != m_md_lookup.end());
229
230       MDDEntry NilEntry;
231       memset(&NilEntry, 0, sizeof(NilEntry));
232
233       m_md_lookup.erase(ii);
234       m_md_rev_lookup.erase(rii);
235       m_MDD_Table[index] = NilEntry;
236       return true;
237     }
238
239   return false;
240 }
241
242 //
243 const ASDCP::MDDEntry&
244 ASDCP::Dictionary::Type(MDD_t type_id) const
245 {
246   assert(m_MDD_Table[0].name[0]);
247   std::map<ui32_t, ASDCP::UL>::const_iterator rii = m_md_rev_lookup.find(type_id);
248
249   if ( rii == m_md_rev_lookup.end() )
250     Kumu::DefaultLogSink().Warn("UL Dictionary: unknown UL type_id: %d\n", type_id);
251
252   return m_MDD_Table[type_id];
253 }
254
255 //
256 const ASDCP::MDDEntry*
257 ASDCP::Dictionary::FindULAnyVersion(const byte_t* ul_buf) const
258 {
259   assert(m_MDD_Table[0].name[0]);
260   byte_t search_ul[SMPTE_UL_LENGTH];
261   memcpy(search_ul, ul_buf, SMPTE_UL_LENGTH);
262   memset(search_ul+7, 0, SMPTE_UL_LENGTH-7);
263
264   UL target(ul_buf);
265   const ASDCP::MDDEntry *found_entry = 0;
266
267   std::map<UL, ui32_t>::const_iterator lower = m_md_lookup.lower_bound(UL(search_ul));
268
269   for ( ; lower != m_md_lookup.end(); ++lower )
270     {
271       if ( lower->first.MatchExact(target) )
272         {
273           found_entry = &m_MDD_Table[lower->second];
274           break;
275         }
276       else if ( found_entry == 0 && lower->first.MatchIgnoreStream(target) )
277         {
278           found_entry = &m_MDD_Table[lower->second];
279         }
280       else if ( found_entry != 0 && ! lower->first.MatchIgnoreStream(target) )
281         {
282           break;
283         }
284     }
285
286   if ( found_entry == 0 )
287     {
288       char buf[64];
289       Kumu::DefaultLogSink().Warn("UL Dictionary: unknown UL: %s\n", target.EncodeString(buf, 64));
290     }
291
292   return found_entry;
293 }
294
295 //
296 const ASDCP::MDDEntry*
297 ASDCP::Dictionary::FindULExact(const byte_t* ul_buf) const
298 {
299   assert(m_MDD_Table[0].name[0]);
300   std::map<UL, ui32_t>::const_iterator i = m_md_lookup.find(UL(ul_buf));
301   
302   if ( i == m_md_lookup.end() )
303     {
304       char buf[64];
305       UL tmp_ul(ul_buf);
306       Kumu::DefaultLogSink().Warn("UL Dictionary: unknown UL: %s\n", tmp_ul.EncodeString(buf, 64));
307       return 0;
308     }
309
310   return &m_MDD_Table[i->second];
311 }
312
313 //
314 const ASDCP::MDDEntry*
315 ASDCP::Dictionary::FindSymbol(const std::string& str) const
316 {
317   assert(m_MDD_Table[0].name[0]);
318   std::map<std::string, ui32_t>::const_iterator i = m_md_sym_lookup.find(str);
319   
320   if ( i == m_md_sym_lookup.end() )
321     {
322       Kumu::DefaultLogSink().Warn("UL Dictionary: unknown symbol: %s\n", str.c_str());
323       return 0;
324     }
325
326   return &m_MDD_Table[i->second];
327 }
328
329 //
330 void
331 ASDCP::Dictionary::Dump(FILE* stream) const
332 {
333   if ( stream == 0 )
334     stream = stderr;
335
336   MDD_t di = (MDD_t)0;
337   char     str_buf[64];
338
339   while ( di < MDD_Max )
340     {
341       if ( m_MDD_Table[di].name != 0 )
342         {
343           UL TmpUL(m_MDD_Table[di].ul);
344           fprintf(stream, "%s: %s\n", TmpUL.EncodeString(str_buf, 64), m_MDD_Table[di].name);
345         }
346
347       di = (MDD_t)(di + 1);
348     }
349 }
350
351 //
352 // end Dict.cpp
353 //