예제 #1
0
bool SkeletonState::DecodeHeader(ogg_packet* aPacket)
{
  nsAutoRef<ogg_packet> autoRelease(aPacket);
  if (IsSkeletonBOS(aPacket)) {
    uint16_t verMajor = LittleEndian::readUint16(aPacket->packet + SKELETON_VERSION_MAJOR_OFFSET);
    uint16_t verMinor = LittleEndian::readUint16(aPacket->packet + SKELETON_VERSION_MINOR_OFFSET);

    // Read the presentation time. We read this before the version check as the
    // presentation time exists in all versions.
    int64_t n = LittleEndian::readInt64(aPacket->packet + SKELETON_PRESENTATION_TIME_NUMERATOR_OFFSET);
    int64_t d = LittleEndian::readInt64(aPacket->packet + SKELETON_PRESENTATION_TIME_DENOMINATOR_OFFSET);
    mPresentationTime = d == 0 ? 0 : (static_cast<float>(n) / static_cast<float>(d)) * USECS_PER_S;

    mVersion = SKELETON_VERSION(verMajor, verMinor);
    // We can only care to parse Skeleton version 4.0+.
    if (mVersion < SKELETON_VERSION(4,0) ||
        mVersion >= SKELETON_VERSION(5,0) ||
        aPacket->bytes < SKELETON_4_0_MIN_HEADER_LEN)
      return false;

    // Extract the segment length.
    mLength = LittleEndian::readInt64(aPacket->packet + SKELETON_FILE_LENGTH_OFFSET);

    LOG(PR_LOG_DEBUG, ("Skeleton segment length: %lld", mLength));

    // Initialize the serialno-to-index map.
    return true;
  } else if (IsSkeletonIndex(aPacket) && mVersion >= SKELETON_VERSION(4,0)) {
    return DecodeIndex(aPacket);
  } else if (aPacket->e_o_s) {
    mDoneReadingHeaders = true;
    return true;
  }
  return true;
}
예제 #2
0
nsresult nsSkeletonState::GetDuration(const nsTArray<PRUint32>& aTracks,
                                      PRInt64& aDuration)
{
  if (!mActive ||
      mVersion < SKELETON_VERSION(4,0) ||
      !HasIndex() ||
      aTracks.Length() == 0)
  {
    return NS_ERROR_FAILURE;
  }
  PRInt64 endTime = PR_INT64_MIN;
  PRInt64 startTime = PR_INT64_MAX;
  for (PRUint32 i=0; i<aTracks.Length(); i++) {
    nsKeyFrameIndex* index = nsnull;
    mIndex.Get(aTracks[i], &index);
    if (!index) {
      // Can't get the timestamps for one of the required tracks, fail.
      return NS_ERROR_FAILURE;
    }
    if (index->mEndTime > endTime) {
      endTime = index->mEndTime;
    }
    if (index->mStartTime < startTime) {
      startTime = index->mStartTime;
    }
  }
  NS_ASSERTION(endTime > startTime, "Duration must be positive");
  return AddOverflow(endTime, -startTime, aDuration) ? NS_OK : NS_ERROR_FAILURE;
}
예제 #3
0
nsresult nsSkeletonState::IndexedSeekTarget(PRInt64 aTarget,
                                            nsTArray<PRUint32>& aTracks,
                                            nsSeekTarget& aResult)
{
  if (!mActive || mVersion < SKELETON_VERSION(4,0)) {
    return NS_ERROR_FAILURE;
  }
  // Loop over all requested tracks' indexes, and get the keypoint for that
  // seek target. Record the keypoint with the lowest offset, this will be
  // our seek result. User must seek to the one with lowest offset to ensure we
  // pass "keyframes" on all tracks when we decode forwards to the seek target.
  nsSeekTarget r;
  for (PRUint32 i=0; i<aTracks.Length(); i++) {
    nsKeyPoint k;
    if (NS_SUCCEEDED(IndexedSeekTargetForTrack(aTracks[i], aTarget, k)) &&
        k.mOffset < r.mKeyPoint.mOffset)
    {
      r.mKeyPoint = k;
      r.mSerial = aTracks[i];
    }
  }
  if (r.IsNull()) {
    return NS_ERROR_FAILURE;
  }
  LOG(PR_LOG_DEBUG, ("Indexed seek target for time %lld is offset %lld",
                     aTarget, r.mKeyPoint.mOffset));
  aResult = r;
  return NS_OK;
}
예제 #4
0
nsresult SkeletonState::GetDuration(const nsTArray<uint32_t>& aTracks,
                                      int64_t& aDuration)
{
  if (!mActive ||
      mVersion < SKELETON_VERSION(4,0) ||
      !HasIndex() ||
      aTracks.Length() == 0)
  {
    return NS_ERROR_FAILURE;
  }
  int64_t endTime = INT64_MIN;
  int64_t startTime = INT64_MAX;
  for (uint32_t i=0; i<aTracks.Length(); i++) {
    nsKeyFrameIndex* index = nullptr;
    mIndex.Get(aTracks[i], &index);
    if (!index) {
      // Can't get the timestamps for one of the required tracks, fail.
      return NS_ERROR_FAILURE;
    }
    if (index->mEndTime > endTime) {
      endTime = index->mEndTime;
    }
    if (index->mStartTime < startTime) {
      startTime = index->mStartTime;
    }
  }
  NS_ASSERTION(endTime > startTime, "Duration must be positive");
  CheckedInt64 duration = CheckedInt64(endTime) - startTime;
  aDuration = duration.isValid() ? duration.value() : 0;
  return duration.isValid() ? NS_OK : NS_ERROR_FAILURE;
}
예제 #5
0
PRBool nsSkeletonState::DecodeHeader(ogg_packet* aPacket)
{
  if (IsSkeletonBOS(aPacket)) {
    PRUint16 verMajor = LEUint16(aPacket->packet + SKELETON_VERSION_MAJOR_OFFSET);
    PRUint16 verMinor = LEUint16(aPacket->packet + SKELETON_VERSION_MINOR_OFFSET);

    // Read the presentation time. We read this before the version check as the
    // presentation time exists in all versions.
    PRInt64 n = LEInt64(aPacket->packet + SKELETON_PRESENTATION_TIME_NUMERATOR_OFFSET);
    PRInt64 d = LEInt64(aPacket->packet + SKELETON_PRESENTATION_TIME_DENOMINATOR_OFFSET);
    mPresentationTime = d == 0 ? 0 : (static_cast<float>(n) / static_cast<float>(d)) * USECS_PER_S;

    mVersion = SKELETON_VERSION(verMajor, verMinor);
    if (mVersion < SKELETON_VERSION(4,0) ||
        mVersion >= SKELETON_VERSION(5,0) ||
        aPacket->bytes < SKELETON_4_0_MIN_HEADER_LEN)
    {
      // We can only care to parse Skeleton version 4.0+.
      mActive = PR_FALSE;
      return mDoneReadingHeaders = PR_TRUE;
    }

    // Extract the segment length.
    mLength = LEInt64(aPacket->packet + SKELETON_FILE_LENGTH_OFFSET);

    LOG(PR_LOG_DEBUG, ("Skeleton segment length: %lld", mLength));

    // Initialize the serianlno-to-index map.
    PRBool init = mIndex.Init();
    if (!init) {
      NS_WARNING("Failed to initialize Ogg skeleton serialno-to-index map");
      mActive = PR_FALSE;
      return mDoneReadingHeaders = PR_TRUE;
    }
    mActive = PR_TRUE;
  } else if (IsSkeletonIndex(aPacket) && mVersion >= SKELETON_VERSION(4,0)) {
    if (!DecodeIndex(aPacket)) {
      // Failed to parse index, or invalid/hostile index. DecodeIndex() will
      // have deactivated the track.
      return mDoneReadingHeaders = PR_TRUE;
    }

  } else if (aPacket->e_o_s) {
    mDoneReadingHeaders = PR_TRUE;
  }
  return mDoneReadingHeaders;
}
예제 #6
0
PRBool nsSkeletonState::DecodeHeader(ogg_packet* aPacket)
{
  if (IsSkeletonBOS(aPacket)) {
    PRUint16 verMajor = LEUint16(aPacket->packet + SKELETON_VERSION_MAJOR_OFFSET);
    PRUint16 verMinor = LEUint16(aPacket->packet + SKELETON_VERSION_MINOR_OFFSET);
    mVersion = SKELETON_VERSION(verMajor, verMinor);
    if (mVersion < SKELETON_VERSION(4,0) ||
        mVersion >= SKELETON_VERSION(5,0) ||
        aPacket->bytes < SKELETON_4_0_MIN_HEADER_LEN)
    {
      // We can only care to parse Skeleton version 4.0+.
      mActive = PR_FALSE;
      return mDoneReadingHeaders = PR_TRUE;
    }

    // Extract the segment length.
    mLength = LEInt64(aPacket->packet + SKELETON_FILE_LENGTH_OFFSET);

    LOG(PR_LOG_DEBUG, ("Skeleton segment length: %lld", mLength));

    // Initialize the serianlno-to-index map.
    PRBool init = mIndex.Init();
    if (!init) {
      NS_WARNING("Failed to initialize Ogg skeleton serialno-to-index map");
      mActive = PR_FALSE;
      return mDoneReadingHeaders = PR_TRUE;
    }
    mActive = PR_TRUE;
  } else if (IsSkeletonIndex(aPacket) && mVersion >= SKELETON_VERSION(4,0)) {
    if (!DecodeIndex(aPacket)) {
      // Failed to parse index, or invalid/hostile index. DecodeIndex() will
      // have deactivated the track.
      return mDoneReadingHeaders = PR_TRUE;
    }

  } else if (aPacket->e_o_s) {
    mDoneReadingHeaders = PR_TRUE;
  }
  return mDoneReadingHeaders;
}