Пример #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;
}
Пример #2
0
uint64 KaxCluster::GetBlockGlobalTimecode(int16 GlobalSavedTimecode)
{
  if (!bFirstFrameInside) {
    KaxClusterTimecode * Timecode = static_cast<KaxClusterTimecode *>(this->FindElt(EBML_INFO(KaxClusterTimecode)));
    assert (bFirstFrameInside); // use the InitTimecode() hack for now
    MinTimecode = MaxTimecode = PreviousTimecode = *static_cast<EbmlUInteger *>(Timecode);
    bFirstFrameInside = true;
    bPreviousTimecodeIsSet = true;
  }
  return int64(GlobalSavedTimecode * GlobalTimecodeScale()) + GlobalTimecode();
}
Пример #3
0
void KaxCues::PositionSet(const KaxBlockBlob & BlockReference)
{
	// look for the element in the temporary references
	std::vector<const KaxBlockBlob *>::iterator ListIdx;

	for (ListIdx = myTempReferences.begin(); ListIdx != myTempReferences.end(); ListIdx++) {
		if (*ListIdx == &BlockReference) {
			// found, now add the element to the entry list
			KaxCuePoint & NewPoint = AddNewChild<KaxCuePoint>(*this);
			NewPoint.PositionSet(BlockReference, GlobalTimecodeScale());
			myTempReferences.erase(ListIdx);
			break;
		}
	}
}
Пример #4
0
void KaxCues::PositionSet(const KaxBlockGroup & BlockRef)
{
	// look for the element in the temporary references
	std::vector<const KaxBlockBlob *>::iterator ListIdx;

	for (ListIdx = myTempReferences.begin(); ListIdx != myTempReferences.end(); ListIdx++) {
		const KaxInternalBlock &refTmp = **ListIdx;
		if (refTmp.GlobalTimecode() == BlockRef.GlobalTimecode() &&
			refTmp.TrackNum() == BlockRef.TrackNumber()) {
			// found, now add the element to the entry list
			KaxCuePoint & NewPoint = AddNewChild<KaxCuePoint>(*this);
			NewPoint.PositionSet(**ListIdx, GlobalTimecodeScale());
			myTempReferences.erase(ListIdx);
			break;
		}
	}
}
Пример #5
0
/*!
  \brief retrieve the relative
  \todo !!! We need a way to know the TimecodeScale
*/
int16 KaxCluster::GetBlockLocalTimecode(uint64 aGlobalTimecode) const
{
  int64 TimecodeDelay = (int64(aGlobalTimecode) - int64(GlobalTimecode())) / int64(GlobalTimecodeScale());
  assert(TimecodeDelay >= int16(0x8000) && TimecodeDelay <= int16(0x7FFF));
  return int16(TimecodeDelay);
}
Пример #6
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;
}