Beispiel #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;
}
Beispiel #2
0
EbmlElement *
kax_file_c::read_one_element() {
  if (m_segment_end && (m_in->getFilePointer() >= m_segment_end))
    return nullptr;

  int upper_lvl_el = 0;
  EbmlElement *l1  = m_es->FindNextElement(EBML_CLASS_CONTEXT(KaxSegment), upper_lvl_el, 0xFFFFFFFFL, true);

  if (!l1)
    return nullptr;

  const EbmlCallbacks *callbacks = find_ebml_callbacks(EBML_INFO(KaxSegment), EbmlId(*l1));
  if (!callbacks)
    callbacks = &EBML_CLASS_CALLBACK(KaxSegment);

  EbmlElement *l2 = nullptr;
  try {
    l1->Read(*m_es.get(), EBML_INFO_CONTEXT(*callbacks), upper_lvl_el, l2, true);

  } catch (libebml::CRTError &e) {
    mxdebug_if(m_debug_resync, boost::format("exception reading element data: %1% (%2%)\n") % e.what() % e.getError());
    m_in->setFilePointer(l1->GetElementPosition() + 1);
    delete l1;
    return nullptr;
  }

  unsigned long element_size = get_element_size(l1);
  if (m_debug_resync)
    mxinfo(boost::format("kax_file::read_one_element(): read element at %1% calculated size %2% stored size %3%\n")
           % l1->GetElementPosition() % element_size % (l1->IsFiniteSize() ? (boost::format("%1%") % l1->ElementSize()).str() : std::string("unknown")));
  m_in->setFilePointer(l1->GetElementPosition() + element_size, seek_beginning);

  return l1;
}
Beispiel #3
0
uint16 KaxCueTrackPositions::TrackNumber() const
{
  const KaxCueTrack *aTrack = static_cast<const KaxCueTrack *>(FindFirstElt(EBML_INFO(KaxCueTrack)));
  if (aTrack == NULL)
    return 0;

  return uint16(*aTrack);
}
Beispiel #4
0
bool KaxCuePoint::Timecode(uint64 & aTimecode, uint64 GlobalTimecodeScale) const
{
  const KaxCueTime *aTime = static_cast<const KaxCueTime *>(FindFirstElt(EBML_INFO(KaxCueTime)));
  if (aTime == NULL)
    return false;
  aTimecode = uint64(*aTime) * GlobalTimecodeScale;
  return true;
}
Beispiel #5
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();
}
Beispiel #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;
}
Beispiel #7
0
void KaxCuePoint::PositionSet(const KaxBlockBlob & BlobReference, uint64 GlobalTimecodeScale)
{
  const KaxInternalBlock &BlockReference = BlobReference;

  // fill me
  KaxCueTime & NewTime = GetChild<KaxCueTime>(*this);
  *static_cast<EbmlUInteger*>(&NewTime) = BlockReference.GlobalTimecode() / GlobalTimecodeScale;

  KaxCueTrackPositions & NewPositions = AddNewChild<KaxCueTrackPositions>(*this);
  KaxCueTrack & TheTrack = GetChild<KaxCueTrack>(NewPositions);
  *static_cast<EbmlUInteger*>(&TheTrack) = BlockReference.TrackNum();

  KaxCueClusterPosition & TheClustPos = GetChild<KaxCueClusterPosition>(NewPositions);
  *static_cast<EbmlUInteger*>(&TheClustPos) = BlockReference.ClusterPosition();

#if 0 // MATROSKA_VERSION >= 2
  // handle reference use
  if (BlockReference.ReferenceCount() != 0) {
    unsigned int i;
    for (i=0; i<BlockReference.ReferenceCount(); i++) {
      KaxCueReference & NewRefs = AddNewChild<KaxCueReference>(NewPositions);
      NewRefs.AddReference(BlockReference.Reference(i).RefBlock(), GlobalTimecodeScale);
    }
  }
#endif // MATROSKA_VERSION

#if MATROSKA_VERSION >= 2
  if (!BlobReference.IsSimpleBlock()) {
    const KaxBlockGroup &BlockGroup = BlobReference;
    const KaxCodecState *CodecState = static_cast<KaxCodecState *>(BlockGroup.FindFirstElt(EBML_INFO(KaxCodecState)));
    if (CodecState != NULL) {
      KaxCueCodecState &CueCodecState = AddNewChild<KaxCueCodecState>(NewPositions);
      *static_cast<EbmlUInteger*>(&CueCodecState) = BlockGroup.GetParentCluster()->GetParentSegment()->GetRelativePosition(CodecState->GetElementPosition());
    }
  }
#endif // MATROSKA_VERSION

  SetValueIsSet();
}
Beispiel #8
0
START_LIBMATROSKA_NAMESPACE

/*!
  \todo handle codec state checking
  \todo remove duplicate references (reference to 2 frames that each reference the same frame)
*/
void KaxCuePoint::PositionSet(const KaxBlockGroup & BlockReference, uint64 GlobalTimecodeScale)
{
  // fill me
  KaxCueTime & NewTime = GetChild<KaxCueTime>(*this);
  *static_cast<EbmlUInteger*>(&NewTime) = BlockReference.GlobalTimecode() / GlobalTimecodeScale;

  KaxCueTrackPositions & NewPositions = AddNewChild<KaxCueTrackPositions>(*this);
  KaxCueTrack & TheTrack = GetChild<KaxCueTrack>(NewPositions);
  *static_cast<EbmlUInteger*>(&TheTrack) = BlockReference.TrackNumber();

  KaxCueClusterPosition & TheClustPos = GetChild<KaxCueClusterPosition>(NewPositions);
  *static_cast<EbmlUInteger*>(&TheClustPos) = BlockReference.ClusterPosition();

#if MATROSKA_VERSION >= 2
  // handle reference use
  if (BlockReference.ReferenceCount() != 0) {
    unsigned int i;
    for (i=0; i<BlockReference.ReferenceCount(); i++) {
      KaxCueReference & NewRefs = AddNewChild<KaxCueReference>(NewPositions);
      NewRefs.AddReference(BlockReference.Reference(i).RefBlock(), GlobalTimecodeScale);
    }
  }

  KaxCodecState *CodecState = static_cast<KaxCodecState *>(BlockReference.FindFirstElt(EBML_INFO(KaxCodecState)));
  if (CodecState != NULL) {
    KaxCueCodecState &CueCodecState = AddNewChild<KaxCueCodecState>(NewPositions);
    *static_cast<EbmlUInteger*>(&CueCodecState) = BlockReference.GetParentCluster()->GetParentSegment()->GetRelativePosition(CodecState->GetElementPosition());
  }
#endif // MATROSKA_VERSION

  SetValueIsSet();
}
Beispiel #9
0
uint64 KaxCueTrackPositions::ClusterPosition() const
{
  const KaxCueClusterPosition *aPos = static_cast<const KaxCueClusterPosition *>(FindFirstElt(EBML_INFO(KaxCueClusterPosition)));
  if (aPos == NULL)
    return 0;

  return uint64(*aPos);
}
Beispiel #10
0
/*!
  \brief return the position of the Cluster to load
*/
const KaxCueTrackPositions * KaxCuePoint::GetSeekPosition() const
{
  const KaxCueTrackPositions * result = NULL;
  uint64 aPosition = EBML_PRETTYLONGINT(0xFFFFFFFFFFFFFFF);
  // find the position of the "earlier" Cluster
  const KaxCueTrackPositions *aPoss = static_cast<const KaxCueTrackPositions *>(FindFirstElt(EBML_INFO(KaxCueTrackPositions)));
  while (aPoss != NULL) {
    const KaxCueClusterPosition *aPos = static_cast<const KaxCueClusterPosition *>(aPoss->FindFirstElt(EBML_INFO(KaxCueClusterPosition)));
    if (aPos != NULL && uint64(*aPos) < aPosition) {
      aPosition = uint64(*aPos);
      result = aPoss;
    }

    aPoss = static_cast<const KaxCueTrackPositions *>(FindNextElt(*aPoss));
  }
  return result;
}
Beispiel #11
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;
}
Beispiel #12
0
**
**********************************************************************/

/*!
	\file
	\version \$Id: 51041ecb39a4fd1d3ef7982c26f4ebed686b2637 $
	\author Steve Lhomme     <robux4 @ users.sf.net>
*/
#include "ebml/EbmlContexts.h"
#include "ebml/EbmlCrc32.h"
#include "ebml/EbmlVoid.h"

START_LIBEBML_NAMESPACE

static const EbmlSemantic EbmlGlobal_ContextList[2] =
{
	EbmlSemantic(false, false, EBML_INFO(EbmlCrc32)),   ///< EbmlCrc32
	EbmlSemantic(false, false, EBML_INFO(EbmlVoid)),    ///< EbmlVoid
};

const EbmlSemanticContext Context_EbmlGlobal = EbmlSemanticContext(0, NULL, NULL, *GetEbmlGlobal_Context, NULL);

static const EbmlSemanticContext EbmlGlobal_Context = EbmlSemanticContext(countof(EbmlGlobal_ContextList), EbmlGlobal_ContextList, NULL, *GetEbmlGlobal_Context, NULL);

const EbmlSemanticContext & GetEbmlGlobal_Context()
{
	return EbmlGlobal_Context;
}

END_LIBEBML_NAMESPACE