2.5.11.
[asdcplib-cth.git] / src / Dict.cpp
1 /*
2 Copyright (c) 2006-2009, 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: Dict.cpp,v 1.16 2013/06/07 00:41:00 jhurst Exp $
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 #ifdef MDD_AUTHORING_MODE
199   char buf[64];
200   std::map<ASDCP::UL, ui32_t>::iterator ii = m_md_lookup.find(TmpUL);
201   if ( ii != m_md_lookup.end() )
202     {
203       fprintf(stderr, "DUPE! %s (%02x, %02x) %s | (%02x, %02x) %s\n",
204               TmpUL.EncodeString(buf, 64),
205               m_MDD_Table[ii->second].tag.a, m_MDD_Table[ii->second].tag.b,
206               m_MDD_Table[ii->second].name,
207               Entry.tag.a, Entry.tag.b, Entry.name);
208     }
209 #endif
210
211   m_md_lookup.insert(std::map<UL, ui32_t>::value_type(TmpUL, index));
212   m_md_rev_lookup.insert(std::map<ui32_t, UL>::value_type(index, TmpUL));
213   m_md_sym_lookup.insert(std::map<std::string, ui32_t>::value_type(Entry.name, index));
214   m_MDD_Table[index] = Entry;
215
216   return result;
217 }
218
219 //
220 bool
221 ASDCP::Dictionary::DeleteEntry(ui32_t index)
222 {
223   std::map<ui32_t, ASDCP::UL>::iterator rii = m_md_rev_lookup.find(index);
224   if ( rii != m_md_rev_lookup.end() )
225     {
226       std::map<ASDCP::UL, ui32_t>::iterator ii = m_md_lookup.find(rii->second);
227       assert(ii != m_md_lookup.end());
228
229       MDDEntry NilEntry;
230       memset(&NilEntry, 0, sizeof(NilEntry));
231
232       m_md_lookup.erase(ii);
233       m_md_rev_lookup.erase(rii);
234       m_MDD_Table[index] = NilEntry;
235       return true;
236     }
237
238   return false;
239 }
240
241 //
242 const ASDCP::MDDEntry&
243 ASDCP::Dictionary::Type(MDD_t type_id) const
244 {
245   assert(m_MDD_Table[0].name[0]);
246   std::map<ui32_t, ASDCP::UL>::const_iterator rii = m_md_rev_lookup.find(type_id);
247
248   if ( rii == m_md_rev_lookup.end() )
249     Kumu::DefaultLogSink().Warn("UL Dictionary: unknown UL type_id: %d\n", type_id);
250
251   return m_MDD_Table[type_id];
252 }
253
254 //
255 const ASDCP::MDDEntry*
256 ASDCP::Dictionary::FindUL(const byte_t* ul_buf) const
257 {
258   assert(m_MDD_Table[0].name[0]);
259   std::map<UL, ui32_t>::const_iterator i = m_md_lookup.find(UL(ul_buf));
260   
261   if ( i == m_md_lookup.end() )
262     {
263       byte_t tmp_ul[SMPTE_UL_LENGTH];
264       memcpy(tmp_ul, ul_buf, SMPTE_UL_LENGTH);
265       tmp_ul[SMPTE_UL_LENGTH-1] = 0;
266
267       i = m_md_lookup.find(UL(tmp_ul));
268
269       if ( i == m_md_lookup.end() )
270         {
271           char buf[64];
272           UL TmpUL(ul_buf);
273           Kumu::DefaultLogSink().Warn("UL Dictionary: unknown UL: %s\n", TmpUL.EncodeString(buf, 64));
274           return 0;
275         }
276     }
277
278   return &m_MDD_Table[i->second];
279 }
280
281 //
282 const ASDCP::MDDEntry*
283 ASDCP::Dictionary::FindSymbol(const std::string& str) const
284 {
285   assert(m_MDD_Table[0].name[0]);
286   std::map<std::string, ui32_t>::const_iterator i = m_md_sym_lookup.find(str);
287   
288   if ( i == m_md_sym_lookup.end() )
289     {
290       Kumu::DefaultLogSink().Warn("UL Dictionary: unknown symbol: %s\n", str.c_str());
291       return 0;
292     }
293
294   return &m_MDD_Table[i->second];
295 }
296
297 //
298 void
299 ASDCP::Dictionary::Dump(FILE* stream) const
300 {
301   if ( stream == 0 )
302     stream = stderr;
303
304   MDD_t di = (MDD_t)0;
305   char     str_buf[64];
306
307   while ( di < MDD_Max )
308     {
309       if ( m_MDD_Table[di].name != 0 )
310         {
311           UL TmpUL(m_MDD_Table[di].ul);
312           fprintf(stream, "%s: %s\n", TmpUL.EncodeString(str_buf, 64), m_MDD_Table[di].name);
313         }
314
315       di = (MDD_t)(di + 1);
316     }
317 }
318
319 //
320 // end Dict.cpp
321 //