/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "VideoUtils.h" #include "MediaResource.h" #include "mozilla/dom/TimeRanges.h" #include "nsMathUtils.h" #include "mozilla/StandardInteger.h" // Converts from number of audio frames to microseconds, given the specified // audio rate. CheckedInt64 FramesToUsecs(int64_t aFrames, uint32_t aRate) { return (CheckedInt64(aFrames) * USECS_PER_S) / aRate; } // Converts from microseconds to number of audio frames, given the specified // audio rate. CheckedInt64 UsecsToFrames(int64_t aUsecs, uint32_t aRate) { return (CheckedInt64(aUsecs) * aRate) / USECS_PER_S; } static int32_t ConditionDimension(float aValue) { // This will exclude NaNs and too-big values. if (aValue > 1.0 && aValue <= INT32_MAX) return int32_t(NS_round(aValue)); return 0; } void ScaleDisplayByAspectRatio(nsIntSize& aDisplay, float aAspectRatio) { if (aAspectRatio > 1.0) { // Increase the intrinsic width aDisplay.width = ConditionDimension(aAspectRatio * aDisplay.width); } else { // Increase the intrinsic height aDisplay.height = ConditionDimension(aDisplay.height / aAspectRatio); } } static int64_t BytesToTime(int64_t offset, int64_t length, int64_t durationUs) { NS_ASSERTION(length > 0, "Must have positive length"); double r = double(offset) / double(length); if (r > 1.0) r = 1.0; return int64_t(double(durationUs) * r); } void GetEstimatedBufferedTimeRanges(mozilla::MediaResource* aStream, int64_t aDurationUsecs, mozilla::dom::TimeRanges* aOutBuffered) { // Nothing to cache if the media takes 0us to play. if (aDurationUsecs <= 0 || !aStream || !aOutBuffered) return; // Special case completely cached files. This also handles local files. if (aStream->IsDataCachedToEndOfResource(0)) { aOutBuffered->Add(0, double(aDurationUsecs) / USECS_PER_S); return; } int64_t totalBytes = aStream->GetLength(); // If we can't determine the total size, pretend that we have nothing // buffered. This will put us in a state of eternally-low-on-undecoded-data // which is not great, but about the best we can do. if (totalBytes <= 0) return; int64_t startOffset = aStream->GetNextCachedData(0); while (startOffset >= 0) { int64_t endOffset = aStream->GetCachedDataEnd(startOffset); // Bytes [startOffset..endOffset] are cached. NS_ASSERTION(startOffset >= 0, "Integer underflow in GetBuffered"); NS_ASSERTION(endOffset >= 0, "Integer underflow in GetBuffered"); int64_t startUs = BytesToTime(startOffset, totalBytes, aDurationUsecs); int64_t endUs = BytesToTime(endOffset, totalBytes, aDurationUsecs); if (startUs != endUs) { aOutBuffered->Add(double(startUs) / USECS_PER_S, double(endUs) / USECS_PER_S); } startOffset = aStream->GetNextCachedData(endOffset); } return; }