UL dict final
[asdcplib.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$
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_EssenceContainers_DEPRECATED  // 34
158            || x == MDD_IndexTableSegmentBase_IndexSID_DEPRECATED  // 56
159            || x == MDD_IndexTableSegmentBase_BodySID_DEPRECATED  // 57
160            || x == MDD_PartitionArray_RandomIndexMetadata_BodySID_DEPRECATED  // 73
161            || x == MDD_Preface_EssenceContainers_DEPRECATED  // 85
162            || x == MDD_EssenceContainerData_IndexSID_DEPRECATED  // 103
163            || x == MDD_EssenceContainerData_BodySID_DEPRECATED  // 104
164            || x == MDD_DMSegment_DataDefinition_DEPRECATED // 266
165            || x == MDD_DMSegment_Duration_DEPRECATED // 267
166            || x == MDD_PartitionMetadata_OperationalPattern_DEPRECATED  // 33
167            || x == MDD_Preface_OperationalPattern_DEPRECATED  // 84
168            || x == MDD_TimedTextResourceSubDescriptor_EssenceStreamID_DEPRECATED // 264
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_MDD_Table[index] = Entry;
214
215   return result;
216 }
217
218 //
219 bool
220 ASDCP::Dictionary::DeleteEntry(ui32_t index)
221 {
222   std::map<ui32_t, ASDCP::UL>::iterator rii = m_md_rev_lookup.find(index);
223   if ( rii != m_md_rev_lookup.end() )
224     {
225       std::map<ASDCP::UL, ui32_t>::iterator ii = m_md_lookup.find(rii->second);
226       assert(ii != m_md_lookup.end());
227
228       MDDEntry NilEntry;
229       memset(&NilEntry, 0, sizeof(NilEntry));
230
231       m_md_lookup.erase(ii);
232       m_md_rev_lookup.erase(rii);
233       m_MDD_Table[index] = NilEntry;
234       return true;
235     }
236
237   return false;
238 }
239
240 //
241 const ASDCP::MDDEntry&
242 ASDCP::Dictionary::Type(MDD_t type_id) const
243 {
244   assert(m_MDD_Table[0].name[0]);
245   std::map<ui32_t, ASDCP::UL>::const_iterator rii = m_md_rev_lookup.find(type_id);
246
247   if ( rii == m_md_rev_lookup.end() )
248     Kumu::DefaultLogSink().Warn("UL Dictionary: unknown UL type_id: %d\n", type_id);
249
250   return m_MDD_Table[type_id];
251 }
252
253 //
254 const ASDCP::MDDEntry*
255 ASDCP::Dictionary::FindUL(const byte_t* ul_buf) const
256 {
257   assert(m_MDD_Table[0].name[0]);
258   std::map<UL, ui32_t>::const_iterator i = m_md_lookup.find(UL(ul_buf));
259   
260   if ( i == m_md_lookup.end() )
261     {
262       byte_t tmp_ul[SMPTE_UL_LENGTH];
263       memcpy(tmp_ul, ul_buf, SMPTE_UL_LENGTH);
264       tmp_ul[SMPTE_UL_LENGTH-1] = 0;
265
266       i = m_md_lookup.find(UL(tmp_ul));
267
268       if ( i == m_md_lookup.end() )
269         {
270           char buf[64];
271           UL TmpUL(ul_buf);
272           Kumu::DefaultLogSink().Warn("UL Dictionary: unknown UL: %s\n", TmpUL.EncodeString(buf, 64));
273           return 0;
274         }
275     }
276
277   return &m_MDD_Table[(*i).second];
278 }
279
280 //
281 void
282 ASDCP::Dictionary::Dump(FILE* stream) const
283 {
284   if ( stream == 0 )
285     stream = stderr;
286
287   MDD_t di = (MDD_t)0;
288   char     str_buf[64];
289
290   while ( di < MDD_Max )
291     {
292       if ( m_MDD_Table[di].name != 0 )
293         {
294           UL TmpUL(m_MDD_Table[di].ul);
295           fprintf(stream, "%s: %s\n", TmpUL.EncodeString(str_buf, 64), m_MDD_Table[di].name);
296         }
297
298       di = (MDD_t)(di + 1);
299     }
300 }
301
302 //
303 // end Dict.cpp
304 //