2012-05-21 04:12:37 -07:00
|
|
|
/* 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/. */
|
2010-08-17 19:17:50 -07:00
|
|
|
|
2010-08-12 19:28:15 -07:00
|
|
|
#include "VideoUtils.h"
|
2012-09-02 15:56:29 -07:00
|
|
|
#include "MediaResource.h"
|
2013-03-02 11:14:44 -08:00
|
|
|
#include "mozilla/dom/TimeRanges.h"
|
2011-06-23 15:08:54 -07:00
|
|
|
#include "nsMathUtils.h"
|
2010-08-12 19:28:15 -07:00
|
|
|
|
2012-02-29 19:56:43 -08:00
|
|
|
#include "mozilla/StandardInteger.h"
|
2012-01-11 00:23:07 -08:00
|
|
|
|
2011-09-26 20:31:18 -07:00
|
|
|
// Converts from number of audio frames to microseconds, given the specified
|
2010-08-12 19:28:15 -07:00
|
|
|
// audio rate.
|
2012-08-22 08:56:38 -07:00
|
|
|
CheckedInt64 FramesToUsecs(int64_t aFrames, uint32_t aRate) {
|
2012-02-22 04:28:06 -08:00
|
|
|
return (CheckedInt64(aFrames) * USECS_PER_S) / aRate;
|
2010-08-12 19:28:15 -07:00
|
|
|
}
|
|
|
|
|
2011-09-26 20:31:18 -07:00
|
|
|
// Converts from microseconds to number of audio frames, given the specified
|
2010-08-12 19:28:15 -07:00
|
|
|
// audio rate.
|
2012-08-22 08:56:38 -07:00
|
|
|
CheckedInt64 UsecsToFrames(int64_t aUsecs, uint32_t aRate) {
|
2012-02-22 04:28:06 -08:00
|
|
|
return (CheckedInt64(aUsecs) * aRate) / USECS_PER_S;
|
2010-08-12 19:28:15 -07:00
|
|
|
}
|
2011-06-23 15:08:54 -07:00
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
static int32_t ConditionDimension(float aValue)
|
2011-06-23 15:08:54 -07:00
|
|
|
{
|
|
|
|
// This will exclude NaNs and too-big values.
|
2012-09-27 23:57:33 -07:00
|
|
|
if (aValue > 1.0 && aValue <= INT32_MAX)
|
2012-08-22 08:56:38 -07:00
|
|
|
return int32_t(NS_round(aValue));
|
2011-06-23 15:08:54 -07:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2012-09-02 15:56:29 -07:00
|
|
|
|
|
|
|
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,
|
2013-03-02 11:14:44 -08:00
|
|
|
mozilla::dom::TimeRanges* aOutBuffered)
|
2012-09-02 15:56:29 -07:00
|
|
|
{
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|