harder than it looks
[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 //
129
130 ASDCP::Dictionary::Dictionary() {}
131 ASDCP::Dictionary::~Dictionary() {}
132
133 //
134 void
135 ASDCP::Dictionary::Init()
136 {
137   m_md_lookup.clear();
138   memset(m_MDD_Table, 0, sizeof(m_MDD_Table));
139
140   for ( ui32_t x = 0; x < (ui32_t)ASDCP::MDD_Max; x++ )
141     {
142       if ( x == MDD_PartitionMetadata_IndexSID_DEPRECATED  // 30
143            || x == MDD_PartitionMetadata_BodySID_DEPRECATED  // 32
144            || x == MDD_PartitionMetadata_EssenceContainers_DEPRECATED  // 34
145            || x == MDD_IndexTableSegmentBase_IndexSID_DEPRECATED  // 56
146            || x == MDD_IndexTableSegmentBase_BodySID_DEPRECATED  // 57
147            || x == MDD_PartitionArray_RandomIndexMetadata_BodySID_DEPRECATED  // 73
148            || x == MDD_Preface_EssenceContainers_DEPRECATED  // 85
149            || x == MDD_EssenceContainerData_IndexSID_DEPRECATED  // 103
150            || x == MDD_EssenceContainerData_BodySID_DEPRECATED  // 104
151            || x == MDD_DMSegment_DataDefinition_DEPRECATED // 266
152            || x == MDD_DMSegment_Duration_DEPRECATED // 267
153            || x == MDD_PartitionMetadata_OperationalPattern_DEPRECATED  // 33
154            || x == MDD_Preface_OperationalPattern_DEPRECATED  // 84
155            || x == MDD_TimedTextResourceSubDescriptor_EssenceStreamID_DEPRECATED // 264
156            )
157         continue;
158
159       AddEntry(s_MDD_Table[x], x);
160     }
161 }
162
163 //
164 bool
165 ASDCP::Dictionary::AddEntry(const MDDEntry& Entry, ui32_t index)
166 {
167   bool result = true;
168   // is this index already there?
169   std::map<ui32_t, ASDCP::UL>::iterator rii = m_md_rev_lookup.find(index);
170
171   if ( rii != m_md_rev_lookup.end() )
172     {
173       DeleteEntry(index);
174       result = false;
175     }
176
177 #ifdef MDD_AUTHORING_MODE
178   char buf[64];
179   UL TmpUL(Entry.ul);
180   std::map<ASDCP::UL, ui32_t>::iterator ii = m_md_lookup.find(TmpUL);
181   if ( ii != m_md_lookup.end() )
182     {
183       fprintf(stderr, "DUPE! %s (%02x, %02x) %s | (%02x, %02x) %s\n",
184               TmpUL.EncodeString(buf, 64),
185               m_MDD_Table[ii->second].tag.a, m_MDD_Table[ii->second].tag.b,
186               m_MDD_Table[ii->second].name,
187               Entry.tag.a, Entry.tag.b, Entry.name);
188     }
189 #endif
190
191   m_md_lookup.insert(std::map<UL, ui32_t>::value_type(TmpUL, index));
192   m_md_rev_lookup.insert(std::map<ui32_t, UL>::value_type(index, TmpUL));
193   m_MDD_Table[index] = Entry;
194
195   return result;
196 }
197
198 //
199 bool
200 ASDCP::Dictionary::DeleteEntry(ui32_t index)
201 {
202   std::map<ui32_t, ASDCP::UL>::iterator rii = m_md_rev_lookup.find(index);
203   if ( rii != m_md_rev_lookup.end() )
204     {
205       std::map<ASDCP::UL, ui32_t>::iterator ii = m_md_lookup.find(rii->second);
206       assert(ii != m_md_lookup.end());
207
208       MDDEntry NilEntry;
209       memset(&NilEntry, 0, sizeof(NilEntry));
210
211       m_md_lookup.erase(ii);
212       m_md_rev_lookup.erase(rii);
213       m_MDD_Table[index] = NilEntry;
214       return true;
215     }
216
217   return false;
218 }
219
220 //
221 const ASDCP::MDDEntry&
222 ASDCP::Dictionary::Type(MDD_t type_id) const
223 {
224   assert(m_MDD_Table[0].name[0]);
225   std::map<ui32_t, ASDCP::UL>::const_iterator rii = m_md_rev_lookup.find(type_id);
226
227   if ( rii == m_md_rev_lookup.end() )
228     Kumu::DefaultLogSink().Warn("Unknown UL type_id: %d\n", type_id);
229
230   return m_MDD_Table[type_id];
231 }
232
233 //
234 const ASDCP::MDDEntry*
235 ASDCP::Dictionary::FindUL(const byte_t* ul_buf) const
236 {
237   assert(m_MDD_Table[0].name[0]);
238   std::map<UL, ui32_t>::const_iterator i = m_md_lookup.find(UL(ul_buf));
239   
240   if ( i == m_md_lookup.end() )
241     {
242       byte_t tmp_ul[SMPTE_UL_LENGTH];
243       memcpy(tmp_ul, ul_buf, SMPTE_UL_LENGTH);
244       tmp_ul[SMPTE_UL_LENGTH-1] = 0;
245
246       i = m_md_lookup.find(UL(tmp_ul));
247
248       if ( i == m_md_lookup.end() )
249         {
250           char buf[64];
251           UL TmpUL(ul_buf);
252           Kumu::DefaultLogSink().Warn("Unknown UL: %s\n", TmpUL.EncodeString(buf, 64));
253           return 0;
254         }
255     }
256
257   return &m_MDD_Table[(*i).second];
258 }
259
260 //
261 void
262 ASDCP::Dictionary::Dump(FILE* stream) const
263 {
264   if ( stream == 0 )
265     stream = stderr;
266
267   MDD_t di = (MDD_t)0;
268   char     str_buf[64];
269
270   while ( di < MDD_Max )
271     {
272       if ( m_MDD_Table[di].name != 0 )
273         {
274           UL TmpUL(m_MDD_Table[di].ul);
275           fprintf(stream, "%s: %s\n", TmpUL.EncodeString(str_buf, 64), m_MDD_Table[di].name);
276         }
277
278       di = (MDD_t)(di + 1);
279     }
280 }
281
282 //
283 // end Dict.cpp
284 //