Esempio n. 1
0
/*!
	\warning Assume that the list has been sorted (Sort())
*/
const KaxCuePoint * KaxCues::GetTimecodePoint(uint64 aTimecode) const
{
	uint64 TimecodeToLocate = aTimecode / GlobalTimecodeScale();
	const KaxCuePoint * aPointPrev = NULL;
	uint64 aPrevTime = 0;
	uint64 aNextTime = EBML_PRETTYLONGINT(0xFFFFFFFFFFFF);

    EBML_MASTER_CONST_ITERATOR Itr;
	for (Itr = begin(); Itr != end(); ++Itr)
    {
		if (EbmlId(*(*Itr)) == EBML_ID(KaxCuePoint)) {
			const KaxCuePoint *tmp = static_cast<const KaxCuePoint *>(*Itr);
			// check the tile
			const KaxCueTime *aTime = static_cast<const KaxCueTime *>(tmp->FindFirstElt(EBML_INFO(KaxCueTime)));
			if (aTime != NULL)
			{
				uint64 _Time = uint64(*aTime);
				if (_Time > aPrevTime && _Time < TimecodeToLocate) {
					aPrevTime = _Time;
					aPointPrev = tmp;
				}
				if (_Time < aNextTime && _Time > TimecodeToLocate) {
					aNextTime= _Time;
				}
			}
		}
	}

	return aPointPrev;
}
Esempio n. 2
0
void KaxCluster::ReleaseFrames()
{
  EBML_MASTER_ITERATOR Itr;
  for (Itr = begin(); Itr != end(); ++Itr) {
    if (EbmlId(*(*Itr)) == EBML_ID(KaxBlockGroup)) {
      static_cast<KaxBlockGroup*>(*Itr)->ReleaseFrames();
    }
  }
}
Esempio n. 3
0
void
cues_c::write(mm_io_c &out,
              KaxSeekHead &seek_head) {
  if (!m_points.size() || !g_cue_writing_requested)
    return;

  // auto start = get_current_time_millis();
  sort();
  // auto end_sort = get_current_time_millis();

  // Need to write the (empty) cues element so that its position will
  // be set for indexing in g_kax_sh_main. Necessary because there's
  // no API function to force the position to a certain value; nor is
  // there a different API function in KaxSeekHead for adding anything
  // by ID and position manually.
  out.save_pos();
  kax_cues_position_dummy_c cues_dummy;
  cues_dummy.Render(out);
  out.restore_pos();

  // Write meta seek information if it is not disabled.
  seek_head.IndexThis(cues_dummy, *g_kax_segment);

  // Forcefully write the correct head and copy its content from the
  // temporary storage location.
  auto total_size = calculate_total_size();
  write_ebml_element_head(out, EBML_ID(KaxCues), total_size);

  for (auto &point : m_points) {
    KaxCuePoint kc_point;

    GetChild<KaxCueTime>(kc_point).SetValue(point.timecode / g_timecode_scale);

    auto &positions = GetChild<KaxCueTrackPositions>(kc_point);
    GetChild<KaxCueTrack>(positions).SetValue(point.track_num);
    GetChild<KaxCueClusterPosition>(positions).SetValue(point.cluster_position);

    auto codec_state_position = m_codec_state_position_map.find({ point.track_num, point.timecode });
    if (codec_state_position != m_codec_state_position_map.end())
      GetChild<KaxCueCodecState>(positions).SetValue(codec_state_position->second);

    if (point.relative_position)
      GetChild<KaxCueRelativePosition>(positions).SetValue(point.relative_position);

    if (point.duration)
      GetChild<KaxCueDuration>(positions).SetValue(RND_TIMECODE_SCALE(point.duration) / g_timecode_scale);

    kc_point.Render(out);
  }

  m_points.clear();
  m_codec_state_position_map.clear();
  m_num_cue_points_postprocessed = 0;

  // auto end_all = get_current_time_millis();
  // mxinfo(boost::format("dur sort %1% write %2% total %3%\n") % (end_sort - start) % (end_all - end_sort) % (end_all - start));
}
Esempio n. 4
0
KaxCluster::KaxCluster(const KaxCluster & ElementToClone)
  :EbmlMaster(ElementToClone)
  ,bSilentTracksUsed(ElementToClone.bSilentTracksUsed)
{
  // update the parent of each children
  EBML_MASTER_ITERATOR Itr = begin();
  while (Itr != end()) {
    if (EbmlId(**Itr) == EBML_ID(KaxBlockGroup)) {
      static_cast<KaxBlockGroup   *>(*Itr)->SetParent(*this);
    } else if (EbmlId(**Itr) == EBML_ID(KaxBlock)) {
      static_cast<KaxBlock        *>(*Itr)->SetParent(*this);
#if MATROSKA_VERSION >= 2
    } else if (EbmlId(**Itr) == EBML_ID(KaxBlockVirtual)) {
      static_cast<KaxBlockVirtual *>(*Itr)->SetParent(*this);
#endif // MATROSKA_VERSION
    }
    ++Itr;
  }
}
Esempio n. 5
0
KaxSegment::KaxSegment(const KaxSegment & ElementToClone)
 :EbmlMaster(ElementToClone)
{
	// update the parent of each children
	EBML_MASTER_ITERATOR Itr = begin();
	while (Itr != end())
	{
		if (EbmlId(**Itr) == EBML_ID(KaxCluster)) {
			static_cast<KaxCluster *>(*Itr)->SetParent(*this);
		}
        ++Itr;
	}
}
Esempio n. 6
0
bool KaxCuePoint::IsSmallerThan(const EbmlElement * EltB) const
{
  assert(EbmlId(*this) == EBML_ID(KaxCuePoint));
  assert(EbmlId(*EltB) == EBML_ID(KaxCuePoint));

  const KaxCuePoint & theEltB = *static_cast<const KaxCuePoint *>(EltB);

  // compare timecode
  const KaxCueTime * TimeCodeA = static_cast<const KaxCueTime *>(FindElt(EBML_INFO(KaxCueTime)));
  if (TimeCodeA == NULL)
    return false;

  const KaxCueTime * TimeCodeB = static_cast<const KaxCueTime *>(theEltB.FindElt(EBML_INFO(KaxCueTime)));
  if (TimeCodeB == NULL)
    return false;

  if (TimeCodeA->IsSmallerThan(TimeCodeB))
    return true;

  if (TimeCodeB->IsSmallerThan(TimeCodeA))
    return false;

  // compare tracks (timecodes are equal)
  const KaxCueTrack * TrackA = static_cast<const KaxCueTrack *>(FindElt(EBML_INFO(KaxCueTrack)));
  if (TrackA == NULL)
    return false;

  const KaxCueTrack * TrackB = static_cast<const KaxCueTrack *>(theEltB.FindElt(EBML_INFO(KaxCueTrack)));
  if (TrackB == NULL)
    return false;

  if (TrackA->IsSmallerThan(TrackB))
    return true;

  if (TrackB->IsSmallerThan(TrackA))
    return false;

  return false;
}
Esempio n. 7
0
uint64_t
cues_c::calculate_point_size(cue_point_t const &point)
  const {
  uint64_t point_size = EBML_ID_LENGTH(EBML_ID(KaxCuePoint))           + 1
                      + EBML_ID_LENGTH(EBML_ID(KaxCuePoint))           + 1 + calculate_bytes_for_uint(point.timecode / g_timecode_scale)
                      + EBML_ID_LENGTH(EBML_ID(KaxCueTrackPositions))  + 1
                      + EBML_ID_LENGTH(EBML_ID(KaxCueTrack))           + 1 + calculate_bytes_for_uint(point.track_num)
                      + EBML_ID_LENGTH(EBML_ID(KaxCueClusterPosition)) + 1 + calculate_bytes_for_uint(point.cluster_position);

  auto codec_state_position = m_codec_state_position_map.find({ point.track_num, point.timecode });
  if (codec_state_position != m_codec_state_position_map.end())
    point_size += EBML_ID_LENGTH(EBML_ID(KaxCueCodecState)) + 1 + calculate_bytes_for_uint(codec_state_position->second);

  if (point.relative_position)
    point_size += EBML_ID_LENGTH(EBML_ID(KaxCueRelativePosition)) + 1 + calculate_bytes_for_uint(point.relative_position);

  if (point.duration)
    point_size += EBML_ID_LENGTH(EBML_ID(KaxCueDuration)) + 1 + calculate_bytes_for_uint(RND_TIMECODE_SCALE(point.duration) / g_timecode_scale);

  return point_size;
}
Esempio n. 8
0
/*!
	\todo better zero copy handling
*/
filepos_t KaxInternalBlock::ReadData(IOCallback & input, ScopeMode ReadFully)
{
	filepos_t Result;

	FirstFrameLocation = input.getFilePointer(); // will be updated accordingly below

	if (ReadFully == SCOPE_ALL_DATA)
	{
		Result = EbmlBinary::ReadData(input, ReadFully);
        binary *cursor = EbmlBinary::GetBuffer();
		uint8 BlockHeadSize = 4;

		// update internal values
		TrackNumber = *cursor++;
		if ((TrackNumber & 0x80) == 0) {
			// there is extra data
			if ((TrackNumber & 0x40) == 0) {
				// We don't support track numbers that large !
				return Result;
			}
			TrackNumber = (TrackNumber & 0x3F) << 8;
			TrackNumber += *cursor++;
			BlockHeadSize++;
		} else {
			TrackNumber &= 0x7F;
		}

		big_int16 b16;
		b16.Eval(cursor);
		LocalTimecode = int16(b16);
		bLocalTimecodeUsed = true;
		cursor += 2;

		if (EbmlId(*this) == EBML_ID(KaxSimpleBlock)) {
			bIsKeyframe = (*cursor & 0x80) != 0;
			bIsDiscardable = (*cursor & 0x01) != 0;
		}
		mInvisible = (*cursor & 0x08) >> 3;
		mLacing = LacingType((*cursor++ & 0x06) >> 1);

		// put all Frames in the list
		if (mLacing == LACING_NONE) {
			FirstFrameLocation += cursor - EbmlBinary::GetBuffer();
			DataBuffer * soloFrame = new DataBuffer(cursor, GetSize() - BlockHeadSize);
			myBuffers.push_back(soloFrame);
			SizeList.resize(1);
			SizeList[0] = GetSize() - BlockHeadSize;
		} else {
			// read the number of frames in the lace
			uint32 LastBufferSize = GetSize() - BlockHeadSize - 1; // 1 for number of frame
			uint8 FrameNum = *cursor++; // number of frames in the lace - 1
			// read the list of frame sizes
			uint8 Index;
			int32 FrameSize;
			uint32 SizeRead;
			uint64 SizeUnknown;

			SizeList.resize(FrameNum + 1);

			switch (mLacing)
			{
			case LACING_XIPH:
				for (Index=0; Index<FrameNum; Index++) {
					// get the size of the frame
					FrameSize = 0;
					do {
						FrameSize += uint8(*cursor);
						LastBufferSize--;
					} while (*cursor++ == 0xFF);
					SizeList[Index] = FrameSize;
					LastBufferSize -= FrameSize;
				}
				SizeList[Index] = LastBufferSize;
				break;
			case LACING_EBML:
				SizeRead = LastBufferSize;
				FrameSize = ReadCodedSizeValue(cursor, SizeRead, SizeUnknown);
				SizeList[0] = FrameSize;
				cursor += SizeRead;
				LastBufferSize -= FrameSize + SizeRead;

				for (Index=1; Index<FrameNum; Index++) {
					// get the size of the frame
					SizeRead = LastBufferSize;
					FrameSize += ReadCodedSizeSignedValue(cursor, SizeRead, SizeUnknown);
					SizeList[Index] = FrameSize;
					cursor += SizeRead;
					LastBufferSize -= FrameSize + SizeRead;
				}
				SizeList[Index] = LastBufferSize;
				break;
			case LACING_FIXED:
				for (Index=0; Index<=FrameNum; Index++) {
					// get the size of the frame
					SizeList[Index] = LastBufferSize / (FrameNum + 1);
				}
				break;
			default: // other lacing not supported
				assert(0);
			}

			FirstFrameLocation += cursor - EbmlBinary::GetBuffer();

			for (Index=0; Index<=FrameNum; Index++) {
				DataBuffer * lacedFrame = new DataBuffer(cursor, SizeList[Index]);
				myBuffers.push_back(lacedFrame);
				cursor += SizeList[Index];
			}
		}
		SetValueIsSet();
	}
Esempio n. 9
0
/*!
  \todo better zero copy handling
*/
filepos_t KaxInternalBlock::ReadData(IOCallback & input, ScopeMode ReadFully)
{
  filepos_t Result;

  FirstFrameLocation = input.getFilePointer(); // will be updated accordingly below

  SetValueIsSet(false);

  try {
    if (ReadFully == SCOPE_ALL_DATA) {
      Result = EbmlBinary::ReadData(input, ReadFully);
      if (Result != GetSize())
        throw SafeReadIOCallback::EndOfStreamX(GetSize() - Result);

      binary *BufferStart = EbmlBinary::GetBuffer();

      SafeReadIOCallback Mem(*this);
      uint8 BlockHeadSize = 4;

      // update internal values
      TrackNumber = Mem.GetUInt8();
      if ((TrackNumber & 0x80) == 0) {
        // there is extra data
        if ((TrackNumber & 0x40) == 0) {
          // We don't support track numbers that large !
          throw SafeReadIOCallback::EndOfStreamX(0);
        }
        TrackNumber = (TrackNumber & 0x3F) << 8;
        TrackNumber += Mem.GetUInt8();
        BlockHeadSize++;
      } else {
        TrackNumber &= 0x7F;
      }

      LocalTimecode = int16(Mem.GetUInt16BE());
      bLocalTimecodeUsed = true;

      uint8 Flags = Mem.GetUInt8();
      if (EbmlId(*this) == EBML_ID(KaxSimpleBlock)) {
        bIsKeyframe = (Flags & 0x80) != 0;
        bIsDiscardable = (Flags & 0x01) != 0;
      }
      mInvisible = (Flags & 0x08) >> 3;
      mLacing = LacingType((Flags & 0x06) >> 1);

      // put all Frames in the list
      if (mLacing == LACING_NONE) {
        FirstFrameLocation += Mem.GetPosition();
        DataBuffer * soloFrame = new DataBuffer(BufferStart + Mem.GetPosition(), GetSize() - BlockHeadSize);
        myBuffers.push_back(soloFrame);
        SizeList.resize(1);
        SizeList[0] = GetSize() - BlockHeadSize;
      } else {
        // read the number of frames in the lace
        uint32 LastBufferSize = GetSize() - BlockHeadSize - 1; // 1 for number of frame
        uint8 FrameNum = Mem.GetUInt8(); // number of frames in the lace - 1
        // read the list of frame sizes
        uint8 Index;
        int32 FrameSize;
        uint32 SizeRead;
        uint64 SizeUnknown;

        SizeList.resize(FrameNum + 1);

        switch (mLacing) {
          case LACING_XIPH:
            for (Index=0; Index<FrameNum; Index++) {
              // get the size of the frame
              FrameSize = 0;
              uint8 Value;
              do {
                Value = Mem.GetUInt8();
                FrameSize += Value;
                LastBufferSize--;
              } while (Value == 0xFF);
              SizeList[Index] = FrameSize;
              LastBufferSize -= FrameSize;
            }
            SizeList[Index] = LastBufferSize;
            break;
          case LACING_EBML:
            SizeRead = LastBufferSize;
            FrameSize = ReadCodedSizeValue(BufferStart + Mem.GetPosition(), SizeRead, SizeUnknown);
            SizeList[0] = FrameSize;
            Mem.Skip(SizeRead);
            LastBufferSize -= FrameSize + SizeRead;

            for (Index=1; Index<FrameNum; Index++) {
              // get the size of the frame
              SizeRead = LastBufferSize;
              FrameSize += ReadCodedSizeSignedValue(BufferStart + Mem.GetPosition(), SizeRead, SizeUnknown);
              SizeList[Index] = FrameSize;
              Mem.Skip(SizeRead);
              LastBufferSize -= FrameSize + SizeRead;
            }
            if (Index <= FrameNum) // Safety check if FrameNum == 0
              SizeList[Index] = LastBufferSize;
            break;
          case LACING_FIXED:
            for (Index=0; Index<=FrameNum; Index++) {
              // get the size of the frame
              SizeList[Index] = LastBufferSize / (FrameNum + 1);
            }
            break;
          default: // other lacing not supported
            assert(0);
        }

        FirstFrameLocation += Mem.GetPosition();

        for (Index=0; Index<=FrameNum; Index++) {
          DataBuffer * lacedFrame = new DataBuffer(BufferStart + Mem.GetPosition(), SizeList[Index]);
          myBuffers.push_back(lacedFrame);
          Mem.Skip(SizeList[Index]);
        }
      }

      binary *BufferEnd = BufferStart + GetSize();
      size_t NumFrames  = myBuffers.size();

      // Sanity checks for frame pointers and boundaries.
      for (size_t Index = 0; Index < NumFrames; ++Index) {
        binary *FrameStart  = myBuffers[Index]->Buffer();
        binary *FrameEnd    = FrameStart + myBuffers[Index]->Size();
        binary *ExpectedEnd = (Index + 1) < NumFrames ? myBuffers[Index + 1]->Buffer() : BufferEnd;

        if ((FrameStart < BufferStart) || (FrameEnd > BufferEnd) || (FrameEnd != ExpectedEnd))
          throw SafeReadIOCallback::EndOfStreamX(0);
      }

      SetValueIsSet();
    } else if (ReadFully == SCOPE_PARTIAL_DATA) {
      binary _TempHead[5];
      Result = input.read(_TempHead, 5);
      if (Result != 5)
        throw SafeReadIOCallback::EndOfStreamX(0);
      binary *cursor = _TempHead;
      binary *_tmpBuf;
      uint8 BlockHeadSize = 4;

      // update internal values
      TrackNumber = *cursor++;
      if ((TrackNumber & 0x80) == 0) {
        // there is extra data
        if ((TrackNumber & 0x40) == 0) {
          // We don't support track numbers that large !
          return Result;
        }
        TrackNumber = (TrackNumber & 0x3F) << 8;
        TrackNumber += *cursor++;
        BlockHeadSize++;
      } else {
        TrackNumber &= 0x7F;
      }

      big_int16 b16;
      b16.Eval(cursor);
      LocalTimecode = int16(b16);
      bLocalTimecodeUsed = true;
      cursor += 2;

      if (EbmlId(*this) == EBML_ID(KaxSimpleBlock)) {
        bIsKeyframe = (*cursor & 0x80) != 0;
        bIsDiscardable = (*cursor & 0x01) != 0;
      }
      mInvisible = (*cursor & 0x08) >> 3;
      mLacing = LacingType((*cursor++ & 0x06) >> 1);
      if (cursor == &_TempHead[4]) {
        _TempHead[0] = _TempHead[4];
      } else {
        Result += input.read(_TempHead, 1);
      }

      FirstFrameLocation += cursor - _TempHead;

      // put all Frames in the list
      if (mLacing != LACING_NONE) {
        // read the number of frames in the lace
        uint32 LastBufferSize = GetSize() - BlockHeadSize - 1; // 1 for number of frame
        uint8 FrameNum = _TempHead[0]; // number of frames in the lace - 1
        // read the list of frame sizes
        uint8 Index;
        int32 FrameSize;
        uint32 SizeRead;
        uint64 SizeUnknown;

        SizeList.resize(FrameNum + 1);

        switch (mLacing) {
          case LACING_XIPH:
            for (Index=0; Index<FrameNum; Index++) {
              // get the size of the frame
              FrameSize = 0;
              do {
                Result += input.read(_TempHead, 1);
                FrameSize += uint8(_TempHead[0]);
                LastBufferSize--;

                FirstFrameLocation++;
              } while (_TempHead[0] == 0xFF);

              FirstFrameLocation++;
              SizeList[Index] = FrameSize;
              LastBufferSize -= FrameSize;
            }
            SizeList[Index] = LastBufferSize;
            break;
          case LACING_EBML:
            SizeRead = LastBufferSize;
            cursor = _tmpBuf = new binary[FrameNum*4]; /// \warning assume the mean size will be coded in less than 4 bytes
            Result += input.read(cursor, FrameNum*4);
            FrameSize = ReadCodedSizeValue(cursor, SizeRead, SizeUnknown);
            SizeList[0] = FrameSize;
            cursor += SizeRead;
            LastBufferSize -= FrameSize + SizeRead;

            for (Index=1; Index<FrameNum; Index++) {
              // get the size of the frame
              SizeRead = LastBufferSize;
              FrameSize += ReadCodedSizeSignedValue(cursor, SizeRead, SizeUnknown);
              SizeList[Index] = FrameSize;
              cursor += SizeRead;
              LastBufferSize -= FrameSize + SizeRead;
            }

            FirstFrameLocation += cursor - _tmpBuf;

            SizeList[Index] = LastBufferSize;
            delete [] _tmpBuf;
            break;
          case LACING_FIXED:
            for (Index=0; Index<=FrameNum; Index++) {
              // get the size of the frame
              SizeList[Index] = LastBufferSize / (FrameNum + 1);
            }
            break;
          default: // other lacing not supported
            assert(0);
        }
      } else {
        SizeList.resize(1);
        SizeList[0] = GetSize() - BlockHeadSize;
      }
      SetValueIsSet(false);
      Result = GetSize();
    } else {
Esempio n. 10
0
KaxCluster *
kax_file_c::read_next_cluster() {
  return static_cast<KaxCluster *>(read_next_level1_element(EBML_ID_VALUE(EBML_ID(KaxCluster))));
}
Esempio n. 11
0
EbmlElement *
kax_file_c::resync_to_level1_element_internal(uint32_t wanted_id) {
  if (m_segment_end && (m_in->getFilePointer() >= m_segment_end))
    return nullptr;

  m_resynced         = true;
  m_resync_start_pos = m_in->getFilePointer();

  uint32_t actual_id = m_in->read_uint32_be();
  int64_t start_time = mtx::sys::get_current_time_millis();
  bool is_cluster_id = !wanted_id || (EBML_ID_VALUE(EBML_ID(KaxCluster)) == wanted_id); // 0 means: any level 1 element will do

  mxinfo(boost::format(Y("%1%: Error in the Matroska file structure at position %2%. Resyncing to the next level 1 element.\n"))
         % m_in->get_file_name() % m_resync_start_pos);

  if (is_cluster_id && (-1 != m_last_timecode)) {
    mxinfo(boost::format(Y("The last timecode processed before the error was encountered was %1%.\n")) % format_timecode(m_last_timecode));
    m_last_timecode = -1;
  }

  if (m_debug_resync)
    mxinfo(boost::format("kax_file::resync_to_level1_element(): starting at %1% potential ID %|2$08x|\n") % m_resync_start_pos % actual_id);

  while (m_in->getFilePointer() < m_file_size) {
    int64_t now = mtx::sys::get_current_time_millis();
    if ((now - start_time) >= 10000) {
      mxinfo(boost::format("Still resyncing at position %1%.\n") % m_in->getFilePointer());
      start_time = now;
    }

    actual_id = (actual_id << 8) | m_in->read_uint8();

    if (   ((0 != wanted_id) && (wanted_id != actual_id))
        || ((0 == wanted_id) && !is_level1_element_id(vint_c(actual_id, 4))))
      continue;

    uint64_t current_start_pos = m_in->getFilePointer() - 4;
    uint64_t element_pos       = current_start_pos;
    unsigned int num_headers   = 1;
    bool valid_unknown_size    = false;

    if (m_debug_resync)
      mxinfo(boost::format("kax_file::resync_to_level1_element(): byte-for-byte search, found level 1 ID %|2$x| at %1%\n") % current_start_pos % actual_id);

    try {
      unsigned int idx;
      for (idx = 0; 3 > idx; ++idx) {
        vint_c length = vint_c::read(m_in);

        if (m_debug_resync)
          mxinfo(boost::format("kax_file::resync_to_level1_element():   read ebml length %1%/%2% valid? %3% unknown? %4%\n")
                 % length.m_value % length.m_coded_size % length.is_valid() % length.is_unknown());

        if (length.is_unknown()) {
          valid_unknown_size = true;
          break;
        }

        if (   !length.is_valid()
            || ((element_pos + length.m_value + length.m_coded_size + 2 * 4) >= m_file_size)
            || !m_in->setFilePointer2(element_pos + 4 + length.m_value + length.m_coded_size, seek_beginning))
          break;

        element_pos      = m_in->getFilePointer();
        uint32_t next_id = m_in->read_uint32_be();

        if (m_debug_resync)
          mxinfo(boost::format("kax_file::resync_to_level1_element():   next ID is %|1$x| at %2%\n") % next_id % element_pos);

        if (   ((0 != wanted_id) && (wanted_id != next_id))
            || ((0 == wanted_id) && !is_level1_element_id(vint_c(next_id, 4))))
          break;

        ++num_headers;
      }
    } catch (...) {
    }

    if ((4 == num_headers) || valid_unknown_size) {
      mxinfo(boost::format(Y("Resyncing successful at position %1%.\n")) % current_start_pos);
      m_in->setFilePointer(current_start_pos, seek_beginning);
      return read_next_level1_element(wanted_id, is_cluster_id);
    }

    m_in->setFilePointer(current_start_pos + 4, seek_beginning);
  }

  mxinfo(Y("Resync failed: no valid Matroska level 1 element found.\n"));

  return nullptr;
}
Esempio n. 12
0
bool
kax_file_c::is_global_element_id(vint_c id) const {
  return (EBML_ID_VALUE(EBML_ID(EbmlVoid))  == id.m_value)
    ||   (EBML_ID_VALUE(EBML_ID(EbmlCrc32)) == id.m_value);
}
Esempio n. 13
0
/*!
  \todo only put the Blocks written in the cue entries
*/
filepos_t KaxCluster::Render(IOCallback & output, KaxCues & CueToUpdate, bool bSaveDefault)
{
  filepos_t Result = 0;
  size_t Index;
  EBML_MASTER_ITERATOR TrkItr, Itr;

  // update the Timecode of the Cluster before writing
  KaxClusterTimecode * Timecode = static_cast<KaxClusterTimecode *>(this->FindElt(EBML_INFO(KaxClusterTimecode)));
  *static_cast<EbmlUInteger *>(Timecode) = GlobalTimecode() / GlobalTimecodeScale();

  if (Blobs.size() == 0) {
    // old-school direct KaxBlockGroup

    // SilentTracks handling
    // check the parent cluster for existing tracks and see if they are contained in this cluster or not
    if (bSilentTracksUsed) {
      KaxTracks & MyTracks = *static_cast<KaxTracks *>(ParentSegment->FindElt(EBML_INFO(KaxTracks)));
      for (TrkItr = MyTracks.begin(); TrkItr != MyTracks.end(); ++TrkItr) {
        if (EbmlId(*(*TrkItr)) == EBML_ID(KaxTrackEntry)) {
          KaxTrackEntry & entry = *static_cast<KaxTrackEntry *>(*TrkItr);
          uint32 tracknum = entry.TrackNumber();
          for (Itr = begin(); Itr != end(); ++Itr) {
            if (EbmlId(*(*Itr)) == EBML_ID(KaxBlockGroup)) {
              KaxBlockGroup & group = *static_cast<KaxBlockGroup *>(*Itr);
              if (group.TrackNumber() == tracknum)
                break; // this track is used
            }
          }
          // the track wasn't found in this cluster
          if (Itr == end()) {
            KaxClusterSilentTracks * SilentTracks = static_cast<KaxClusterSilentTracks *>(this->FindFirstElt(EBML_INFO(KaxClusterSilentTracks)));
            assert(SilentTracks != NULL); // the flag bSilentTracksUsed should be set when creating the Cluster
            KaxClusterSilentTrackNumber * trackelt = static_cast<KaxClusterSilentTrackNumber *>(SilentTracks->AddNewElt(EBML_INFO(KaxClusterSilentTrackNumber)));
            *static_cast<EbmlUInteger *>(trackelt) = tracknum;
          }
        }
      }
    }

    Result = EbmlMaster::Render(output, bSaveDefault);
    // For all Blocks add their position on the CueEntry

    for (Itr = begin(); Itr != end(); ++Itr) {
      if (EbmlId(*(*Itr)) == EBML_ID(KaxBlockGroup)) {
        CueToUpdate.PositionSet(*static_cast<const KaxBlockGroup *>(*Itr));
      }
    }
  } else {
    // new school, using KaxBlockBlob
    for (Index = 0; Index<Blobs.size(); Index++) {
#if MATROSKA_VERSION >= 2
      if (Blobs[Index]->IsSimpleBlock())
        PushElement( (KaxSimpleBlock&) *Blobs[Index] );
      else
#endif
        PushElement( (KaxBlockGroup&) *Blobs[Index] );
    }

    // SilentTracks handling
    // check the parent cluster for existing tracks and see if they are contained in this cluster or not
    if (bSilentTracksUsed) {
      KaxTracks & MyTracks = *static_cast<KaxTracks *>(ParentSegment->FindElt(EBML_INFO(KaxTracks)));
      for (TrkItr = MyTracks.begin(); TrkItr != MyTracks.end(); ++TrkItr) {
        if (EbmlId(*(*TrkItr)) == EBML_ID(KaxTrackEntry)) {
          KaxTrackEntry & entry = *static_cast<KaxTrackEntry *>(*TrkItr);
          uint32 tracknum = entry.TrackNumber();
          for (Index = 0; Index<Blobs.size(); Index++) {
            if (((KaxInternalBlock&)*Blobs[Index]).TrackNum() == tracknum)
              break; // this track is used
          }
          // the track wasn't found in this cluster
          if (Index == ListSize()) {
            KaxClusterSilentTracks * SilentTracks = static_cast<KaxClusterSilentTracks *>(this->FindFirstElt(EBML_INFO(KaxClusterSilentTracks)));
            assert(SilentTracks != NULL); // the flag bSilentTracksUsed should be set when creating the Cluster
            KaxClusterSilentTrackNumber * trackelt = static_cast<KaxClusterSilentTrackNumber *>(SilentTracks->AddNewElt(EBML_INFO(KaxClusterSilentTrackNumber)));
            *static_cast<EbmlUInteger *>(trackelt) = tracknum;
          }
        }
      }
    }

    Result = EbmlMaster::Render(output, bSaveDefault);

    // For all Blocks add their position on the CueEntry
    for (Index = 0; Index<Blobs.size(); Index++) {
      CueToUpdate.PositionSet(*Blobs[Index]);
    }

    Blobs.clear();
  }

  return Result;
}
Esempio n. 14
0
/*!
	\brief Method to help reading a Master element and all subsequent children quickly
	\todo add an option to discard even unknown elements
	\todo handle when a mandatory element is not found
*/
void EbmlMaster::Read(EbmlStream & inDataStream, const EbmlSemanticContext & sContext, int & UpperEltFound, EbmlElement * & FoundElt, bool AllowDummyElt, ScopeMode ReadFully)
{
	if (ReadFully != SCOPE_NO_DATA)
	{
		EbmlElement * ElementLevelA;
		// remove all existing elements, including the mandatory ones...
		size_t Index;
		for (Index=0; Index<ElementList.size(); Index++) {
			if (!(*ElementList[Index]).IsLocked()) {
				delete ElementList[Index];
			}
		}
		ElementList.clear();
		uint64 MaxSizeToRead;

		if (IsFiniteSize())
			MaxSizeToRead = GetSize();
		else
			MaxSizeToRead = 0x7FFFFFFF;

		// read blocks and discard the ones we don't care about
		if (MaxSizeToRead > 0)
		{
			inDataStream.I_O().setFilePointer(GetSizePosition() + GetSizeLength(), seek_beginning);
			ElementLevelA = inDataStream.FindNextElement(sContext, UpperEltFound, MaxSizeToRead, AllowDummyElt);
			while (ElementLevelA != NULL && UpperEltFound <= 0 && MaxSizeToRead > 0) {
				if (IsFiniteSize())
					MaxSizeToRead = GetEndPosition() - ElementLevelA->GetEndPosition(); // even if it's the default value
				if (!AllowDummyElt && ElementLevelA->IsDummy()) {
					ElementLevelA->SkipData(inDataStream, sContext);
					delete ElementLevelA; // forget this unknown element
				} else {
					// more logical to do it afterward
					ElementList.push_back(ElementLevelA);

					ElementLevelA->Read(inDataStream, EBML_CONTEXT(ElementLevelA), UpperEltFound, FoundElt, AllowDummyElt, ReadFully);

					// just in case
					ElementLevelA->SkipData(inDataStream, EBML_CONTEXT(ElementLevelA));
				}

				if (UpperEltFound > 0) {
					UpperEltFound--;
					if (UpperEltFound > 0 || MaxSizeToRead <= 0)
						goto processCrc;
					ElementLevelA = FoundElt;
					continue;
				} 
				
				if (UpperEltFound < 0) {
					UpperEltFound++;
					if (UpperEltFound < 0)
						goto processCrc;
				}

				if (MaxSizeToRead <= 0)
					goto processCrc;// this level is finished
				
				ElementLevelA = inDataStream.FindNextElement(sContext, UpperEltFound, MaxSizeToRead, AllowDummyElt);
			}
			if (UpperEltFound > 0) {
				FoundElt = ElementLevelA;
			}
		}
	processCrc:
        EBML_MASTER_ITERATOR Itr, CrcItr;
        for (Itr = ElementList.begin(); Itr != ElementList.end();) {
			if ((EbmlId)(*(*Itr)) == EBML_ID(EbmlCrc32)) {
				bChecksumUsed = true;
				// remove the element
				Checksum = *(static_cast<EbmlCrc32*>(*Itr));
                CrcItr = Itr;
                break;
			}
            ++Itr;
		}
        if (bChecksumUsed)
        {
		    delete *CrcItr;
		    Remove(CrcItr);
        }
		SetValueIsSet();
	}
}