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; }
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; }
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; }
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; }
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; }
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; }