Modified to enforce execution order of the predicates
[asdcplib.git] / src / Index.cpp
1 /*
2 Copyright (c) 2005-2012, 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    Index.cpp
28     \version $Id$
29     \brief   MXF index segment objects
30 */
31
32 #include "MXF.h"
33 const ui32_t kl_length = ASDCP::SMPTE_UL_LENGTH + ASDCP::MXF_BER_LENGTH;
34
35
36 //
37 ASDCP::MXF::IndexTableSegment::IndexTableSegment(const Dictionary*& d) :
38   InterchangeObject(d), m_Dict(d), RtFileOffset(0), RtEntryOffset(0),
39   IndexStartPosition(0), IndexDuration(0), EditUnitByteCount(0),
40   IndexSID(129), BodySID(1), SliceCount(0), PosTableCount(0)
41 {
42   assert(m_Dict);
43   m_UL = m_Dict->ul(MDD_IndexTableSegment);
44 }
45
46 //
47 ASDCP::MXF::IndexTableSegment::~IndexTableSegment()
48 {
49 }
50
51 //
52 void
53 ASDCP::MXF::IndexTableSegment::Copy(const IndexTableSegment& rhs)
54 {
55   InterchangeObject::Copy(rhs);
56   IndexEditRate = rhs.IndexEditRate;
57   IndexStartPosition = rhs.IndexStartPosition;
58   IndexDuration = rhs.IndexDuration;
59   EditUnitByteCount = rhs.EditUnitByteCount;
60   IndexSID = rhs.IndexSID;
61   BodySID = rhs.BodySID;
62   SliceCount = rhs.SliceCount;
63   PosTableCount = rhs.PosTableCount;
64   DeltaEntryArray = rhs.DeltaEntryArray;
65   IndexEntryArray = rhs.IndexEntryArray;
66 }
67
68 //
69 ASDCP::Result_t
70 ASDCP::MXF::IndexTableSegment::InitFromTLVSet(TLVReader& TLVSet)
71 {
72   Result_t result = InterchangeObject::InitFromTLVSet(TLVSet);
73   if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(IndexTableSegmentBase, IndexEditRate));
74   if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi64(OBJ_READ_ARGS(IndexTableSegmentBase, IndexStartPosition));
75   if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi64(OBJ_READ_ARGS(IndexTableSegmentBase, IndexDuration));
76   if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi32(OBJ_READ_ARGS(IndexTableSegmentBase, EditUnitByteCount));
77   if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi32(OBJ_READ_ARGS(IndexTableSegmentBase, IndexSID));
78   if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi32(OBJ_READ_ARGS(EssenceContainerData, BodySID));
79   if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi8(OBJ_READ_ARGS(IndexTableSegmentBase, SliceCount));
80   if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi8(OBJ_READ_ARGS(IndexTableSegmentBase, PosTableCount));
81   if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(IndexTableSegment, DeltaEntryArray));
82
83   if ( ASDCP_SUCCESS(result) )
84     {
85       bool rc = TLVSet.FindTL(m_Dict->Type(MDD_IndexTableSegment_IndexEntryArray));
86
87       if ( rc )
88         {
89           ui32_t item_count, item_size;
90           ui32_t const decoder_item_size = IndexEntryArray.ItemSize();
91
92           if ( TLVSet.ReadUi32BE(&item_count) )
93             {
94               if ( TLVSet.ReadUi32BE(&item_size) )
95                 {
96                   for ( ui32_t i = 0; i < item_count && rc; ++i )
97                     {
98                       IndexEntry tmp_item;
99                       rc = tmp_item.Unarchive(&TLVSet);
100
101                       if ( rc )
102                         {
103                           IndexEntryArray.push_back(tmp_item);
104
105                           if ( decoder_item_size < item_size )
106                             {
107                               TLVSet.SkipOffset(item_size - decoder_item_size);
108                             }
109                         }
110                     }
111                 }
112             }
113         }
114
115       result = rc ? RESULT_OK : RESULT_FALSE;
116     }
117
118   return result;
119 }
120
121 //
122 ASDCP::Result_t
123 ASDCP::MXF::IndexTableSegment::WriteToTLVSet(TLVWriter& TLVSet)
124 {
125   Result_t result = InterchangeObject::WriteToTLVSet(TLVSet);
126   if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(IndexTableSegmentBase, IndexEditRate));
127   if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi64(OBJ_WRITE_ARGS(IndexTableSegmentBase, IndexStartPosition));
128   if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi64(OBJ_WRITE_ARGS(IndexTableSegmentBase, IndexDuration));
129   if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi32(OBJ_WRITE_ARGS(IndexTableSegmentBase, EditUnitByteCount));
130   if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi32(OBJ_WRITE_ARGS(IndexTableSegmentBase, IndexSID));
131   if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi32(OBJ_WRITE_ARGS(EssenceContainerData, BodySID));
132   if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi8(OBJ_WRITE_ARGS(IndexTableSegmentBase, SliceCount));
133   if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi8(OBJ_WRITE_ARGS(IndexTableSegmentBase, PosTableCount));
134   if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(IndexTableSegment, DeltaEntryArray));
135   if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(IndexTableSegment, IndexEntryArray));
136   return result;
137 }
138
139 //
140 ASDCP::Result_t
141 ASDCP::MXF::IndexTableSegment::InitFromBuffer(const byte_t* p, ui32_t l)
142 {
143   return InterchangeObject::InitFromBuffer(p, l);
144 }
145
146 //
147 ASDCP::Result_t
148 ASDCP::MXF::IndexTableSegment::WriteToBuffer(ASDCP::FrameBuffer& Buffer)
149 {
150   return InterchangeObject::WriteToBuffer(Buffer);
151 }
152
153 //
154 void
155 ASDCP::MXF::IndexTableSegment::Dump(FILE* stream)
156 {
157   char identbuf[IdentBufferLen];
158
159   if ( stream == 0 )
160     stream = stderr;
161
162   InterchangeObject::Dump(stream);
163   fprintf(stream, "  IndexEditRate      = %s\n",  IndexEditRate.EncodeString(identbuf, IdentBufferLen));
164   fprintf(stream, "  IndexStartPosition = %s\n",  i64sz(IndexStartPosition, identbuf));
165   fprintf(stream, "  IndexDuration      = %s\n",  i64sz(IndexDuration, identbuf));
166   fprintf(stream, "  EditUnitByteCount  = %u\n",  EditUnitByteCount);
167   fprintf(stream, "  IndexSID           = %u\n",  IndexSID);
168   fprintf(stream, "  BodySID            = %u\n",  BodySID);
169   fprintf(stream, "  SliceCount         = %hhu\n", SliceCount);
170   fprintf(stream, "  PosTableCount      = %hhu\n", PosTableCount);
171
172   fprintf(stream, "  DeltaEntryArray:\n");  DeltaEntryArray.Dump(stream);
173
174   if ( IndexEntryArray.empty() )
175     {
176       fprintf(stream, "  IndexEntryArray: NO ENTRIES\n");
177     }
178   else if ( IndexEntryArray.size() < 1000 )
179     {
180       fprintf(stream, "  IndexEntryArray:\n");
181       IndexEntryArray.Dump(stream);
182     }
183   else
184     {
185       fprintf(stream, "  IndexEntryArray: %zu entries\n", IndexEntryArray.size());
186     }
187 }
188
189 //------------------------------------------------------------------------------------------
190 //
191
192 //
193 const char*
194 ASDCP::MXF::IndexTableSegment::DeltaEntry::EncodeString(char* str_buf, ui32_t buf_len) const
195 {
196   snprintf(str_buf, buf_len, "%3d %-3hhu %-3u", PosTableIndex, Slice, ElementData);
197   return str_buf;
198 }
199
200 //
201 bool
202 ASDCP::MXF::IndexTableSegment::DeltaEntry::Unarchive(Kumu::MemIOReader* Reader)
203 {
204   if ( ! Reader->ReadUi8((ui8_t*)&PosTableIndex) ) return false;
205   if ( ! Reader->ReadUi8(&Slice) ) return false;
206   if ( ! Reader->ReadUi32BE(&ElementData) ) return false;
207   return true;
208 }
209
210 //
211 bool
212 ASDCP::MXF::IndexTableSegment::DeltaEntry::Archive(Kumu::MemIOWriter* Writer) const
213 {
214   if ( ! Writer->WriteUi8((ui8_t)PosTableIndex) ) return false;
215   if ( ! Writer->WriteUi8(Slice) ) return false;
216   if ( ! Writer->WriteUi32BE(ElementData) ) return false;
217   return true;
218 }
219
220 //------------------------------------------------------------------------------------------
221 //
222
223 // Flags:
224 // Bit 7: Random Access
225 // Bit 6: Sequence Header
226 // Bit 5: forward prediction flag
227 // Bit 4: backward prediction flag 
228 //   e.g.
229 //   00== I frame (no prediction)
230 //   10== P frame(forward prediction from previous  frame)
231 //   01== B frame (backward prediction from future  frame)
232 //   11== B frame (forward & backward prediction)
233 // Bits 0-3: reserved  [RP210 Flags to indicate coding of elements in this  edit unit]
234
235 //
236 const char*
237 ASDCP::MXF::IndexTableSegment::IndexEntry::EncodeString(char* str_buf, ui32_t buf_len) const
238 {
239   char intbuf[IntBufferLen];
240   char txt_flags[6];
241
242   txt_flags[0] = ( (Flags & 0x80) != 0 ) ? 'r' : ' ';
243   txt_flags[1] = ( (Flags & 0x40) != 0 ) ? 's' : ' ';
244   txt_flags[2] = ( (Flags & 0x20) != 0 ) ? 'f' : ' ';
245   txt_flags[3] = ( (Flags & 0x10) != 0 ) ? 'b' : ' ';
246   txt_flags[4] = ( (Flags & 0x0f) == 3 ) ? 'B' : ( (Flags & 0x0f) == 2 ) ? 'P' : 'I';
247   txt_flags[5] = 0;
248
249   snprintf(str_buf, buf_len, "%3i %-3hhu %s %s",
250            TemporalOffset, KeyFrameOffset, txt_flags,
251            i64sz(StreamOffset, intbuf));
252
253   return str_buf;
254 }
255
256 //
257 bool
258 ASDCP::MXF::IndexTableSegment::IndexEntry::Unarchive(Kumu::MemIOReader* Reader)
259 {
260   if ( ! Reader->ReadUi8((ui8_t*)&TemporalOffset) ) return false;
261   if ( ! Reader->ReadUi8((ui8_t*)&KeyFrameOffset) ) return false;
262   if ( ! Reader->ReadUi8(&Flags) ) return false;
263   if ( ! Reader->ReadUi64BE(&StreamOffset) ) return false;
264   return true;
265 }
266
267 //
268 bool
269 ASDCP::MXF::IndexTableSegment::IndexEntry::Archive(Kumu::MemIOWriter* Writer) const
270 {
271   if ( ! Writer->WriteUi8((ui8_t)TemporalOffset) ) return false;
272   if ( ! Writer->WriteUi8((ui8_t)KeyFrameOffset) ) return false;
273   if ( ! Writer->WriteUi8(Flags) ) return false;
274   if ( ! Writer->WriteUi64BE(StreamOffset) ) return false;
275   return true;
276 }
277
278
279 //
280 // end Index.cpp
281 //
282