Bug 462959 - Implement HTMLMediaElement.played; r=kinetik

This commit is contained in:
Paul ADENOT 2011-07-03 11:53:38 +02:00
Родитель bcfd45f55e
Коммит e0f3c8f562
7 изменённых файлов: 111 добавлений и 7 удалений

Просмотреть файл

@ -50,6 +50,7 @@
#include "nsIObserver.h"
#include "ImageLayers.h"
#include "nsAudioStream.h"
#include "nsTimeRanges.h"
// Define to output information on decoding and painting framerate
/* #define DEBUG_FRAME_RATE 1 */
@ -624,6 +625,12 @@ protected:
// a media and element same-origin check.
PRBool mAllowAudioData;
// Range of time played.
nsTimeRanges mPlayed;
// Temporary variable for storing a time, when the stream starts to play
double mCurrentPlayRangeStart;
// If true then we have begun downloading the media content.
// Set to false when completed, or not yet started.
PRPackedBool mBegun;

Просмотреть файл

@ -39,7 +39,6 @@
#include "nsIDOMHTMLMediaElement.h"
#include "nsIDOMHTMLSourceElement.h"
#include "nsHTMLMediaElement.h"
#include "nsTimeRanges.h"
#include "nsGenericHTMLElement.h"
#include "nsPresContext.h"
#include "nsIPresShell.h"
@ -1092,6 +1091,16 @@ NS_IMETHODIMP nsHTMLMediaElement::SetCurrentTime(double aCurrentTime)
{
StopSuspendingAfterFirstFrame();
if (mCurrentPlayRangeStart != -1) {
double oldCurrentTime = 0;
GetCurrentTime(&oldCurrentTime);
LOG(PR_LOG_DEBUG, ("Adding a range: [%f, %f]", mCurrentPlayRangeStart, oldCurrentTime));
// Multiple seek without playing
if (mCurrentPlayRangeStart != oldCurrentTime) {
mPlayed.Add(mCurrentPlayRangeStart, oldCurrentTime);
}
}
if (!mDecoder) {
LOG(PR_LOG_DEBUG, ("%p SetCurrentTime(%f) failed: no decoder", this, aCurrentTime));
return NS_ERROR_DOM_INVALID_STATE_ERR;
@ -1121,6 +1130,9 @@ NS_IMETHODIMP nsHTMLMediaElement::SetCurrentTime(double aCurrentTime)
LOG(PR_LOG_DEBUG, ("%p SetCurrentTime(%f) starting seek", this, aCurrentTime));
nsresult rv = mDecoder->Seek(clampedTime);
// Start a new range at position we seeked to
mCurrentPlayRangeStart = clampedTime;
// We changed whether we're seeking so we need to AddRemoveSelfReference
AddRemoveSelfReference();
@ -1142,6 +1154,35 @@ NS_IMETHODIMP nsHTMLMediaElement::GetPaused(PRBool *aPaused)
return NS_OK;
}
/* readonly attribute nsIDOMHTMLTimeRanges played; */
NS_IMETHODIMP nsHTMLMediaElement::GetPlayed(nsIDOMTimeRanges** aPlayed)
{
nsRefPtr<nsTimeRanges> ranges = new nsTimeRanges();
PRUint32 timeRangeCount = 0;
mPlayed.GetLength(&timeRangeCount);
for (PRUint32 i = 0; i < timeRangeCount; i++) {
double begin;
double end;
mPlayed.Start(i, &begin);
mPlayed.End(i, &end);
ranges->Add(begin, end);
}
if (mCurrentPlayRangeStart != -1.0) {
double now = 0.0;
GetCurrentTime(&now);
if (mCurrentPlayRangeStart != now) {
ranges->Add(mCurrentPlayRangeStart, now);
}
}
ranges->Normalize();
ranges.forget(aPlayed);
return NS_OK;
}
/* void pause (); */
NS_IMETHODIMP nsHTMLMediaElement::Pause()
{
@ -1280,6 +1321,7 @@ nsHTMLMediaElement::nsHTMLMediaElement(already_AddRefed<nsINodeInfo> aNodeInfo,
mMediaSize(-1,-1),
mLastCurrentTime(0.0),
mAllowAudioData(PR_FALSE),
mCurrentPlayRangeStart(-1.0),
mBegun(PR_FALSE),
mLoadedFirstFrame(PR_FALSE),
mAutoplaying(PR_TRUE),
@ -1380,6 +1422,10 @@ NS_IMETHODIMP nsHTMLMediaElement::Play()
}
}
if (mCurrentPlayRangeStart == -1.0) {
GetCurrentTime(&mCurrentPlayRangeStart);
}
// TODO: If the playback has ended, then the user agent must set
// seek to the effective start.
// TODO: The playback rate must be set to the default playback rate.
@ -2034,6 +2080,13 @@ void nsHTMLMediaElement::PlaybackEnded()
// We changed the state of IsPlaybackEnded which can affect AddRemoveSelfReference
AddRemoveSelfReference();
double end = 0.0;
GetCurrentTime(&end);
if (mCurrentPlayRangeStart != end) {
mPlayed.Add(mCurrentPlayRangeStart, end);
}
mCurrentPlayRangeStart = -1.0;
if (mDecoder && mDecoder->IsInfinite()) {
LOG(PR_LOG_DEBUG, ("%p, got duration by reaching the end of the stream", this));
DispatchAsyncEvent(NS_LITERAL_STRING("durationchange"));
@ -2455,7 +2508,7 @@ void nsHTMLMediaElement::NotifyAddedSource()
}
// A load was paused in the resource selection algorithm, waiting for
// a new source child to be added, resume the resource selction algorithm.
// a new source child to be added, resume the resource selection algorithm.
if (mLoadWaitStatus == WAITING_FOR_SOURCE) {
QueueLoadFromSourceTask();
}

Просмотреть файл

@ -85,3 +85,28 @@ void
nsTimeRanges::Add(double aStart, double aEnd) {
mRanges.AppendElement(TimeRange(aStart,aEnd));
}
void
nsTimeRanges::Normalize() {
if (mRanges.Length() <= 1) {
return;
}
nsAutoTArray<TimeRange, 4> normalized;
mRanges.Sort(CompareTimeRanges());
// This merges the intervals
TimeRange current(mRanges[0]);
for (PRUint32 i = 1; i < mRanges.Length(); i++) {
if (current.mEnd >= mRanges[i].mStart) {
current.mEnd = NS_MAX(current.mEnd, mRanges[i].mEnd);
} else {
normalized.AppendElement(current);
current = mRanges[i];
}
}
normalized.AppendElement(current);
mRanges = normalized;
}

Просмотреть файл

@ -55,6 +55,9 @@ public:
void Add(double aStart, double aEnd);
// See <http://www.whatwg.org/html/#normalized-timeranges-object>.
void Normalize();
private:
struct TimeRange {
@ -65,6 +68,21 @@ private:
double mEnd;
};
struct CompareTimeRanges
{
PRBool Equals(const TimeRange& tr1, const TimeRange& tr2) const
{
return tr1.mStart == tr2.mStart && tr1.mEnd == tr2.mEnd;
}
// Here, we aim at time range normalization. That why we order only by start
// time, since the ranges can overlap.
PRBool LessThan(const TimeRange& tr1, const TimeRange& tr2) const
{
return tr1.mStart < tr2.mStart;
}
};
nsAutoTArray<TimeRange,4> mRanges;
};

Просмотреть файл

@ -52,7 +52,7 @@
* @status UNDER_DEVELOPMENT
*/
[scriptable, uuid(f0d4977c-9632-4fab-bc9b-91c250a6ef96)]
[scriptable, uuid(1f2437f1-6037-40c4-bfb6-105c6c60f0ca)]
interface nsIDOMHTMLAudioElement : nsIDOMHTMLMediaElement
{
// Setup the audio stream for writing

Просмотреть файл

@ -57,7 +57,7 @@
#endif
%}
[scriptable, uuid(d8213322-46d8-47ca-a15c-2abae47ddfde)]
[scriptable, uuid(c8a5f714-97de-4e2c-8394-2397870224bb)]
interface nsIDOMHTMLMediaElement : nsIDOMHTMLElement
{
// error state
@ -89,6 +89,7 @@ interface nsIDOMHTMLMediaElement : nsIDOMHTMLElement
attribute double currentTime;
readonly attribute double duration;
readonly attribute boolean paused;
readonly attribute nsIDOMTimeRanges played;
readonly attribute boolean ended;
readonly attribute boolean mozAutoplayEnabled;
attribute boolean autoplay;

Просмотреть файл

@ -48,15 +48,15 @@
* @status UNDER_DEVELOPMENT
*/
[scriptable, uuid(00c757ec-db7b-477e-95cd-b2a03b0f8634)]
[scriptable, uuid(169f0ff1-511a-453d-86b6-346c1e936122)]
interface nsIDOMHTMLVideoElement : nsIDOMHTMLMediaElement
{
attribute long width;
attribute long width;
attribute long height;
readonly attribute unsigned long videoWidth;
readonly attribute unsigned long videoHeight;
attribute DOMString poster;
// A count of the number of video frames that have demuxed from the media
// resource. If we were playing perfectly, we'd be able to paint this many
// frames.