~ubuntu-branches/ubuntu/wily/mkvtoolnix/wily

« back to all changes in this revision

Viewing changes to lib/libmatroska/src/KaxBlock.cpp

  • Committer: Package Import Robot
  • Author(s): Christian Marillat
  • Date: 2015-04-26 10:36:27 UTC
  • mfrom: (1.1.29) (4.2.45 sid)
  • Revision ID: package-import@ubuntu.com-20150426103627-k53p8hrai2ynikaa
Tags: 7.8.0-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
9
9
** modify it under the terms of the GNU Lesser General Public
10
10
** License as published by the Free Software Foundation; either
11
11
** version 2.1 of the License, or (at your option) any later version.
12
 
** 
 
12
**
13
13
** This library is distributed in the hope that it will be useful,
14
14
** but WITHOUT ANY WARRANTY; without even the implied warranty of
15
15
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
16
** Lesser General Public License for more details.
17
 
** 
 
17
**
18
18
** You should have received a copy of the GNU Lesser General Public
19
19
** License along with this library; if not, write to the Free Software
20
20
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
26
26
**********************************************************************/
27
27
 
28
28
/*!
29
 
        \file
30
 
        \version \$Id: KaxBlock.cpp 1265 2007-01-14 17:20:35Z mosu $
31
 
        \author Steve Lhomme     <robux4 @ users.sf.net>
32
 
        \author Julien Coloos    <suiryc @ users.sf.net>
 
29
  \file
 
30
  \version \$Id: KaxBlock.cpp 1265 2007-01-14 17:20:35Z mosu $
 
31
  \author Steve Lhomme     <robux4 @ users.sf.net>
 
32
  \author Julien Coloos    <suiryc @ users.sf.net>
 
33
  \author Moritz Bunkus <moritz@bunkus.org>
33
34
*/
34
35
#include <cassert>
35
36
 
36
37
//#include <streams.h>
37
38
 
 
39
#include "ebml/MemReadIOCallback.h"
 
40
#include "ebml/SafeReadIOCallback.h"
38
41
#include "matroska/KaxBlock.h"
39
42
#include "matroska/KaxContexts.h"
40
43
#include "matroska/KaxBlockData.h"
45
48
 
46
49
DataBuffer * DataBuffer::Clone()
47
50
{
48
 
        binary *ClonedData = (binary *)malloc(mySize * sizeof(binary));
49
 
        assert(ClonedData != NULL);
50
 
        memcpy(ClonedData, myBuffer ,mySize );
 
51
  binary *ClonedData = (binary *)malloc(mySize * sizeof(binary));
 
52
  assert(ClonedData != NULL);
 
53
  memcpy(ClonedData, myBuffer ,mySize );
51
54
 
52
 
        SimpleDataBuffer * result = new SimpleDataBuffer(ClonedData, mySize, 0);
53
 
        result->bValidValue = bValidValue;
54
 
        return result;
 
55
  SimpleDataBuffer * result = new SimpleDataBuffer(ClonedData, mySize, 0);
 
56
  result->bValidValue = bValidValue;
 
57
  return result;
55
58
}
56
59
 
57
60
SimpleDataBuffer::SimpleDataBuffer(const SimpleDataBuffer & ToClone)
58
 
 :DataBuffer((binary *)malloc(ToClone.mySize * sizeof(binary)), ToClone.mySize, myFreeBuffer)
 
61
  :DataBuffer((binary *)malloc(ToClone.mySize * sizeof(binary)), ToClone.mySize, myFreeBuffer)
59
62
{
60
 
        assert(myBuffer != NULL);
61
 
        memcpy(myBuffer, ToClone.myBuffer ,mySize );
62
 
        bValidValue = ToClone.bValidValue;
 
63
  assert(myBuffer != NULL);
 
64
  memcpy(myBuffer, ToClone.myBuffer ,mySize );
 
65
  bValidValue = ToClone.bValidValue;
63
66
}
64
67
 
65
68
bool KaxInternalBlock::ValidateSize() const
66
69
{
67
 
        return (GetSize() >= 4); /// for the moment
 
70
  return (GetSize() >= 4); /// for the moment
68
71
}
69
72
 
70
73
KaxInternalBlock::~KaxInternalBlock()
71
74
{
72
 
        ReleaseFrames();
 
75
  ReleaseFrames();
73
76
}
74
77
 
75
78
KaxInternalBlock::KaxInternalBlock(const KaxInternalBlock & ElementToClone)
76
 
 :EbmlBinary(ElementToClone)
77
 
 ,myBuffers(ElementToClone.myBuffers.size())
78
 
 ,Timecode(ElementToClone.Timecode)
79
 
 ,LocalTimecode(ElementToClone.LocalTimecode)
80
 
 ,bLocalTimecodeUsed(ElementToClone.bLocalTimecodeUsed)
81
 
 ,TrackNumber(ElementToClone.TrackNumber)
82
 
 ,ParentCluster(ElementToClone.ParentCluster) ///< \todo not exactly
 
79
  :EbmlBinary(ElementToClone)
 
80
  ,myBuffers(ElementToClone.myBuffers.size())
 
81
  ,Timecode(ElementToClone.Timecode)
 
82
  ,LocalTimecode(ElementToClone.LocalTimecode)
 
83
  ,bLocalTimecodeUsed(ElementToClone.bLocalTimecodeUsed)
 
84
  ,TrackNumber(ElementToClone.TrackNumber)
 
85
  ,ParentCluster(ElementToClone.ParentCluster) ///< \todo not exactly
83
86
{
84
 
        // add a clone of the list
85
 
        std::vector<DataBuffer *>::const_iterator Itr = ElementToClone.myBuffers.begin();
86
 
        std::vector<DataBuffer *>::iterator myItr = myBuffers.begin();
87
 
        while (Itr != ElementToClone.myBuffers.end())
88
 
        {
89
 
                *myItr = (*Itr)->Clone();
90
 
                Itr++; myItr++;
91
 
        }
 
87
  // add a clone of the list
 
88
  std::vector<DataBuffer *>::const_iterator Itr = ElementToClone.myBuffers.begin();
 
89
  std::vector<DataBuffer *>::iterator myItr = myBuffers.begin();
 
90
  while (Itr != ElementToClone.myBuffers.end()) {
 
91
    *myItr = (*Itr)->Clone();
 
92
    Itr++; myItr++;
 
93
  }
92
94
}
93
95
 
94
96
 
95
97
KaxBlockGroup::~KaxBlockGroup()
96
98
{
97
 
//NOTE("KaxBlockGroup::~KaxBlockGroup");
 
99
  //NOTE("KaxBlockGroup::~KaxBlockGroup");
98
100
}
99
101
 
100
102
KaxBlockGroup::KaxBlockGroup(EBML_EXTRA_DEF)
101
 
 :EbmlMaster(EBML_CLASS_SEMCONTEXT(KaxBlockGroup) EBML_DEF_SEP EBML_EXTRA_CALL)
102
 
 ,ParentCluster(NULL)
103
 
 ,ParentTrack(NULL)
 
103
  :EbmlMaster(EBML_CLASS_SEMCONTEXT(KaxBlockGroup) EBML_DEF_SEP EBML_EXTRA_CALL)
 
104
  ,ParentCluster(NULL)
 
105
  ,ParentTrack(NULL)
104
106
{}
105
107
 
106
108
/*!
107
 
        \todo handle flags
108
 
        \todo hardcoded limit of the number of frames in a lace should be a parameter
109
 
        \return true if more frames can be added to this Block
 
109
  \todo handle flags
 
110
  \todo hardcoded limit of the number of frames in a lace should be a parameter
 
111
  \return true if more frames can be added to this Block
110
112
*/
111
113
bool KaxInternalBlock::AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, LacingType lacing, bool invisible)
112
114
{
113
 
        SetValueIsSet();
114
 
        if (myBuffers.size() == 0) {
115
 
                // first frame
116
 
                Timecode = timecode;
117
 
                TrackNumber = track.TrackNumber();
118
 
                mInvisible = invisible;
119
 
                mLacing = lacing;
120
 
        }
121
 
        myBuffers.push_back(&buffer);
122
 
 
123
 
        // we don't allow more than 8 frames in a Block because the overhead improvement is minimal
124
 
        if (myBuffers.size() >= 8 || lacing == LACING_NONE)
125
 
                return false;
126
 
 
127
 
        if (lacing == LACING_XIPH)
128
 
                // decide wether a new frame can be added or not
129
 
                // a frame in a lace is not efficient when the place necessary to code it in a lace is bigger 
130
 
                // than the size of a simple Block. That means more than 6 bytes (4 in struct + 2 for EBML) to code the size
131
 
                return (buffer.Size() < 6*0xFF);
132
 
        else
133
 
                return true;
 
115
  SetValueIsSet();
 
116
  if (myBuffers.size() == 0) {
 
117
    // first frame
 
118
    Timecode = timecode;
 
119
    TrackNumber = track.TrackNumber();
 
120
    mInvisible = invisible;
 
121
    mLacing = lacing;
 
122
  }
 
123
  myBuffers.push_back(&buffer);
 
124
 
 
125
  // we don't allow more than 8 frames in a Block because the overhead improvement is minimal
 
126
  if (myBuffers.size() >= 8 || lacing == LACING_NONE)
 
127
    return false;
 
128
 
 
129
  if (lacing == LACING_XIPH)
 
130
    // decide wether a new frame can be added or not
 
131
    // a frame in a lace is not efficient when the place necessary to code it in a lace is bigger
 
132
    // than the size of a simple Block. That means more than 6 bytes (4 in struct + 2 for EBML) to code the size
 
133
    return (buffer.Size() < 6*0xFF);
 
134
  else
 
135
    return true;
134
136
}
135
137
 
136
138
/*!
137
 
       \return Returns the lacing type that produces the smallest footprint.
 
139
  \return Returns the lacing type that produces the smallest footprint.
138
140
*/
139
141
LacingType KaxInternalBlock::GetBestLacingType() const {
140
 
        int XiphLacingSize, EbmlLacingSize, i;
141
 
        bool SameSize = true;
142
 
 
143
 
        if (myBuffers.size() <= 1)
144
 
                return LACING_NONE;
145
 
 
146
 
        XiphLacingSize = 1; // Number of laces is stored in 1 byte.
147
 
        EbmlLacingSize = 1;
148
 
        for (i = 0; i < (int)myBuffers.size() - 1; i++) {
149
 
                if (myBuffers[i]->Size() != myBuffers[i + 1]->Size())
150
 
                        SameSize = false;
151
 
                XiphLacingSize += myBuffers[i]->Size() / 255 + 1;
152
 
        }
153
 
        EbmlLacingSize += CodedSizeLength(myBuffers[0]->Size(), 0, IsFiniteSize());
154
 
        for (i = 1; i < (int)myBuffers.size() - 1; i++)
155
 
                EbmlLacingSize += CodedSizeLengthSigned(int64(myBuffers[i]->Size()) - int64(myBuffers[i - 1]->Size()), 0);
156
 
        if (SameSize)
157
 
                return LACING_FIXED;
158
 
        else if (XiphLacingSize < EbmlLacingSize)
159
 
                return LACING_XIPH;
160
 
        else
161
 
                return LACING_EBML;
 
142
  int XiphLacingSize, EbmlLacingSize, i;
 
143
  bool SameSize = true;
 
144
 
 
145
  if (myBuffers.size() <= 1)
 
146
    return LACING_NONE;
 
147
 
 
148
  XiphLacingSize = 1; // Number of laces is stored in 1 byte.
 
149
  EbmlLacingSize = 1;
 
150
  for (i = 0; i < (int)myBuffers.size() - 1; i++) {
 
151
    if (myBuffers[i]->Size() != myBuffers[i + 1]->Size())
 
152
      SameSize = false;
 
153
    XiphLacingSize += myBuffers[i]->Size() / 255 + 1;
 
154
  }
 
155
  EbmlLacingSize += CodedSizeLength(myBuffers[0]->Size(), 0, IsFiniteSize());
 
156
  for (i = 1; i < (int)myBuffers.size() - 1; i++)
 
157
    EbmlLacingSize += CodedSizeLengthSigned(int64(myBuffers[i]->Size()) - int64(myBuffers[i - 1]->Size()), 0);
 
158
  if (SameSize)
 
159
    return LACING_FIXED;
 
160
  else if (XiphLacingSize < EbmlLacingSize)
 
161
    return LACING_XIPH;
 
162
  else
 
163
    return LACING_EBML;
162
164
}
163
165
 
164
166
filepos_t KaxInternalBlock::UpdateSize(bool /* bSaveDefault */, bool /* bForceRender */)
165
167
{
166
 
        LacingType LacingHere;
167
 
    assert(EbmlBinary::GetBuffer() == NULL); // Data is not used for KaxInternalBlock
168
 
        assert(TrackNumber < 0x4000); // no more allowed for the moment
169
 
        unsigned int i;
170
 
 
171
 
        // compute the final size of the data
172
 
        switch (myBuffers.size()) {
173
 
                case 0:
174
 
                        SetSize_(0);
175
 
                        break;
176
 
                case 1:
177
 
                        SetSize_(4 + myBuffers[0]->Size());
178
 
                        break;
179
 
                default:
180
 
                        SetSize_(4 + 1); // 1 for the lacing head
181
 
                        if (mLacing == LACING_AUTO)
182
 
                                LacingHere = GetBestLacingType();
183
 
                        else
184
 
                                LacingHere = mLacing;
185
 
                        switch (LacingHere)
186
 
                        {
187
 
                        case LACING_XIPH:
188
 
                                for (i=0; i<myBuffers.size()-1; i++) {
189
 
                                        SetSize_(GetSize() + myBuffers[i]->Size() + (myBuffers[i]->Size() / 0xFF + 1));
190
 
                                }
191
 
                                break;
192
 
                        case LACING_EBML:
193
 
                                SetSize_(GetSize() + myBuffers[0]->Size() + CodedSizeLength(myBuffers[0]->Size(), 0, IsFiniteSize()));
194
 
                                for (i=1; i<myBuffers.size()-1; i++) {
195
 
                                        SetSize_(GetSize() + myBuffers[i]->Size() + CodedSizeLengthSigned(int64(myBuffers[i]->Size()) - int64(myBuffers[i-1]->Size()), 0));
196
 
                                }
197
 
                                break;
198
 
                        case LACING_FIXED:
199
 
                                for (i=0; i<myBuffers.size()-1; i++) {
200
 
                                        SetSize_(GetSize() + myBuffers[i]->Size());
201
 
                                }
202
 
                                break;
203
 
                        default:
204
 
                                i = 0;
205
 
                                assert(0);
206
 
                        }
207
 
                        // Size of the last frame (not in lace)
208
 
                        SetSize_(GetSize() + myBuffers[i]->Size());
209
 
                        break;
210
 
        }
211
 
 
212
 
        if (TrackNumber >= 0x80)
213
 
                SetSize_(GetSize() + 1); // the size will be coded with one more octet
214
 
 
215
 
        return GetSize();
 
168
  LacingType LacingHere;
 
169
  assert(EbmlBinary::GetBuffer() == NULL); // Data is not used for KaxInternalBlock
 
170
  assert(TrackNumber < 0x4000); // no more allowed for the moment
 
171
  unsigned int i;
 
172
 
 
173
  // compute the final size of the data
 
174
  switch (myBuffers.size()) {
 
175
    case 0:
 
176
      SetSize_(0);
 
177
      break;
 
178
    case 1:
 
179
      SetSize_(4 + myBuffers[0]->Size());
 
180
      break;
 
181
    default:
 
182
      SetSize_(4 + 1); // 1 for the lacing head
 
183
      if (mLacing == LACING_AUTO)
 
184
        LacingHere = GetBestLacingType();
 
185
      else
 
186
        LacingHere = mLacing;
 
187
      switch (LacingHere) {
 
188
        case LACING_XIPH:
 
189
          for (i=0; i<myBuffers.size()-1; i++) {
 
190
            SetSize_(GetSize() + myBuffers[i]->Size() + (myBuffers[i]->Size() / 0xFF + 1));
 
191
          }
 
192
          break;
 
193
        case LACING_EBML:
 
194
          SetSize_(GetSize() + myBuffers[0]->Size() + CodedSizeLength(myBuffers[0]->Size(), 0, IsFiniteSize()));
 
195
          for (i=1; i<myBuffers.size()-1; i++) {
 
196
            SetSize_(GetSize() + myBuffers[i]->Size() + CodedSizeLengthSigned(int64(myBuffers[i]->Size()) - int64(myBuffers[i-1]->Size()), 0));
 
197
          }
 
198
          break;
 
199
        case LACING_FIXED:
 
200
          for (i=0; i<myBuffers.size()-1; i++) {
 
201
            SetSize_(GetSize() + myBuffers[i]->Size());
 
202
          }
 
203
          break;
 
204
        default:
 
205
          i = 0;
 
206
          assert(0);
 
207
      }
 
208
      // Size of the last frame (not in lace)
 
209
      SetSize_(GetSize() + myBuffers[i]->Size());
 
210
      break;
 
211
  }
 
212
 
 
213
  if (TrackNumber >= 0x80)
 
214
    SetSize_(GetSize() + 1); // the size will be coded with one more octet
 
215
 
 
216
  return GetSize();
216
217
}
217
218
 
218
219
#if MATROSKA_VERSION >= 2
219
220
KaxBlockVirtual::KaxBlockVirtual(const KaxBlockVirtual & ElementToClone)
220
 
 :EbmlBinary(ElementToClone)
221
 
 ,Timecode(ElementToClone.Timecode)
222
 
 ,TrackNumber(ElementToClone.TrackNumber)
223
 
 ,ParentCluster(ElementToClone.ParentCluster) ///< \todo not exactly
 
221
  :EbmlBinary(ElementToClone)
 
222
  ,Timecode(ElementToClone.Timecode)
 
223
  ,TrackNumber(ElementToClone.TrackNumber)
 
224
  ,ParentCluster(ElementToClone.ParentCluster) ///< \todo not exactly
224
225
{
225
 
    SetBuffer(DataBlock,sizeof(DataBlock));
226
 
    SetValueIsSet(false);
 
226
  SetBuffer(DataBlock,sizeof(DataBlock));
 
227
  SetValueIsSet(false);
227
228
}
228
229
 
229
230
KaxBlockVirtual::KaxBlockVirtual(EBML_EXTRA_DEF)
230
 
:EBML_DEF_BINARY(KaxBlockVirtual)EBML_DEF_SEP ParentCluster(NULL)
 
231
  :EBML_DEF_BINARY(KaxBlockVirtual)EBML_DEF_SEP ParentCluster(NULL)
231
232
{
232
 
    SetBuffer(DataBlock,sizeof(DataBlock));
233
 
    SetValueIsSet(false);
 
233
  SetBuffer(DataBlock,sizeof(DataBlock));
 
234
  SetValueIsSet(false);
234
235
}
235
236
 
236
237
KaxBlockVirtual::~KaxBlockVirtual()
237
238
{
238
 
    if(GetBuffer() == DataBlock)
239
 
        SetBuffer( NULL, 0 ); 
 
239
  if(GetBuffer() == DataBlock)
 
240
    SetBuffer( NULL, 0 );
240
241
}
241
242
 
242
243
filepos_t KaxBlockVirtual::UpdateSize(bool /* bSaveDefault */, bool /* bForceRender */)
243
244
{
244
 
        assert(TrackNumber < 0x4000);
245
 
        binary *cursor = EbmlBinary::GetBuffer();
246
 
        // fill data
247
 
        if (TrackNumber < 0x80) {
248
 
        assert(GetSize() >= 4);
249
 
                *cursor++ = TrackNumber | 0x80; // set the first bit to 1 
250
 
        } else {
251
 
        assert(GetSize() >= 5);
252
 
                *cursor++ = (TrackNumber >> 8) | 0x40; // set the second bit to 1
253
 
                *cursor++ = TrackNumber & 0xFF;
254
 
        }
255
 
 
256
 
        assert(ParentCluster != NULL);
257
 
        int16 ActualTimecode = ParentCluster->GetBlockLocalTimecode(Timecode);
258
 
        big_int16 b16(ActualTimecode);
259
 
        b16.Fill(cursor);
260
 
        cursor += 2;
261
 
 
262
 
        *cursor++ = 0; // flags
263
 
 
264
 
        return GetSize();
 
245
  assert(TrackNumber < 0x4000);
 
246
  binary *cursor = EbmlBinary::GetBuffer();
 
247
  // fill data
 
248
  if (TrackNumber < 0x80) {
 
249
    assert(GetSize() >= 4);
 
250
    *cursor++ = TrackNumber | 0x80; // set the first bit to 1
 
251
  } else {
 
252
    assert(GetSize() >= 5);
 
253
    *cursor++ = (TrackNumber >> 8) | 0x40; // set the second bit to 1
 
254
    *cursor++ = TrackNumber & 0xFF;
 
255
  }
 
256
 
 
257
  assert(ParentCluster != NULL);
 
258
  int16 ActualTimecode = ParentCluster->GetBlockLocalTimecode(Timecode);
 
259
  big_int16 b16(ActualTimecode);
 
260
  b16.Fill(cursor);
 
261
  cursor += 2;
 
262
 
 
263
  *cursor++ = 0; // flags
 
264
 
 
265
  return GetSize();
265
266
}
266
267
#endif // MATROSKA_VERSION
267
268
 
268
269
/*!
269
 
        \todo more optimisation is possible (render the Block head and don't copy the buffer in memory, care should be taken with the allocation of Data)
270
 
        \todo the actual timecode to write should be retrieved from the Cluster from here
 
270
  \todo more optimisation is possible (render the Block head and don't copy the buffer in memory, care should be taken with the allocation of Data)
 
271
  \todo the actual timecode to write should be retrieved from the Cluster from here
271
272
*/
272
273
filepos_t KaxInternalBlock::RenderData(IOCallback & output, bool /* bForceRender */, bool /* bSaveDefault */)
273
274
{
274
 
        if (myBuffers.size() == 0) {
275
 
                return 0;
276
 
        } else {
277
 
                assert(TrackNumber < 0x4000);
278
 
                binary BlockHead[5], *cursor = BlockHead;
279
 
                unsigned int i;
280
 
 
281
 
                if (myBuffers.size() == 1) {
282
 
                        SetSize_(4);
283
 
                        mLacing = LACING_NONE;
284
 
                } else {
285
 
                        if (mLacing == LACING_NONE)
286
 
                                mLacing = LACING_EBML; // supposedly the best of all
287
 
                        SetSize_(4 + 1); // 1 for the lacing head (number of laced elements)
288
 
                }
289
 
                if (TrackNumber > 0x80)
290
 
                        SetSize_(GetSize() + 1);
291
 
 
292
 
                // write Block Head
293
 
                if (TrackNumber < 0x80) {
294
 
                        *cursor++ = TrackNumber | 0x80; // set the first bit to 1 
295
 
                } else {
296
 
                        *cursor++ = (TrackNumber >> 8) | 0x40; // set the second bit to 1
297
 
                        *cursor++ = TrackNumber & 0xFF;
298
 
                }
299
 
 
300
 
                assert(ParentCluster != NULL);
301
 
                int16 ActualTimecode = ParentCluster->GetBlockLocalTimecode(Timecode);
302
 
                big_int16 b16(ActualTimecode);
303
 
                b16.Fill(cursor);
304
 
                cursor += 2;
305
 
 
306
 
                *cursor = 0; // flags
307
 
 
308
 
                if (mLacing == LACING_AUTO) {
309
 
                        mLacing = GetBestLacingType();
310
 
                }
311
 
 
312
 
                // invisible flag
313
 
                if (mInvisible)
314
 
                        *cursor = 0x08;
315
 
 
316
 
                if (bIsSimple) {
317
 
                        if (bIsKeyframe)
318
 
                                *cursor |= 0x80;
319
 
                        if (bIsDiscardable)
320
 
                                *cursor |= 0x01;
321
 
                }
322
 
                
323
 
                // lacing flag
324
 
                switch (mLacing)
325
 
                {
326
 
                case LACING_XIPH:
327
 
                        *cursor++ |= 0x02;
328
 
                        break;
329
 
                case LACING_EBML:
330
 
                        *cursor++ |= 0x06;
331
 
                        break;
332
 
                case LACING_FIXED:
333
 
                        *cursor++ |= 0x04;
334
 
                        break;
335
 
                case LACING_NONE:
336
 
                        break;
337
 
            default:
338
 
                        assert(0);
339
 
                }
340
 
 
341
 
                output.writeFully(BlockHead, 4 + ((TrackNumber > 0x80) ? 1 : 0));
342
 
 
343
 
                binary tmpValue;
344
 
                switch (mLacing)
345
 
                {
346
 
                case LACING_XIPH:
347
 
                        // number of laces
348
 
                        tmpValue = myBuffers.size()-1;
349
 
                        output.writeFully(&tmpValue, 1);
350
 
 
351
 
                        // set the size of each member in the lace
352
 
                        for (i=0; i<myBuffers.size()-1; i++) {
353
 
                                tmpValue = 0xFF;
354
 
                                uint16 tmpSize = myBuffers[i]->Size();
355
 
                                while (tmpSize >= 0xFF) {
356
 
                                        output.writeFully(&tmpValue, 1);
357
 
                                        SetSize_(GetSize() + 1);
358
 
                                        tmpSize -= 0xFF;
359
 
                                }
360
 
                                tmpValue = binary(tmpSize);
361
 
                                output.writeFully(&tmpValue, 1);
362
 
                                SetSize_(GetSize() + 1);
363
 
                        }
364
 
                        break;
365
 
                case LACING_EBML:
366
 
                        // number of laces
367
 
                        tmpValue = myBuffers.size()-1;
368
 
                        output.writeFully(&tmpValue, 1);
369
 
 
370
 
                        {
371
 
                                int64 _Size;
372
 
                                int _CodedSize;
373
 
                                binary _FinalHead[8]; // 64 bits max coded size
374
 
 
375
 
                                _Size = myBuffers[0]->Size();
376
 
 
377
 
                                _CodedSize = CodedSizeLength(_Size, 0, IsFiniteSize());
378
 
 
379
 
                                // first size in the lace is not a signed
380
 
                                CodedValueLength(_Size, _CodedSize, _FinalHead);
381
 
                                output.writeFully(_FinalHead, _CodedSize);
382
 
                                SetSize_(GetSize() + _CodedSize);
383
 
 
384
 
                                // set the size of each member in the lace
385
 
                                for (i=1; i<myBuffers.size()-1; i++) {
386
 
                                        _Size = int64(myBuffers[i]->Size()) - int64(myBuffers[i-1]->Size());
387
 
                                        _CodedSize = CodedSizeLengthSigned(_Size, 0);
388
 
                                        CodedValueLengthSigned(_Size, _CodedSize, _FinalHead);
389
 
                                        output.writeFully(_FinalHead, _CodedSize);
390
 
                                        SetSize_(GetSize() + _CodedSize);
391
 
                                }
392
 
                        }
393
 
                        break;
394
 
                case LACING_FIXED:
395
 
                        // number of laces
396
 
                        tmpValue = myBuffers.size()-1;
397
 
                        output.writeFully(&tmpValue, 1);
398
 
                        break;
399
 
                case LACING_NONE:
400
 
                        break;
401
 
            default:
402
 
                        assert(0);
403
 
                }
404
 
 
405
 
                // put the data of each frame
406
 
                for (i=0; i<myBuffers.size(); i++) {
407
 
                        output.writeFully(myBuffers[i]->Buffer(), myBuffers[i]->Size());
408
 
                        SetSize_(GetSize() + myBuffers[i]->Size());
409
 
                }
410
 
        }
411
 
 
412
 
        return GetSize();
 
275
  if (myBuffers.size() == 0) {
 
276
    return 0;
 
277
  } else {
 
278
    assert(TrackNumber < 0x4000);
 
279
    binary BlockHead[5], *cursor = BlockHead;
 
280
    unsigned int i;
 
281
 
 
282
    if (myBuffers.size() == 1) {
 
283
      SetSize_(4);
 
284
      mLacing = LACING_NONE;
 
285
    } else {
 
286
      if (mLacing == LACING_NONE)
 
287
        mLacing = LACING_EBML; // supposedly the best of all
 
288
      SetSize_(4 + 1); // 1 for the lacing head (number of laced elements)
 
289
    }
 
290
    if (TrackNumber > 0x80)
 
291
      SetSize_(GetSize() + 1);
 
292
 
 
293
    // write Block Head
 
294
    if (TrackNumber < 0x80) {
 
295
      *cursor++ = TrackNumber | 0x80; // set the first bit to 1
 
296
    } else {
 
297
      *cursor++ = (TrackNumber >> 8) | 0x40; // set the second bit to 1
 
298
      *cursor++ = TrackNumber & 0xFF;
 
299
    }
 
300
 
 
301
    assert(ParentCluster != NULL);
 
302
    int16 ActualTimecode = ParentCluster->GetBlockLocalTimecode(Timecode);
 
303
    big_int16 b16(ActualTimecode);
 
304
    b16.Fill(cursor);
 
305
    cursor += 2;
 
306
 
 
307
    *cursor = 0; // flags
 
308
 
 
309
    if (mLacing == LACING_AUTO) {
 
310
      mLacing = GetBestLacingType();
 
311
    }
 
312
 
 
313
    // invisible flag
 
314
    if (mInvisible)
 
315
      *cursor = 0x08;
 
316
 
 
317
    if (bIsSimple) {
 
318
      if (bIsKeyframe)
 
319
        *cursor |= 0x80;
 
320
      if (bIsDiscardable)
 
321
        *cursor |= 0x01;
 
322
    }
 
323
 
 
324
    // lacing flag
 
325
    switch (mLacing) {
 
326
      case LACING_XIPH:
 
327
        *cursor++ |= 0x02;
 
328
        break;
 
329
      case LACING_EBML:
 
330
        *cursor++ |= 0x06;
 
331
        break;
 
332
      case LACING_FIXED:
 
333
        *cursor++ |= 0x04;
 
334
        break;
 
335
      case LACING_NONE:
 
336
        break;
 
337
      default:
 
338
        assert(0);
 
339
    }
 
340
 
 
341
    output.writeFully(BlockHead, 4 + ((TrackNumber > 0x80) ? 1 : 0));
 
342
 
 
343
    binary tmpValue;
 
344
    switch (mLacing) {
 
345
      case LACING_XIPH:
 
346
        // number of laces
 
347
        tmpValue = myBuffers.size()-1;
 
348
        output.writeFully(&tmpValue, 1);
 
349
 
 
350
        // set the size of each member in the lace
 
351
        for (i=0; i<myBuffers.size()-1; i++) {
 
352
          tmpValue = 0xFF;
 
353
          uint16 tmpSize = myBuffers[i]->Size();
 
354
          while (tmpSize >= 0xFF) {
 
355
            output.writeFully(&tmpValue, 1);
 
356
            SetSize_(GetSize() + 1);
 
357
            tmpSize -= 0xFF;
 
358
          }
 
359
          tmpValue = binary(tmpSize);
 
360
          output.writeFully(&tmpValue, 1);
 
361
          SetSize_(GetSize() + 1);
 
362
        }
 
363
        break;
 
364
      case LACING_EBML:
 
365
        // number of laces
 
366
        tmpValue = myBuffers.size()-1;
 
367
        output.writeFully(&tmpValue, 1);
 
368
        {
 
369
          int64 _Size;
 
370
          int _CodedSize;
 
371
          binary _FinalHead[8]; // 64 bits max coded size
 
372
 
 
373
          _Size = myBuffers[0]->Size();
 
374
 
 
375
          _CodedSize = CodedSizeLength(_Size, 0, IsFiniteSize());
 
376
 
 
377
          // first size in the lace is not a signed
 
378
          CodedValueLength(_Size, _CodedSize, _FinalHead);
 
379
          output.writeFully(_FinalHead, _CodedSize);
 
380
          SetSize_(GetSize() + _CodedSize);
 
381
 
 
382
          // set the size of each member in the lace
 
383
          for (i=1; i<myBuffers.size()-1; i++) {
 
384
            _Size = int64(myBuffers[i]->Size()) - int64(myBuffers[i-1]->Size());
 
385
            _CodedSize = CodedSizeLengthSigned(_Size, 0);
 
386
            CodedValueLengthSigned(_Size, _CodedSize, _FinalHead);
 
387
            output.writeFully(_FinalHead, _CodedSize);
 
388
            SetSize_(GetSize() + _CodedSize);
 
389
          }
 
390
        }
 
391
        break;
 
392
      case LACING_FIXED:
 
393
        // number of laces
 
394
        tmpValue = myBuffers.size()-1;
 
395
        output.writeFully(&tmpValue, 1);
 
396
        break;
 
397
      case LACING_NONE:
 
398
        break;
 
399
      default:
 
400
        assert(0);
 
401
    }
 
402
 
 
403
    // put the data of each frame
 
404
    for (i=0; i<myBuffers.size(); i++) {
 
405
      output.writeFully(myBuffers[i]->Buffer(), myBuffers[i]->Size());
 
406
      SetSize_(GetSize() + myBuffers[i]->Size());
 
407
    }
 
408
  }
 
409
 
 
410
  return GetSize();
413
411
}
414
412
 
415
413
uint64 KaxInternalBlock::ReadInternalHead(IOCallback & input)
416
414
{
417
 
        binary Buffer[5], *cursor = Buffer;
418
 
        uint64 Result = input.read(cursor, 4);
419
 
        if (Result != 4)
420
 
                return Result;
421
 
        
422
 
        // update internal values
423
 
        TrackNumber = *cursor++;
424
 
        if ((TrackNumber & 0x80) == 0) {
425
 
                // there is extra data
426
 
                if ((TrackNumber & 0x40) == 0) {
427
 
                        // We don't support track numbers that large !
428
 
                        return Result;
429
 
                }
430
 
                Result += input.read(&Buffer[4], 1);
431
 
                TrackNumber = (TrackNumber & 0x3F) << 8;
432
 
                TrackNumber += *cursor++;
433
 
        } else {
434
 
                TrackNumber &= 0x7F;
435
 
        }
436
 
 
437
 
    
438
 
        big_int16 b16;
439
 
        b16.Eval(cursor);
440
 
        assert(ParentCluster != NULL);
441
 
        Timecode = ParentCluster->GetBlockGlobalTimecode(int16(b16));
442
 
        bLocalTimecodeUsed = false;
443
 
        cursor += 2;
444
 
 
445
 
        return Result;
 
415
  binary Buffer[5], *cursor = Buffer;
 
416
  uint64 Result = input.read(cursor, 4);
 
417
  if (Result != 4)
 
418
    return Result;
 
419
 
 
420
  // update internal values
 
421
  TrackNumber = *cursor++;
 
422
  if ((TrackNumber & 0x80) == 0) {
 
423
    // there is extra data
 
424
    if ((TrackNumber & 0x40) == 0) {
 
425
      // We don't support track numbers that large !
 
426
      return Result;
 
427
    }
 
428
    Result += input.read(&Buffer[4], 1);
 
429
    TrackNumber = (TrackNumber & 0x3F) << 8;
 
430
    TrackNumber += *cursor++;
 
431
  } else {
 
432
    TrackNumber &= 0x7F;
 
433
  }
 
434
 
 
435
 
 
436
  big_int16 b16;
 
437
  b16.Eval(cursor);
 
438
  assert(ParentCluster != NULL);
 
439
  Timecode = ParentCluster->GetBlockGlobalTimecode(int16(b16));
 
440
  bLocalTimecodeUsed = false;
 
441
  cursor += 2;
 
442
 
 
443
  return Result;
446
444
}
447
445
 
448
446
/*!
449
 
        \todo better zero copy handling
 
447
  \todo better zero copy handling
450
448
*/
451
449
filepos_t KaxInternalBlock::ReadData(IOCallback & input, ScopeMode ReadFully)
452
450
{
453
 
        filepos_t Result;
454
 
 
455
 
        FirstFrameLocation = input.getFilePointer(); // will be updated accordingly below
456
 
 
457
 
        if (ReadFully == SCOPE_ALL_DATA)
458
 
        {
459
 
                Result = EbmlBinary::ReadData(input, ReadFully);
460
 
        binary *cursor = EbmlBinary::GetBuffer();
461
 
                uint8 BlockHeadSize = 4;
462
 
 
463
 
                // update internal values
464
 
                TrackNumber = *cursor++;
465
 
                if ((TrackNumber & 0x80) == 0) {
466
 
                        // there is extra data
467
 
                        if ((TrackNumber & 0x40) == 0) {
468
 
                                // We don't support track numbers that large !
469
 
                                return Result;
470
 
                        }
471
 
                        TrackNumber = (TrackNumber & 0x3F) << 8;
472
 
                        TrackNumber += *cursor++;
473
 
                        BlockHeadSize++;
474
 
                } else {
475
 
                        TrackNumber &= 0x7F;
476
 
                }
477
 
 
478
 
                big_int16 b16;
479
 
                b16.Eval(cursor);
480
 
                LocalTimecode = int16(b16);
481
 
                bLocalTimecodeUsed = true;
482
 
                cursor += 2;
483
 
 
484
 
                if (EbmlId(*this) == EBML_ID(KaxSimpleBlock)) {
485
 
                        bIsKeyframe = (*cursor & 0x80) != 0;
486
 
                        bIsDiscardable = (*cursor & 0x01) != 0;
487
 
                }
488
 
                mInvisible = (*cursor & 0x08) >> 3;
489
 
                mLacing = LacingType((*cursor++ & 0x06) >> 1);
490
 
 
491
 
                // put all Frames in the list
492
 
                if (mLacing == LACING_NONE) {
493
 
                        FirstFrameLocation += cursor - EbmlBinary::GetBuffer();
494
 
                        DataBuffer * soloFrame = new DataBuffer(cursor, GetSize() - BlockHeadSize);
495
 
                        myBuffers.push_back(soloFrame);
496
 
                        SizeList.resize(1);
497
 
                        SizeList[0] = GetSize() - BlockHeadSize;
498
 
                } else {
499
 
                        // read the number of frames in the lace
500
 
                        uint32 LastBufferSize = GetSize() - BlockHeadSize - 1; // 1 for number of frame
501
 
                        uint8 FrameNum = *cursor++; // number of frames in the lace - 1
502
 
                        // read the list of frame sizes
503
 
                        uint8 Index;
504
 
                        int32 FrameSize;
505
 
                        uint32 SizeRead;
506
 
                        uint64 SizeUnknown;
507
 
 
508
 
                        SizeList.resize(FrameNum + 1);
509
 
 
510
 
                        switch (mLacing)
511
 
                        {
512
 
                        case LACING_XIPH:
513
 
                                for (Index=0; Index<FrameNum; Index++) {
514
 
                                        // get the size of the frame
515
 
                                        FrameSize = 0;
516
 
                                        do {
517
 
                                                FrameSize += uint8(*cursor);
518
 
                                                LastBufferSize--;
519
 
                                        } while (*cursor++ == 0xFF);
520
 
                                        SizeList[Index] = FrameSize;
521
 
                                        LastBufferSize -= FrameSize;
522
 
                                }
523
 
                                SizeList[Index] = LastBufferSize;
524
 
                                break;
525
 
                        case LACING_EBML:
526
 
                                SizeRead = LastBufferSize;
527
 
                                FrameSize = ReadCodedSizeValue(cursor, SizeRead, SizeUnknown);
528
 
                                SizeList[0] = FrameSize;
529
 
                                cursor += SizeRead;
530
 
                                LastBufferSize -= FrameSize + SizeRead;
531
 
 
532
 
                                for (Index=1; Index<FrameNum; Index++) {
533
 
                                        // get the size of the frame
534
 
                                        SizeRead = LastBufferSize;
535
 
                                        FrameSize += ReadCodedSizeSignedValue(cursor, SizeRead, SizeUnknown);
536
 
                                        SizeList[Index] = FrameSize;
537
 
                                        cursor += SizeRead;
538
 
                                        LastBufferSize -= FrameSize + SizeRead;
539
 
                                }
540
 
                                SizeList[Index] = LastBufferSize;
541
 
                                break;
542
 
                        case LACING_FIXED:
543
 
                                for (Index=0; Index<=FrameNum; Index++) {
544
 
                                        // get the size of the frame
545
 
                                        SizeList[Index] = LastBufferSize / (FrameNum + 1);
546
 
                                }
547
 
                                break;
548
 
                        default: // other lacing not supported
549
 
                                assert(0);
550
 
                        }
551
 
 
552
 
                        FirstFrameLocation += cursor - EbmlBinary::GetBuffer();
553
 
 
554
 
                        for (Index=0; Index<=FrameNum; Index++) {
555
 
                                DataBuffer * lacedFrame = new DataBuffer(cursor, SizeList[Index]);
556
 
                                myBuffers.push_back(lacedFrame);
557
 
                                cursor += SizeList[Index];
558
 
                        }
559
 
                }
560
 
                SetValueIsSet();
561
 
        }
562
 
        else if (ReadFully == SCOPE_PARTIAL_DATA)
563
 
        {
564
 
                binary _TempHead[5];
565
 
                Result = input.read(_TempHead, 5);
566
 
                binary *cursor = _TempHead;
567
 
                binary *_tmpBuf;
568
 
                uint8 BlockHeadSize = 4;
569
 
 
570
 
                // update internal values
571
 
                TrackNumber = *cursor++;
572
 
                if ((TrackNumber & 0x80) == 0) {
573
 
                        // there is extra data
574
 
                        if ((TrackNumber & 0x40) == 0) {
575
 
                                // We don't support track numbers that large !
576
 
                                return Result;
577
 
                        }
578
 
                        TrackNumber = (TrackNumber & 0x3F) << 8;
579
 
                        TrackNumber += *cursor++;
580
 
                        BlockHeadSize++;
581
 
                } else {
582
 
                        TrackNumber &= 0x7F;
583
 
                }
584
 
 
585
 
                big_int16 b16;
586
 
                b16.Eval(cursor);
587
 
                LocalTimecode = int16(b16);
588
 
                bLocalTimecodeUsed = true;
589
 
                cursor += 2;
590
 
 
591
 
                if (EbmlId(*this) == EBML_ID(KaxSimpleBlock)) {
592
 
                        bIsKeyframe = (*cursor & 0x80) != 0;
593
 
                        bIsDiscardable = (*cursor & 0x01) != 0;
594
 
                }
595
 
                mInvisible = (*cursor & 0x08) >> 3;
596
 
                mLacing = LacingType((*cursor++ & 0x06) >> 1);
597
 
                if (cursor == &_TempHead[4])
598
 
                {
599
 
                        _TempHead[0] = _TempHead[4];
600
 
                } else {
601
 
                        Result += input.read(_TempHead, 1);
602
 
                }
603
 
 
604
 
                FirstFrameLocation += cursor - _TempHead;
605
 
 
606
 
                // put all Frames in the list
607
 
                if (mLacing != LACING_NONE) {
608
 
                        // read the number of frames in the lace
609
 
                        uint32 LastBufferSize = GetSize() - BlockHeadSize - 1; // 1 for number of frame
610
 
                        uint8 FrameNum = _TempHead[0]; // number of frames in the lace - 1
611
 
                        // read the list of frame sizes
612
 
                        uint8 Index;
613
 
                        int32 FrameSize;
614
 
                        uint32 SizeRead;
615
 
                        uint64 SizeUnknown;
616
 
 
617
 
                        SizeList.resize(FrameNum + 1);
618
 
 
619
 
                        switch (mLacing)
620
 
                        {
621
 
                        case LACING_XIPH:
622
 
                                for (Index=0; Index<FrameNum; Index++) {
623
 
                                        // get the size of the frame
624
 
                                        FrameSize = 0;
625
 
                                        do {
626
 
                                                Result += input.read(_TempHead, 1);
627
 
                                                FrameSize += uint8(_TempHead[0]);
628
 
                                                LastBufferSize--;
629
 
 
630
 
                                                FirstFrameLocation++;
631
 
                                        } while (_TempHead[0] == 0xFF);
632
 
 
633
 
                                        FirstFrameLocation++;
634
 
                                        SizeList[Index] = FrameSize;
635
 
                                        LastBufferSize -= FrameSize;
636
 
                                }
637
 
                                SizeList[Index] = LastBufferSize;
638
 
                                break;
639
 
                        case LACING_EBML:
640
 
                                SizeRead = LastBufferSize;
641
 
                                cursor = _tmpBuf = new binary[FrameNum*4]; /// \warning assume the mean size will be coded in less than 4 bytes
642
 
                                Result += input.read(cursor, FrameNum*4);
643
 
                                FrameSize = ReadCodedSizeValue(cursor, SizeRead, SizeUnknown);
644
 
                                SizeList[0] = FrameSize;
645
 
                                cursor += SizeRead;
646
 
                                LastBufferSize -= FrameSize + SizeRead;
647
 
 
648
 
                                for (Index=1; Index<FrameNum; Index++) {
649
 
                                        // get the size of the frame
650
 
                                        SizeRead = LastBufferSize;
651
 
                                        FrameSize += ReadCodedSizeSignedValue(cursor, SizeRead, SizeUnknown);
652
 
                                        SizeList[Index] = FrameSize;
653
 
                                        cursor += SizeRead;
654
 
                                        LastBufferSize -= FrameSize + SizeRead;
655
 
                                }
656
 
 
657
 
                                FirstFrameLocation += cursor - _tmpBuf;
658
 
 
659
 
                                SizeList[Index] = LastBufferSize;
660
 
                                delete [] _tmpBuf;
661
 
                                break;
662
 
                        case LACING_FIXED:
663
 
                                for (Index=0; Index<=FrameNum; Index++) {
664
 
                                        // get the size of the frame
665
 
                                        SizeList[Index] = LastBufferSize / (FrameNum + 1);
666
 
                                }
667
 
                                break;
668
 
                        default: // other lacing not supported
669
 
                                assert(0);
670
 
                        }
671
 
                } else {
672
 
                        SizeList.resize(1);
673
 
                        SizeList[0] = GetSize() - BlockHeadSize;
674
 
                }
675
 
                SetValueIsSet(false);
676
 
                Result = GetSize();
677
 
        } else {
678
 
                SetValueIsSet(false);
679
 
                Result = GetSize();
680
 
        }
681
 
 
682
 
        return Result;
 
451
  filepos_t Result;
 
452
 
 
453
  FirstFrameLocation = input.getFilePointer(); // will be updated accordingly below
 
454
 
 
455
  SetValueIsSet(false);
 
456
 
 
457
  try {
 
458
    if (ReadFully == SCOPE_ALL_DATA) {
 
459
      Result = EbmlBinary::ReadData(input, ReadFully);
 
460
      if (Result != GetSize())
 
461
        throw SafeReadIOCallback::EndOfStreamX(GetSize() - Result);
 
462
 
 
463
      binary *BufferStart = EbmlBinary::GetBuffer();
 
464
 
 
465
      SafeReadIOCallback Mem(*this);
 
466
      uint8 BlockHeadSize = 4;
 
467
 
 
468
      // update internal values
 
469
      TrackNumber = Mem.GetUInt8();
 
470
      if ((TrackNumber & 0x80) == 0) {
 
471
        // there is extra data
 
472
        if ((TrackNumber & 0x40) == 0) {
 
473
          // We don't support track numbers that large !
 
474
          throw SafeReadIOCallback::EndOfStreamX(0);
 
475
        }
 
476
        TrackNumber = (TrackNumber & 0x3F) << 8;
 
477
        TrackNumber += Mem.GetUInt8();
 
478
        BlockHeadSize++;
 
479
      } else {
 
480
        TrackNumber &= 0x7F;
 
481
      }
 
482
 
 
483
      LocalTimecode = int16(Mem.GetUInt16BE());
 
484
      bLocalTimecodeUsed = true;
 
485
 
 
486
      uint8 Flags = Mem.GetUInt8();
 
487
      if (EbmlId(*this) == EBML_ID(KaxSimpleBlock)) {
 
488
        bIsKeyframe = (Flags & 0x80) != 0;
 
489
        bIsDiscardable = (Flags & 0x01) != 0;
 
490
      }
 
491
      mInvisible = (Flags & 0x08) >> 3;
 
492
      mLacing = LacingType((Flags & 0x06) >> 1);
 
493
 
 
494
      // put all Frames in the list
 
495
      if (mLacing == LACING_NONE) {
 
496
        FirstFrameLocation += Mem.GetPosition();
 
497
        DataBuffer * soloFrame = new DataBuffer(BufferStart + Mem.GetPosition(), GetSize() - BlockHeadSize);
 
498
        myBuffers.push_back(soloFrame);
 
499
        SizeList.resize(1);
 
500
        SizeList[0] = GetSize() - BlockHeadSize;
 
501
      } else {
 
502
        // read the number of frames in the lace
 
503
        uint32 LastBufferSize = GetSize() - BlockHeadSize - 1; // 1 for number of frame
 
504
        uint8 FrameNum = Mem.GetUInt8(); // number of frames in the lace - 1
 
505
        // read the list of frame sizes
 
506
        uint8 Index;
 
507
        int32 FrameSize;
 
508
        uint32 SizeRead;
 
509
        uint64 SizeUnknown;
 
510
 
 
511
        SizeList.resize(FrameNum + 1);
 
512
 
 
513
        switch (mLacing) {
 
514
          case LACING_XIPH:
 
515
            for (Index=0; Index<FrameNum; Index++) {
 
516
              // get the size of the frame
 
517
              FrameSize = 0;
 
518
              uint8 Value;
 
519
              do {
 
520
                Value = Mem.GetUInt8();
 
521
                FrameSize += Value;
 
522
                LastBufferSize--;
 
523
              } while (Value == 0xFF);
 
524
              SizeList[Index] = FrameSize;
 
525
              LastBufferSize -= FrameSize;
 
526
            }
 
527
            SizeList[Index] = LastBufferSize;
 
528
            break;
 
529
          case LACING_EBML:
 
530
            SizeRead = LastBufferSize;
 
531
            FrameSize = ReadCodedSizeValue(BufferStart + Mem.GetPosition(), SizeRead, SizeUnknown);
 
532
            SizeList[0] = FrameSize;
 
533
            Mem.Skip(SizeRead);
 
534
            LastBufferSize -= FrameSize + SizeRead;
 
535
 
 
536
            for (Index=1; Index<FrameNum; Index++) {
 
537
              // get the size of the frame
 
538
              SizeRead = LastBufferSize;
 
539
              FrameSize += ReadCodedSizeSignedValue(BufferStart + Mem.GetPosition(), SizeRead, SizeUnknown);
 
540
              SizeList[Index] = FrameSize;
 
541
              Mem.Skip(SizeRead);
 
542
              LastBufferSize -= FrameSize + SizeRead;
 
543
            }
 
544
            if (Index <= FrameNum) // Safety check if FrameNum == 0
 
545
              SizeList[Index] = LastBufferSize;
 
546
            break;
 
547
          case LACING_FIXED:
 
548
            for (Index=0; Index<=FrameNum; Index++) {
 
549
              // get the size of the frame
 
550
              SizeList[Index] = LastBufferSize / (FrameNum + 1);
 
551
            }
 
552
            break;
 
553
          default: // other lacing not supported
 
554
            assert(0);
 
555
        }
 
556
 
 
557
        FirstFrameLocation += Mem.GetPosition();
 
558
 
 
559
        for (Index=0; Index<=FrameNum; Index++) {
 
560
          DataBuffer * lacedFrame = new DataBuffer(BufferStart + Mem.GetPosition(), SizeList[Index]);
 
561
          myBuffers.push_back(lacedFrame);
 
562
          Mem.Skip(SizeList[Index]);
 
563
        }
 
564
      }
 
565
 
 
566
      binary *BufferEnd = BufferStart + GetSize();
 
567
      size_t NumFrames  = myBuffers.size();
 
568
 
 
569
      // Sanity checks for frame pointers and boundaries.
 
570
      for (size_t Index = 0; Index < NumFrames; ++Index) {
 
571
        binary *FrameStart  = myBuffers[Index]->Buffer();
 
572
        binary *FrameEnd    = FrameStart + myBuffers[Index]->Size();
 
573
        binary *ExpectedEnd = (Index + 1) < NumFrames ? myBuffers[Index + 1]->Buffer() : BufferEnd;
 
574
 
 
575
        if ((FrameStart < BufferStart) || (FrameEnd > BufferEnd) || (FrameEnd != ExpectedEnd))
 
576
          throw SafeReadIOCallback::EndOfStreamX(0);
 
577
      }
 
578
 
 
579
      SetValueIsSet();
 
580
    } else if (ReadFully == SCOPE_PARTIAL_DATA) {
 
581
      binary _TempHead[5];
 
582
      Result = input.read(_TempHead, 5);
 
583
      if (Result != 5)
 
584
        throw SafeReadIOCallback::EndOfStreamX(0);
 
585
      binary *cursor = _TempHead;
 
586
      binary *_tmpBuf;
 
587
      uint8 BlockHeadSize = 4;
 
588
 
 
589
      // update internal values
 
590
      TrackNumber = *cursor++;
 
591
      if ((TrackNumber & 0x80) == 0) {
 
592
        // there is extra data
 
593
        if ((TrackNumber & 0x40) == 0) {
 
594
          // We don't support track numbers that large !
 
595
          return Result;
 
596
        }
 
597
        TrackNumber = (TrackNumber & 0x3F) << 8;
 
598
        TrackNumber += *cursor++;
 
599
        BlockHeadSize++;
 
600
      } else {
 
601
        TrackNumber &= 0x7F;
 
602
      }
 
603
 
 
604
      big_int16 b16;
 
605
      b16.Eval(cursor);
 
606
      LocalTimecode = int16(b16);
 
607
      bLocalTimecodeUsed = true;
 
608
      cursor += 2;
 
609
 
 
610
      if (EbmlId(*this) == EBML_ID(KaxSimpleBlock)) {
 
611
        bIsKeyframe = (*cursor & 0x80) != 0;
 
612
        bIsDiscardable = (*cursor & 0x01) != 0;
 
613
      }
 
614
      mInvisible = (*cursor & 0x08) >> 3;
 
615
      mLacing = LacingType((*cursor++ & 0x06) >> 1);
 
616
      if (cursor == &_TempHead[4]) {
 
617
        _TempHead[0] = _TempHead[4];
 
618
      } else {
 
619
        Result += input.read(_TempHead, 1);
 
620
      }
 
621
 
 
622
      FirstFrameLocation += cursor - _TempHead;
 
623
 
 
624
      // put all Frames in the list
 
625
      if (mLacing != LACING_NONE) {
 
626
        // read the number of frames in the lace
 
627
        uint32 LastBufferSize = GetSize() - BlockHeadSize - 1; // 1 for number of frame
 
628
        uint8 FrameNum = _TempHead[0]; // number of frames in the lace - 1
 
629
        // read the list of frame sizes
 
630
        uint8 Index;
 
631
        int32 FrameSize;
 
632
        uint32 SizeRead;
 
633
        uint64 SizeUnknown;
 
634
 
 
635
        SizeList.resize(FrameNum + 1);
 
636
 
 
637
        switch (mLacing) {
 
638
          case LACING_XIPH:
 
639
            for (Index=0; Index<FrameNum; Index++) {
 
640
              // get the size of the frame
 
641
              FrameSize = 0;
 
642
              do {
 
643
                Result += input.read(_TempHead, 1);
 
644
                FrameSize += uint8(_TempHead[0]);
 
645
                LastBufferSize--;
 
646
 
 
647
                FirstFrameLocation++;
 
648
              } while (_TempHead[0] == 0xFF);
 
649
 
 
650
              FirstFrameLocation++;
 
651
              SizeList[Index] = FrameSize;
 
652
              LastBufferSize -= FrameSize;
 
653
            }
 
654
            SizeList[Index] = LastBufferSize;
 
655
            break;
 
656
          case LACING_EBML:
 
657
            SizeRead = LastBufferSize;
 
658
            cursor = _tmpBuf = new binary[FrameNum*4]; /// \warning assume the mean size will be coded in less than 4 bytes
 
659
            Result += input.read(cursor, FrameNum*4);
 
660
            FrameSize = ReadCodedSizeValue(cursor, SizeRead, SizeUnknown);
 
661
            SizeList[0] = FrameSize;
 
662
            cursor += SizeRead;
 
663
            LastBufferSize -= FrameSize + SizeRead;
 
664
 
 
665
            for (Index=1; Index<FrameNum; Index++) {
 
666
              // get the size of the frame
 
667
              SizeRead = LastBufferSize;
 
668
              FrameSize += ReadCodedSizeSignedValue(cursor, SizeRead, SizeUnknown);
 
669
              SizeList[Index] = FrameSize;
 
670
              cursor += SizeRead;
 
671
              LastBufferSize -= FrameSize + SizeRead;
 
672
            }
 
673
 
 
674
            FirstFrameLocation += cursor - _tmpBuf;
 
675
 
 
676
            SizeList[Index] = LastBufferSize;
 
677
            delete [] _tmpBuf;
 
678
            break;
 
679
          case LACING_FIXED:
 
680
            for (Index=0; Index<=FrameNum; Index++) {
 
681
              // get the size of the frame
 
682
              SizeList[Index] = LastBufferSize / (FrameNum + 1);
 
683
            }
 
684
            break;
 
685
          default: // other lacing not supported
 
686
            assert(0);
 
687
        }
 
688
      } else {
 
689
        SizeList.resize(1);
 
690
        SizeList[0] = GetSize() - BlockHeadSize;
 
691
      }
 
692
      SetValueIsSet(false);
 
693
      Result = GetSize();
 
694
    } else {
 
695
      SetValueIsSet(false);
 
696
      Result = GetSize();
 
697
    }
 
698
 
 
699
  } catch (SafeReadIOCallback::EndOfStreamX &) {
 
700
    SetValueIsSet(false);
 
701
 
 
702
    std::memset(EbmlBinary::GetBuffer(), 0, GetSize());
 
703
    myBuffers.clear();
 
704
    SizeList.clear();
 
705
    Timecode           = 0;
 
706
    LocalTimecode      = 0;
 
707
    TrackNumber        = 0;
 
708
    bLocalTimecodeUsed = false;
 
709
    FirstFrameLocation = 0;
 
710
 
 
711
    return 0;
 
712
  }
 
713
 
 
714
  return Result;
683
715
}
684
716
 
685
717
bool KaxBlockGroup::AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, LacingType lacing)
686
718
{
687
 
        KaxBlock & theBlock = GetChild<KaxBlock>(*this);
688
 
        assert(ParentCluster != NULL);
689
 
        theBlock.SetParent(*ParentCluster);
690
 
        ParentTrack = &track;
691
 
        return theBlock.AddFrame(track, timecode, buffer, lacing);
 
719
  KaxBlock & theBlock = GetChild<KaxBlock>(*this);
 
720
  assert(ParentCluster != NULL);
 
721
  theBlock.SetParent(*ParentCluster);
 
722
  ParentTrack = &track;
 
723
  return theBlock.AddFrame(track, timecode, buffer, lacing);
692
724
}
693
725
 
694
726
bool KaxBlockGroup::AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, const KaxBlockGroup & PastBlock, LacingType lacing)
695
727
{
696
 
//      assert(past_timecode < 0);
697
 
 
698
 
        KaxBlock & theBlock = GetChild<KaxBlock>(*this);
699
 
        assert(ParentCluster != NULL);
700
 
        theBlock.SetParent(*ParentCluster);
701
 
        ParentTrack = &track;
702
 
        bool bRes = theBlock.AddFrame(track, timecode, buffer, lacing);
703
 
 
704
 
        KaxReferenceBlock & thePastRef = GetChild<KaxReferenceBlock>(*this);
705
 
        thePastRef.SetReferencedBlock(PastBlock);
706
 
        thePastRef.SetParentBlock(*this);
707
 
 
708
 
        return bRes;
 
728
  //  assert(past_timecode < 0);
 
729
 
 
730
  KaxBlock & theBlock = GetChild<KaxBlock>(*this);
 
731
  assert(ParentCluster != NULL);
 
732
  theBlock.SetParent(*ParentCluster);
 
733
  ParentTrack = &track;
 
734
  bool bRes = theBlock.AddFrame(track, timecode, buffer, lacing);
 
735
 
 
736
  KaxReferenceBlock & thePastRef = GetChild<KaxReferenceBlock>(*this);
 
737
  thePastRef.SetReferencedBlock(PastBlock);
 
738
  thePastRef.SetParentBlock(*this);
 
739
 
 
740
  return bRes;
709
741
}
710
742
 
711
743
bool KaxBlockGroup::AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, const KaxBlockGroup & PastBlock, const KaxBlockGroup & ForwBlock, LacingType lacing)
712
744
{
713
 
//      assert(past_timecode < 0);
714
 
 
715
 
//      assert(forw_timecode > 0);
716
 
        
717
 
        KaxBlock & theBlock = GetChild<KaxBlock>(*this);
718
 
        assert(ParentCluster != NULL);
719
 
        theBlock.SetParent(*ParentCluster);
720
 
        ParentTrack = &track;
721
 
        bool bRes = theBlock.AddFrame(track, timecode, buffer, lacing);
722
 
 
723
 
        KaxReferenceBlock & thePastRef = GetChild<KaxReferenceBlock>(*this);
724
 
        thePastRef.SetReferencedBlock(PastBlock);
725
 
        thePastRef.SetParentBlock(*this);
726
 
 
727
 
        KaxReferenceBlock & theFutureRef = AddNewChild<KaxReferenceBlock>(*this);
728
 
        theFutureRef.SetReferencedBlock(ForwBlock);
729
 
        theFutureRef.SetParentBlock(*this);
730
 
 
731
 
        return bRes;
 
745
  //  assert(past_timecode < 0);
 
746
 
 
747
  //  assert(forw_timecode > 0);
 
748
 
 
749
  KaxBlock & theBlock = GetChild<KaxBlock>(*this);
 
750
  assert(ParentCluster != NULL);
 
751
  theBlock.SetParent(*ParentCluster);
 
752
  ParentTrack = &track;
 
753
  bool bRes = theBlock.AddFrame(track, timecode, buffer, lacing);
 
754
 
 
755
  KaxReferenceBlock & thePastRef = GetChild<KaxReferenceBlock>(*this);
 
756
  thePastRef.SetReferencedBlock(PastBlock);
 
757
  thePastRef.SetParentBlock(*this);
 
758
 
 
759
  KaxReferenceBlock & theFutureRef = AddNewChild<KaxReferenceBlock>(*this);
 
760
  theFutureRef.SetReferencedBlock(ForwBlock);
 
761
  theFutureRef.SetParentBlock(*this);
 
762
 
 
763
  return bRes;
732
764
}
733
765
 
734
766
bool KaxBlockGroup::AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, const KaxBlockBlob * PastBlock, const KaxBlockBlob * ForwBlock, LacingType lacing)
735
767
{
736
 
        KaxBlock & theBlock = GetChild<KaxBlock>(*this);
737
 
        assert(ParentCluster != NULL);
738
 
        theBlock.SetParent(*ParentCluster);
739
 
        ParentTrack = &track;
740
 
        bool bRes = theBlock.AddFrame(track, timecode, buffer, lacing);
741
 
 
742
 
        if (PastBlock != NULL)
743
 
        {
744
 
                KaxReferenceBlock & thePastRef = GetChild<KaxReferenceBlock>(*this);
745
 
                thePastRef.SetReferencedBlock(PastBlock);
746
 
                thePastRef.SetParentBlock(*this);
747
 
        }
748
 
 
749
 
        if (ForwBlock != NULL)
750
 
        {
751
 
                KaxReferenceBlock & theFutureRef = AddNewChild<KaxReferenceBlock>(*this);
752
 
                theFutureRef.SetReferencedBlock(ForwBlock);
753
 
                theFutureRef.SetParentBlock(*this);
754
 
        }
755
 
 
756
 
        return bRes;
 
768
  KaxBlock & theBlock = GetChild<KaxBlock>(*this);
 
769
  assert(ParentCluster != NULL);
 
770
  theBlock.SetParent(*ParentCluster);
 
771
  ParentTrack = &track;
 
772
  bool bRes = theBlock.AddFrame(track, timecode, buffer, lacing);
 
773
 
 
774
  if (PastBlock != NULL) {
 
775
    KaxReferenceBlock & thePastRef = GetChild<KaxReferenceBlock>(*this);
 
776
    thePastRef.SetReferencedBlock(PastBlock);
 
777
    thePastRef.SetParentBlock(*this);
 
778
  }
 
779
 
 
780
  if (ForwBlock != NULL) {
 
781
    KaxReferenceBlock & theFutureRef = AddNewChild<KaxReferenceBlock>(*this);
 
782
    theFutureRef.SetReferencedBlock(ForwBlock);
 
783
    theFutureRef.SetParentBlock(*this);
 
784
  }
 
785
 
 
786
  return bRes;
757
787
}
758
788
 
759
789
/*!
760
 
        \todo we may cache the reference to the timecode block
 
790
  \todo we may cache the reference to the timecode block
761
791
*/
762
792
uint64 KaxBlockGroup::GlobalTimecode() const
763
793
{
764
 
        assert(ParentCluster != NULL); // impossible otherwise
765
 
        KaxInternalBlock & MyBlock = *static_cast<KaxBlock *>(this->FindElt(EBML_INFO(KaxBlock)));
766
 
        return MyBlock.GlobalTimecode();
 
794
  assert(ParentCluster != NULL); // impossible otherwise
 
795
  KaxInternalBlock & MyBlock = *static_cast<KaxBlock *>(this->FindElt(EBML_INFO(KaxBlock)));
 
796
  return MyBlock.GlobalTimecode();
767
797
 
768
798
}
769
799
 
770
800
uint16 KaxBlockGroup::TrackNumber() const
771
801
{
772
 
        KaxInternalBlock & MyBlock = *static_cast<KaxBlock *>(this->FindElt(EBML_INFO(KaxBlock)));
773
 
        return MyBlock.TrackNum();
 
802
  KaxInternalBlock & MyBlock = *static_cast<KaxBlock *>(this->FindElt(EBML_INFO(KaxBlock)));
 
803
  return MyBlock.TrackNum();
774
804
}
775
805
 
776
806
uint64 KaxBlockGroup::ClusterPosition() const
777
807
{
778
 
        assert(ParentCluster != NULL); // impossible otherwise
779
 
        return ParentCluster->GetPosition();
 
808
  assert(ParentCluster != NULL); // impossible otherwise
 
809
  return ParentCluster->GetPosition();
780
810
}
781
811
 
782
812
uint64 KaxInternalBlock::ClusterPosition() const
783
813
{
784
 
        assert(ParentCluster != NULL); // impossible otherwise
785
 
        return ParentCluster->GetPosition();
 
814
  assert(ParentCluster != NULL); // impossible otherwise
 
815
  return ParentCluster->GetPosition();
786
816
}
787
817
 
788
818
unsigned int KaxBlockGroup::ReferenceCount() const
789
819
{
790
 
        unsigned int Result = 0;
791
 
        KaxReferenceBlock * MyBlockAdds = static_cast<KaxReferenceBlock *>(FindFirstElt(EBML_INFO(KaxReferenceBlock)));
792
 
        if (MyBlockAdds != NULL) {
793
 
                Result++;
794
 
                while ((MyBlockAdds = static_cast<KaxReferenceBlock *>(FindNextElt(*MyBlockAdds))) != NULL)
795
 
                {
796
 
                        Result++;
797
 
                }
798
 
        }
799
 
        return Result;
 
820
  unsigned int Result = 0;
 
821
  KaxReferenceBlock * MyBlockAdds = static_cast<KaxReferenceBlock *>(FindFirstElt(EBML_INFO(KaxReferenceBlock)));
 
822
  if (MyBlockAdds != NULL) {
 
823
    Result++;
 
824
    while ((MyBlockAdds = static_cast<KaxReferenceBlock *>(FindNextElt(*MyBlockAdds))) != NULL) {
 
825
      Result++;
 
826
    }
 
827
  }
 
828
  return Result;
800
829
}
801
830
 
802
831
const KaxReferenceBlock & KaxBlockGroup::Reference(unsigned int Index) const
803
832
{
804
 
        KaxReferenceBlock * MyBlockAdds = static_cast<KaxReferenceBlock *>(FindFirstElt(EBML_INFO(KaxReferenceBlock)));
805
 
        assert(MyBlockAdds != NULL); // call of a non existing reference
806
 
        
807
 
        while (Index != 0) {
808
 
                MyBlockAdds = static_cast<KaxReferenceBlock *>(FindNextElt(*MyBlockAdds));
809
 
                assert(MyBlockAdds != NULL);
810
 
                Index--;
811
 
        }
812
 
        return *MyBlockAdds;
 
833
  KaxReferenceBlock * MyBlockAdds = static_cast<KaxReferenceBlock *>(FindFirstElt(EBML_INFO(KaxReferenceBlock)));
 
834
  assert(MyBlockAdds != NULL); // call of a non existing reference
 
835
 
 
836
  while (Index != 0) {
 
837
    MyBlockAdds = static_cast<KaxReferenceBlock *>(FindNextElt(*MyBlockAdds));
 
838
    assert(MyBlockAdds != NULL);
 
839
    Index--;
 
840
  }
 
841
  return *MyBlockAdds;
813
842
}
814
843
 
815
844
void KaxBlockGroup::ReleaseFrames()
816
845
{
817
 
        KaxInternalBlock & MyBlock = *static_cast<KaxBlock *>(this->FindElt(EBML_INFO(KaxBlock)));
818
 
        MyBlock.ReleaseFrames();
 
846
  KaxInternalBlock & MyBlock = *static_cast<KaxBlock *>(this->FindElt(EBML_INFO(KaxBlock)));
 
847
  MyBlock.ReleaseFrames();
819
848
}
820
849
 
821
850
void KaxInternalBlock::ReleaseFrames()
822
851
{
823
 
        // free the allocated Frames
824
 
        int i;
825
 
        for (i=myBuffers.size()-1; i>=0; i--) {
826
 
                if (myBuffers[i] != NULL) {
827
 
                        myBuffers[i]->FreeBuffer(*myBuffers[i]);
828
 
                        delete myBuffers[i];
829
 
                        myBuffers[i] = NULL;
830
 
                }
831
 
        }
 
852
  // free the allocated Frames
 
853
  int i;
 
854
  for (i=myBuffers.size()-1; i>=0; i--) {
 
855
    if (myBuffers[i] != NULL) {
 
856
      myBuffers[i]->FreeBuffer(*myBuffers[i]);
 
857
      delete myBuffers[i];
 
858
      myBuffers[i] = NULL;
 
859
    }
 
860
  }
832
861
}
833
862
 
834
863
void KaxBlockGroup::SetBlockDuration(uint64 TimeLength)
835
864
{
836
 
        assert(ParentTrack != NULL);
837
 
        int64 scale = ParentTrack->GlobalTimecodeScale();
838
 
        KaxBlockDuration & myDuration = *static_cast<KaxBlockDuration *>(FindFirstElt(EBML_INFO(KaxBlockDuration), true));
839
 
        *(static_cast<EbmlUInteger *>(&myDuration)) = TimeLength / uint64(scale);
 
865
  assert(ParentTrack != NULL);
 
866
  int64 scale = ParentTrack->GlobalTimecodeScale();
 
867
  KaxBlockDuration & myDuration = *static_cast<KaxBlockDuration *>(FindFirstElt(EBML_INFO(KaxBlockDuration), true));
 
868
  *(static_cast<EbmlUInteger *>(&myDuration)) = TimeLength / uint64(scale);
840
869
}
841
870
 
842
871
bool KaxBlockGroup::GetBlockDuration(uint64 &TheTimecode) const
843
872
{
844
 
        KaxBlockDuration * myDuration = static_cast<KaxBlockDuration *>(FindElt(EBML_INFO(KaxBlockDuration)));
845
 
        if (myDuration == NULL) {
846
 
                return false;
847
 
        }
 
873
  KaxBlockDuration * myDuration = static_cast<KaxBlockDuration *>(FindElt(EBML_INFO(KaxBlockDuration)));
 
874
  if (myDuration == NULL) {
 
875
    return false;
 
876
  }
848
877
 
849
 
        assert(ParentTrack != NULL);
850
 
        TheTimecode = uint64(*myDuration) * ParentTrack->GlobalTimecodeScale();
851
 
        return true;
 
878
  assert(ParentTrack != NULL);
 
879
  TheTimecode = uint64(*myDuration) * ParentTrack->GlobalTimecodeScale();
 
880
  return true;
852
881
}
853
882
 
854
883
KaxBlockGroup::operator KaxInternalBlock &() {
855
 
        KaxBlock & theBlock = GetChild<KaxBlock>(*this);
856
 
        return theBlock;
 
884
  KaxBlock & theBlock = GetChild<KaxBlock>(*this);
 
885
  return theBlock;
857
886
}
858
887
 
859
888
void KaxBlockGroup::SetParent(KaxCluster & aParentCluster) {
860
 
        ParentCluster = &aParentCluster;
861
 
        KaxBlock & theBlock = GetChild<KaxBlock>(*this);
862
 
        theBlock.SetParent( aParentCluster );
 
889
  ParentCluster = &aParentCluster;
 
890
  KaxBlock & theBlock = GetChild<KaxBlock>(*this);
 
891
  theBlock.SetParent( aParentCluster );
863
892
}
864
893
 
865
894
void KaxSimpleBlock::SetParent(KaxCluster & aParentCluster) {
866
 
        KaxInternalBlock::SetParent( aParentCluster );
 
895
  KaxInternalBlock::SetParent( aParentCluster );
867
896
}
868
897
 
869
898
void KaxInternalBlock::SetParent(KaxCluster & aParentCluster)
870
899
{
871
 
        ParentCluster = &aParentCluster;
872
 
        if (bLocalTimecodeUsed) {
873
 
                Timecode = aParentCluster.GetBlockGlobalTimecode(LocalTimecode);
874
 
                bLocalTimecodeUsed = false;
875
 
        }
 
900
  ParentCluster = &aParentCluster;
 
901
  if (bLocalTimecodeUsed) {
 
902
    Timecode = aParentCluster.GetBlockGlobalTimecode(LocalTimecode);
 
903
    bLocalTimecodeUsed = false;
 
904
  }
876
905
}
877
906
 
878
907
int64 KaxInternalBlock::GetDataPosition(size_t FrameNumber)
879
908
{
880
 
        int64 _Result = -1;
881
 
 
882
 
        if (ValueIsSet() && FrameNumber < SizeList.size())
883
 
        {
884
 
                _Result = FirstFrameLocation;
885
 
        
886
 
                size_t _Idx = 0;
887
 
                while(FrameNumber--)
888
 
                {
889
 
                        _Result += SizeList[_Idx++];
890
 
                }
891
 
        }
892
 
 
893
 
        return _Result;
 
909
  int64 _Result = -1;
 
910
 
 
911
  if (ValueIsSet() && FrameNumber < SizeList.size()) {
 
912
    _Result = FirstFrameLocation;
 
913
 
 
914
    size_t _Idx = 0;
 
915
    while(FrameNumber--) {
 
916
      _Result += SizeList[_Idx++];
 
917
    }
 
918
  }
 
919
 
 
920
  return _Result;
894
921
}
895
922
 
896
923
int64 KaxInternalBlock::GetFrameSize(size_t FrameNumber)
897
924
{
898
 
        int64 _Result = -1;
899
 
 
900
 
        if (/*bValueIsSet &&*/ FrameNumber < SizeList.size())
901
 
        {
902
 
                _Result = SizeList[FrameNumber];
903
 
        }
904
 
 
905
 
        return _Result;
 
925
  int64 _Result = -1;
 
926
 
 
927
  if (/*bValueIsSet &&*/ FrameNumber < SizeList.size()) {
 
928
    _Result = SizeList[FrameNumber];
 
929
  }
 
930
 
 
931
  return _Result;
906
932
}
907
933
 
908
934
KaxBlockBlob::operator KaxBlockGroup &()
909
935
{
910
 
        assert(!bUseSimpleBlock);
911
 
        assert(Block.group);
912
 
        return *Block.group;
 
936
  assert(!bUseSimpleBlock);
 
937
  assert(Block.group);
 
938
  return *Block.group;
913
939
}
914
940
 
915
941
KaxBlockBlob::operator const KaxBlockGroup &() const
916
942
{
917
 
        assert(!bUseSimpleBlock);
918
 
        assert(Block.group);
919
 
        return *Block.group;
 
943
  assert(!bUseSimpleBlock);
 
944
  assert(Block.group);
 
945
  return *Block.group;
920
946
}
921
947
 
922
948
KaxBlockBlob::operator KaxInternalBlock &()
923
949
{
924
 
        assert(Block.group);
 
950
  assert(Block.group);
925
951
#if MATROSKA_VERSION >= 2
926
 
        if (bUseSimpleBlock)
927
 
                return *Block.simpleblock;
928
 
        else
 
952
  if (bUseSimpleBlock)
 
953
    return *Block.simpleblock;
 
954
  else
929
955
#endif
930
 
                return *Block.group;
 
956
    return *Block.group;
931
957
}
932
958
 
933
959
KaxBlockBlob::operator const KaxInternalBlock &() const
934
960
{
935
 
        assert(Block.group);
 
961
  assert(Block.group);
936
962
#if MATROSKA_VERSION >= 2
937
 
        if (bUseSimpleBlock)
938
 
                return *Block.simpleblock;
939
 
        else
 
963
  if (bUseSimpleBlock)
 
964
    return *Block.simpleblock;
 
965
  else
940
966
#endif
941
 
                return *Block.group;
 
967
    return *Block.group;
942
968
}
943
969
 
944
970
#if MATROSKA_VERSION >= 2
945
971
KaxBlockBlob::operator KaxSimpleBlock &()
946
972
{
947
 
        assert(bUseSimpleBlock);
948
 
        assert(Block.simpleblock);
949
 
        return *Block.simpleblock;
 
973
  assert(bUseSimpleBlock);
 
974
  assert(Block.simpleblock);
 
975
  return *Block.simpleblock;
950
976
}
951
977
#endif
952
978
 
953
979
bool KaxBlockBlob::AddFrameAuto(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, LacingType lacing, const KaxBlockBlob * PastBlock, const KaxBlockBlob * ForwBlock)
954
980
{
955
 
        bool bResult = false;
 
981
  bool bResult = false;
956
982
#if MATROSKA_VERSION >= 2
957
 
        if ((SimpleBlockMode == BLOCK_BLOB_ALWAYS_SIMPLE) || (SimpleBlockMode == BLOCK_BLOB_SIMPLE_AUTO && PastBlock == NULL && ForwBlock == NULL)) {
958
 
                assert(bUseSimpleBlock == true);
959
 
                if (Block.simpleblock == NULL) {
960
 
                        Block.simpleblock = new KaxSimpleBlock();
961
 
                        Block.simpleblock->SetParent(*ParentCluster);
962
 
                }
 
983
  if ((SimpleBlockMode == BLOCK_BLOB_ALWAYS_SIMPLE) || (SimpleBlockMode == BLOCK_BLOB_SIMPLE_AUTO && PastBlock == NULL && ForwBlock == NULL)) {
 
984
    assert(bUseSimpleBlock == true);
 
985
    if (Block.simpleblock == NULL) {
 
986
      Block.simpleblock = new KaxSimpleBlock();
 
987
      Block.simpleblock->SetParent(*ParentCluster);
 
988
    }
963
989
 
964
 
                bResult = Block.simpleblock->AddFrame(track, timecode, buffer, lacing);
965
 
                if (PastBlock == NULL && ForwBlock == NULL) {
966
 
                        Block.simpleblock->SetKeyframe(true);
967
 
                        Block.simpleblock->SetDiscardable(false);
968
 
                } else {
969
 
                        Block.simpleblock->SetKeyframe(false);
970
 
                        if ((ForwBlock == NULL || ((const KaxInternalBlock &)*ForwBlock).GlobalTimecode() <= timecode) &&
971
 
                                (PastBlock == NULL || ((const KaxInternalBlock &)*PastBlock).GlobalTimecode() <= timecode))
972
 
                                Block.simpleblock->SetDiscardable(false);
973
 
                        else
974
 
                                Block.simpleblock->SetDiscardable(true);
975
 
                }
976
 
        }
977
 
        else
 
990
    bResult = Block.simpleblock->AddFrame(track, timecode, buffer, lacing);
 
991
    if (PastBlock == NULL && ForwBlock == NULL) {
 
992
      Block.simpleblock->SetKeyframe(true);
 
993
      Block.simpleblock->SetDiscardable(false);
 
994
    } else {
 
995
      Block.simpleblock->SetKeyframe(false);
 
996
      if ((ForwBlock == NULL || ((const KaxInternalBlock &)*ForwBlock).GlobalTimecode() <= timecode) &&
 
997
          (PastBlock == NULL || ((const KaxInternalBlock &)*PastBlock).GlobalTimecode() <= timecode))
 
998
        Block.simpleblock->SetDiscardable(false);
 
999
      else
 
1000
        Block.simpleblock->SetDiscardable(true);
 
1001
    }
 
1002
  }
 
1003
  else
978
1004
#endif
979
 
        {
980
 
                if (ReplaceSimpleByGroup()) {
981
 
                        bResult = Block.group->AddFrame(track, timecode, buffer, PastBlock, ForwBlock, lacing);
982
 
                }
983
 
        }
 
1005
    if (ReplaceSimpleByGroup())
 
1006
      bResult = Block.group->AddFrame(track, timecode, buffer, PastBlock, ForwBlock, lacing);
984
1007
 
985
 
        return bResult;
 
1008
  return bResult;
986
1009
}
987
1010
 
988
1011
void KaxBlockBlob::SetParent(KaxCluster & parent_clust)
989
1012
{
990
 
        ParentCluster = &parent_clust;
 
1013
  ParentCluster = &parent_clust;
991
1014
}
992
1015
 
993
1016
void KaxBlockBlob::SetBlockDuration(uint64 TimeLength)
994
1017
{
995
 
        if (ReplaceSimpleByGroup())
996
 
                Block.group->SetBlockDuration(TimeLength);
 
1018
  if (ReplaceSimpleByGroup())
 
1019
    Block.group->SetBlockDuration(TimeLength);
997
1020
}
998
1021
 
999
1022
bool KaxBlockBlob::ReplaceSimpleByGroup()
1000
1023
{
1001
 
        if (SimpleBlockMode== BLOCK_BLOB_ALWAYS_SIMPLE)
1002
 
                return false;
 
1024
  if (SimpleBlockMode== BLOCK_BLOB_ALWAYS_SIMPLE)
 
1025
    return false;
1003
1026
 
1004
 
        if (!bUseSimpleBlock) {
1005
 
                if (Block.group == NULL) {
1006
 
                        Block.group = new KaxBlockGroup();
1007
 
                }
1008
 
        }
 
1027
  if (!bUseSimpleBlock) {
 
1028
    if (Block.group == NULL) {
 
1029
      Block.group = new KaxBlockGroup();
 
1030
    }
 
1031
  }
1009
1032
#if MATROSKA_VERSION >= 2
1010
 
        else 
1011
 
        {
 
1033
  else {
1012
1034
 
1013
 
                if (Block.simpleblock != NULL) {
1014
 
                        KaxSimpleBlock *old_simpleblock = Block.simpleblock;
1015
 
                        Block.group = new KaxBlockGroup();
1016
 
                        // _TODO_ : move all the data to the blockgroup
1017
 
                        assert(false);
1018
 
                        // -> while(frame) AddFrame(myBuffer)
1019
 
                        delete old_simpleblock;
1020
 
                } else {
1021
 
                        Block.group = new KaxBlockGroup();
1022
 
                }
1023
 
        }
 
1035
    if (Block.simpleblock != NULL) {
 
1036
      KaxSimpleBlock *old_simpleblock = Block.simpleblock;
 
1037
      Block.group = new KaxBlockGroup();
 
1038
      // _TODO_ : move all the data to the blockgroup
 
1039
      assert(false);
 
1040
      // -> while(frame) AddFrame(myBuffer)
 
1041
      delete old_simpleblock;
 
1042
    } else {
 
1043
      Block.group = new KaxBlockGroup();
 
1044
    }
 
1045
  }
1024
1046
#endif
1025
 
        if (ParentCluster != NULL)
1026
 
                Block.group->SetParent(*ParentCluster);
 
1047
  if (ParentCluster != NULL)
 
1048
    Block.group->SetParent(*ParentCluster);
1027
1049
 
1028
 
        bUseSimpleBlock = false;
1029
 
        return true;
 
1050
  bUseSimpleBlock = false;
 
1051
  return true;
1030
1052
}
1031
1053
 
1032
1054
void KaxBlockBlob::SetBlockGroup( KaxBlockGroup &BlockRef )
1033
1055
{
1034
 
        assert(!bUseSimpleBlock);
1035
 
        Block.group = &BlockRef;
 
1056
  assert(!bUseSimpleBlock);
 
1057
  Block.group = &BlockRef;
1036
1058
}
1037
1059
 
1038
1060
filepos_t KaxBlockVirtual::ReadData(IOCallback & input, ScopeMode /* ReadFully */)
1039
1061
{
1040
 
    input.setFilePointer(SizePosition + CodedSizeLength(Size, SizeLength, bSizeIsFinite) + Size, seek_beginning);
1041
 
    return GetSize();
 
1062
  input.setFilePointer(SizePosition + CodedSizeLength(Size, SizeLength, bSizeIsFinite) + Size, seek_beginning);
 
1063
  return GetSize();
1042
1064
}
1043
1065
 
1044
1066
END_LIBMATROSKA_NAMESPACE