Bug 855130 - Implement a minimal working subset of the Media Source

Extensions specification.  r=roc
This commit is contained in:
Matthew Gregan 2013-06-21 15:14:42 +12:00
Родитель bbbaf88bb3
Коммит d77cb6c12b
20 изменённых файлов: 1529 добавлений и 0 удалений

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

@ -0,0 +1,35 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef MOZILLA_ASYNCEVENTRUNNER_H_
#define MOZILLA_ASYNCEVENTRUNNER_H_
#include "nsThreadUtils.h"
namespace mozilla {
template <typename T>
class AsyncEventRunnner : public nsRunnable
{
public:
AsyncEventRunnner(T* aTarget, const char* aName)
: mTarget(aTarget)
, mName(aName)
{}
NS_IMETHOD Run()
{
mTarget->DispatchSimpleEvent(mName);
return NS_OK;
}
private:
nsRefPtr<T> mTarget;
const char* mName;
};
} // namespace mozilla
#endif /* MOZILLA_ASYNCEVENTRUNNER_H_ */

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

@ -0,0 +1,18 @@
# 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/.
DEPTH = @DEPTH@
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
FAIL_ON_WARNINGS := 1
include $(DEPTH)/config/autoconf.mk
LIBRARY_NAME = gkconmediasource_s
LIBXUL_LIBRARY = 1
FORCE_STATIC_LIB = 1
include $(topsrcdir)/config/rules.mk

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

@ -0,0 +1,395 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 "MediaSource.h"
#include "mozilla/dom/HTMLMediaElement.h"
#include "MediaSourceInputAdapter.h"
#include "SourceBuffer.h"
#include "SourceBufferList.h"
#include "nsContentUtils.h"
#ifdef PR_LOGGING
PRLogModuleInfo* gMediaSourceLog;
#define LOG(type, msg) PR_LOG(gMediaSourceLog, type, msg)
#else
#define LOG(type, msg)
#endif
namespace mozilla {
namespace dom {
already_AddRefed<nsIInputStream>
MediaSource::CreateInternalStream()
{
nsRefPtr<MediaSourceInputAdapter> adapter = new MediaSourceInputAdapter(this);
mAdapters.AppendElement(adapter);
return adapter.forget();
}
/* static */ already_AddRefed<MediaSource>
MediaSource::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
{
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.Get());
if (!window) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
nsRefPtr<MediaSource> mediaSource = new MediaSource(window);
return mediaSource.forget();
}
SourceBufferList*
MediaSource::SourceBuffers()
{
MOZ_ASSERT_IF(mReadyState == MediaSourceReadyState::Closed, mSourceBuffers->IsEmpty());
return mSourceBuffers;
}
SourceBufferList*
MediaSource::ActiveSourceBuffers()
{
MOZ_ASSERT_IF(mReadyState == MediaSourceReadyState::Closed, mActiveSourceBuffers->IsEmpty());
return mActiveSourceBuffers;
}
MediaSourceReadyState
MediaSource::ReadyState()
{
return mReadyState;
}
double
MediaSource::Duration()
{
if (mReadyState == MediaSourceReadyState::Closed) {
return UnspecifiedNaN();
}
return mDuration;
}
void
MediaSource::SetDuration(double aDuration, ErrorResult& aRv)
{
if (aDuration < 0 || IsNaN(aDuration)) {
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return;
}
if (mReadyState != MediaSourceReadyState::Open ||
mSourceBuffers->AnyUpdating()) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
DurationChange(aDuration, aRv);
}
already_AddRefed<SourceBuffer>
MediaSource::AddSourceBuffer(const nsAString& aType, ErrorResult& aRv)
{
if (!IsTypeSupportedInternal(aType, aRv)) {
return nullptr;
}
// TODO: Temporary limit until multiple decoders are supported. Bug 881512.
if (mSourceBuffers->Length() >= 1) {
aRv.Throw(NS_ERROR_DOM_QUOTA_EXCEEDED_ERR);
return nullptr;
}
if (mReadyState != MediaSourceReadyState::Open) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return nullptr;
}
mContentType = aType;
nsRefPtr<SourceBuffer> sourceBuffer = new SourceBuffer(this);
mSourceBuffers->Append(sourceBuffer);
sourceBuffer->Attach();
return sourceBuffer.forget();
}
void
MediaSource::RemoveSourceBuffer(SourceBuffer& aSourceBuffer, ErrorResult& aRv)
{
SourceBuffer* sourceBuffer = &aSourceBuffer;
if (!mSourceBuffers->Contains(sourceBuffer)) {
aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
return;
}
if (sourceBuffer->Updating()) {
// TODO:
// abort stream append loop (if running)
// set updating to false
// fire "abort" at sourceBuffer
// fire "updateend" at sourceBuffer
}
// TODO:
// For all sourceBuffer audioTracks, videoTracks, textTracks:
// set sourceBuffer to null
// remove sourceBuffer video, audio, text Tracks from MediaElement tracks
// remove sourceBuffer video, audio, text Tracks and fire "removetrack" at affected lists
// fire "removetrack" at modified MediaElement track lists
// If removed enabled/selected, fire "change" at affected MediaElement list.
if (mActiveSourceBuffers->Contains(sourceBuffer)) {
mActiveSourceBuffers->Remove(sourceBuffer);
}
mSourceBuffers->Remove(sourceBuffer);
sourceBuffer->Detach();
// TODO: Free all resources associated with sourceBuffer
}
void
MediaSource::EndOfStream(const Optional<MediaSourceEndOfStreamError>& aError, ErrorResult& aRv)
{
if (mReadyState != MediaSourceReadyState::Open ||
mSourceBuffers->AnyUpdating()) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
EndOfStreamInternal(aError, aRv);
}
/* static */ bool
MediaSource::IsTypeSupported(const GlobalObject& aGlobal, const nsAString& aType)
{
ErrorResult unused;
return IsTypeSupportedInternal(aType, unused);
}
void
MediaSource::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
{
MonitorAutoLock mon(mMonitor);
LOG(PR_LOG_DEBUG, ("%p Append(ArrayBuffer=%u) mData=%u", this, aLength, mData.Length()));
mData.AppendElements(aData, aLength);
NotifyListeners();
}
bool
MediaSource::AttachElement(HTMLMediaElement* aElement)
{
LOG(PR_LOG_DEBUG, ("%p Attaching element %p", this, aElement));
MOZ_ASSERT(aElement);
mElement = aElement;
if (mReadyState != MediaSourceReadyState::Closed) {
return false;
}
SetReadyState(MediaSourceReadyState::Open);
return true;
}
void
MediaSource::DetachElement()
{
LOG(PR_LOG_DEBUG, ("%p Detaching element %p", this, mElement.get()));
MOZ_ASSERT(mElement);
mElement = nullptr;
mDuration = UnspecifiedNaN();
mActiveSourceBuffers->Clear();
mSourceBuffers->DetachAndClear();
SetReadyState(MediaSourceReadyState::Closed);
for (uint32_t i = 0; i < mAdapters.Length(); ++i) {
mAdapters[i]->Close();
}
mAdapters.Clear();
}
MediaSource::MediaSource(nsPIDOMWindow* aWindow)
: nsDOMEventTargetHelper(aWindow)
, mDuration(UnspecifiedNaN())
, mMonitor("mozilla::dom::MediaSource::mMonitor")
, mReadyState(MediaSourceReadyState::Closed)
{
mSourceBuffers = new SourceBufferList(this);
mActiveSourceBuffers = new SourceBufferList(this);
#ifdef PR_LOGGING
if (!gMediaSourceLog) {
gMediaSourceLog = PR_NewLogModule("MediaSource");
}
#endif
}
void
MediaSource::SetReadyState(MediaSourceReadyState aState)
{
MOZ_ASSERT(aState != mReadyState);
MonitorAutoLock mon(mMonitor);
NotifyListeners();
if ((mReadyState == MediaSourceReadyState::Closed ||
mReadyState == MediaSourceReadyState::Ended) &&
aState == MediaSourceReadyState::Open) {
mReadyState = aState;
QueueAsyncSimpleEvent("sourceopen");
return;
}
if (mReadyState == MediaSourceReadyState::Open &&
aState == MediaSourceReadyState::Ended) {
mReadyState = aState;
QueueAsyncSimpleEvent("sourceended");
return;
}
if ((mReadyState == MediaSourceReadyState::Open ||
mReadyState == MediaSourceReadyState::Ended) &&
aState == MediaSourceReadyState::Closed) {
mReadyState = aState;
QueueAsyncSimpleEvent("sourceclose");
return;
}
NS_WARNING("Invalid MediaSource readyState transition");
}
void
MediaSource::GetBuffered(TimeRanges* aRanges)
{
if (mActiveSourceBuffers->Length() == 0) {
return;
}
// TODO: Implement intersection computation.
}
void
MediaSource::DispatchSimpleEvent(const char* aName)
{
LOG(PR_LOG_DEBUG, ("%p Dispatching event %s to MediaSource", this, aName));
DispatchTrustedEvent(NS_ConvertUTF8toUTF16(aName));
}
void
MediaSource::QueueAsyncSimpleEvent(const char* aName)
{
LOG(PR_LOG_DEBUG, ("%p Queuing event %s to MediaSource", this, aName));
nsCOMPtr<nsIRunnable> event = new AsyncEventRunnner<MediaSource>(this, aName);
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
}
void
MediaSource::NotifyListeners()
{
for (uint32_t i = 0; i < mAdapters.Length(); ++i) {
mAdapters[i]->NotifyListener();
}
}
void
MediaSource::DurationChange(double aNewDuration, ErrorResult& aRv)
{
if (mDuration == aNewDuration) {
return;
}
double oldDuration = mDuration;
mDuration = aNewDuration;
if (aNewDuration < oldDuration) {
mSourceBuffers->Remove(aNewDuration, oldDuration, aRv);
if (aRv.Failed()) {
return;
}
}
// TODO: If partial audio frames/text cues exist, clamp duration based on mSourceBuffers.
// TODO: Update media element's duration and run element's duration change algorithm.
}
void
MediaSource::EndOfStreamInternal(const Optional<MediaSourceEndOfStreamError>& aError, ErrorResult& aRv)
{
SetReadyState(MediaSourceReadyState::Ended);
if (!aError.WasPassed()) {
// TODO:
// Run duration change algorithm.
// DurationChange(highestDurationOfSourceBuffers, aRv);
// if (aRv.Failed()) {
// return;
// }
// Notify media element that all data is now available.
return;
}
switch (aError.Value()) {
case MediaSourceEndOfStreamError::Network:
// TODO: If media element has a readyState of:
// HAVE_NOTHING -> run resource fetch algorithm
// > HAVE_NOTHING -> run "interrupted" steps of resource fetch
break;
case MediaSourceEndOfStreamError::Decode:
// TODO: If media element has a readyState of:
// HAVE_NOTHING -> run "unsupported" steps of resource fetch
// > HAVE_NOTHING -> run "corrupted" steps of resource fetch
break;
default:
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
}
}
static const char* const gMediaSourceTypes[5] = {
"video/webm",
"audio/webm",
"video/mp4",
"audio/mp4",
nullptr
};
/* static */ bool
MediaSource::IsTypeSupportedInternal(const nsAString& aType, ErrorResult& aRv)
{
if (aType.IsEmpty()) {
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return false;
}
// TODO: Further restrict this to formats in the spec.
nsContentTypeParser parser(aType);
nsAutoString mimeType;
nsresult rv = parser.GetType(mimeType);
if (NS_FAILED(rv)) {
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return false;
}
bool found = false;
for (uint32_t i = 0; gMediaSourceTypes[i]; ++i) {
if (mimeType.EqualsASCII(gMediaSourceTypes[i])) {
found = true;
break;
}
}
if (!found) {
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return false;
}
// Check aType against HTMLMediaElement list of MIME types. Since we've
// already restricted the container format, this acts as a specific check
// of any specified "codecs" parameter of aType.
if (HTMLMediaElement::GetCanPlay(aType) == CANPLAY_NO) {
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return false;
}
return true;
}
nsPIDOMWindow*
MediaSource::GetParentObject() const
{
return GetOwner();
}
JSObject*
MediaSource::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
{
return MediaSourceBinding::Wrap(aCx, aScope, this);
}
NS_IMPL_CYCLE_COLLECTION_INHERITED_4(MediaSource, nsDOMEventTargetHelper,
mSourceBuffers, mActiveSourceBuffers, mAdapters, mElement)
NS_IMPL_ADDREF_INHERITED(MediaSource, nsDOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(MediaSource, nsDOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaSource)
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
} // namespace dom
} // namespace mozilla

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

@ -0,0 +1,127 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef mozilla_dom_MediaSource_h_
#define mozilla_dom_MediaSource_h_
#include "AsyncEventRunner.h"
#include "mozilla/Attributes.h"
#include "mozilla/Monitor.h"
#include "mozilla/dom/MediaSourceBinding.h"
#include "mozilla/dom/TypedArray.h"
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsDOMEventTargetHelper.h"
#include "nsWrapperCache.h"
#include "nscore.h"
namespace mozilla {
namespace dom {
class HTMLMediaElement;
class MediaSourceInputAdapter;
class SourceBufferList;
class SourceBuffer;
class TimeRanges;
class MediaSource MOZ_FINAL : public nsDOMEventTargetHelper
{
public:
/** WebIDL Methods. */
static already_AddRefed<MediaSource> Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
SourceBufferList* SourceBuffers();
SourceBufferList* ActiveSourceBuffers();
MediaSourceReadyState ReadyState();
double Duration();
void SetDuration(double aDuration, ErrorResult& aRv);
already_AddRefed<SourceBuffer> AddSourceBuffer(const nsAString& aType, ErrorResult& aRv);
void RemoveSourceBuffer(SourceBuffer& aSourceBuffer, ErrorResult& aRv);
void EndOfStream(const Optional<MediaSourceEndOfStreamError>& aError, ErrorResult& aRv);
static bool IsTypeSupported(const GlobalObject& aGlobal, const nsAString& aType);
/** End WebIDL Methods. */
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MediaSource, nsDOMEventTargetHelper)
nsPIDOMWindow* GetParentObject() const;
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
const nsString& GetType()
{
return mContentType;
}
already_AddRefed<nsIInputStream> CreateInternalStream();
void AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv);
// Semi-private, for MediaSourceInputAdapter only.
nsTArray<uint8_t> const& GetData()
{
return mData;
}
Monitor& GetMonitor()
{
return mMonitor;
}
bool AppendDone() const
{
return mReadyState == MediaSourceReadyState::Closed;
}
// Attach this MediaSource to MediaElement aElement. Returns false if already attached.
bool AttachElement(HTMLMediaElement* aElement);
void DetachElement();
// Set mReadyState to aState and fire the required events at the MediaSource.
void SetReadyState(MediaSourceReadyState aState);
void GetBuffered(TimeRanges* aRanges);
private:
explicit MediaSource(nsPIDOMWindow* aWindow);
friend class AsyncEventRunnner<MediaSource>;
void DispatchSimpleEvent(const char* aName);
void QueueAsyncSimpleEvent(const char* aName);
void NotifyListeners();
void DurationChange(double aNewDuration, ErrorResult& aRv);
void EndOfStreamInternal(const Optional<MediaSourceEndOfStreamError>& aError, ErrorResult& aRv);
static bool IsTypeSupportedInternal(const nsAString& aType, ErrorResult& aRv);
double mDuration;
nsTArray<nsRefPtr<MediaSourceInputAdapter> > mAdapters;
// Protected by monitor.
nsTArray<uint8_t> mData;
// Protects access to mData.
Monitor mMonitor;
nsRefPtr<SourceBufferList> mSourceBuffers;
nsRefPtr<SourceBufferList> mActiveSourceBuffers;
nsRefPtr<HTMLMediaElement> mElement;
nsString mContentType;
MediaSourceReadyState mReadyState;
};
} // namespace dom
} // namespace mozilla
#endif /* mozilla_dom_MediaSource_h_ */

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

@ -0,0 +1,176 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 "MediaSourceInputAdapter.h"
#include "nsStreamUtils.h"
#include "nsCycleCollectionParticipant.h"
#ifdef PR_LOGGING
extern PRLogModuleInfo* gMediaSourceLog;
#define LOG(type, msg) PR_LOG(gMediaSourceLog, type, msg)
#else
#define LOG(type, msg)
#endif
namespace mozilla {
namespace dom {
NS_IMETHODIMP
MediaSourceInputAdapter::Close()
{
MonitorAutoLock mon(mMediaSource->GetMonitor());
LOG(PR_LOG_DEBUG, ("%p IA::Close", this));
//MOZ_ASSERT(!mClosed);
mClosed = true;
NotifyListener();
return NS_OK;
}
NS_IMETHODIMP
MediaSourceInputAdapter::Available(uint64_t* aAvailable)
{
MonitorAutoLock mon(mMediaSource->GetMonitor());
if (mClosed) {
LOG(PR_LOG_DEBUG, ("%p IA::Available (closed)", this));
return NS_BASE_STREAM_CLOSED;
}
*aAvailable = Available();
LOG(PR_LOG_DEBUG, ("%p IA::Available available=%llu", this, *aAvailable));
return NS_OK;
}
NS_IMETHODIMP
MediaSourceInputAdapter::Read(char* aBuf, uint32_t aCount, uint32_t* aWriteCount)
{
return ReadSegments(NS_CopySegmentToBuffer, aBuf, aCount, aWriteCount);
}
NS_IMETHODIMP
MediaSourceInputAdapter::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
uint32_t aCount, uint32_t* aWriteCount)
{
MonitorAutoLock mon(mMediaSource->GetMonitor());
uint32_t available = Available();
LOG(PR_LOG_DEBUG, ("%p IA::ReadSegments aCount=%u available=%u appendDone=%d rv=%x",
this, aCount, available, mMediaSource->AppendDone(),
mMediaSource->AppendDone() ? NS_OK : NS_BASE_STREAM_WOULD_BLOCK));
if (available == 0) {
*aWriteCount = 0;
return mMediaSource->AppendDone() ? NS_OK : NS_BASE_STREAM_WOULD_BLOCK;
}
uint32_t count = std::min(aCount, available);
nsresult rv = aWriter(this, aClosure,
reinterpret_cast<const char*>(&mMediaSource->GetData()[mOffset]),
0, count, aWriteCount);
if (NS_SUCCEEDED(rv)) {
MOZ_ASSERT(*aWriteCount <= count);
mOffset += *aWriteCount;
}
return NS_OK;
}
NS_IMETHODIMP
MediaSourceInputAdapter::IsNonBlocking(bool* aNonBlocking)
{
LOG(PR_LOG_DEBUG, ("%p IA::IsNonBlocking", this));
*aNonBlocking = true;
return NS_OK;
}
NS_IMETHODIMP
MediaSourceInputAdapter::CloseWithStatus(nsresult aStatus)
{
return Close();
}
NS_IMETHODIMP
MediaSourceInputAdapter::AsyncWait(nsIInputStreamCallback* aCallback, uint32_t aFlags,
uint32_t aRequestedCount, nsIEventTarget* aTarget)
{
LOG(PR_LOG_DEBUG, ("%p IA::AsyncWait aCallback=%p aFlags=%u aRequestedCount=%u aTarget=%p",
this, aCallback, aFlags, aRequestedCount, aTarget));
if (aFlags != 0) {
return NS_ERROR_NOT_IMPLEMENTED;
}
if (mCallback || mCallbackTarget) {
return NS_ERROR_UNEXPECTED;
}
mCallback = aCallback;
mCallbackTarget = aTarget;
mNotifyThreshold = aRequestedCount;
if (!aRequestedCount) {
mNotifyThreshold = 1024;
}
NotifyListener();
return NS_OK;
}
void
MediaSourceInputAdapter::NotifyListener()
{
if (!mCallback) {
return;
}
// Don't notify unless more data is available than the threshold, except
// in the case that there's no more data coming.
if (Available() < mNotifyThreshold && !mClosed && !mMediaSource->AppendDone()) {
return;
}
nsCOMPtr<nsIInputStreamCallback> callback;
if (mCallbackTarget) {
callback = NS_NewInputStreamReadyEvent(mCallback, mCallbackTarget);
} else {
callback = mCallback;
}
MOZ_ASSERT(callback);
mCallback = nullptr;
mCallbackTarget = nullptr;
mNotifyThreshold = 0;
LOG(PR_LOG_DEBUG, ("%p IA::NotifyListener", this));
callback->OnInputStreamReady(this);
}
uint64_t
MediaSourceInputAdapter::Available()
{
return mMediaSource->GetData().Length() - mOffset;
}
MediaSourceInputAdapter::~MediaSourceInputAdapter()
{
LOG(PR_LOG_DEBUG, ("%p Destroy input adapter", this));
}
MediaSourceInputAdapter::MediaSourceInputAdapter(MediaSource* aMediaSource)
: mMediaSource(aMediaSource)
, mOffset(0)
, mClosed(false)
{
LOG(PR_LOG_DEBUG, ("%p Create input adapter for %p", this, aMediaSource));
}
NS_IMPL_CYCLE_COLLECTION_1(MediaSourceInputAdapter, mMediaSource)
NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaSourceInputAdapter)
NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaSourceInputAdapter)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaSourceInputAdapter)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY(nsIInputStream)
NS_INTERFACE_MAP_ENTRY(nsIAsyncInputStream)
NS_INTERFACE_MAP_END
} // namespace dom
} // namespace mozilla

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

@ -0,0 +1,43 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef MOZILLA_MEDIASOURCEINPUTADAPTER_H_
#define MOZILLA_MEDIASOURCEINPUTADAPTER_H_
#include "nsIAsyncInputStream.h"
#include "nsCycleCollectionParticipant.h"
#include "MediaSource.h"
namespace mozilla {
namespace dom {
class MediaSourceInputAdapter MOZ_FINAL : public nsIAsyncInputStream
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(MediaSourceInputAdapter)
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSIASYNCINPUTSTREAM
MediaSourceInputAdapter(MediaSource* aMediaSource);
~MediaSourceInputAdapter();
void NotifyListener();
private:
uint64_t Available();
nsRefPtr<MediaSource> mMediaSource;
nsCOMPtr<nsIInputStreamCallback> mCallback;
nsCOMPtr<nsIEventTarget> mCallbackTarget;
int64_t mOffset;
uint32_t mNotifyThreshold;
bool mClosed;
};
} // namespace dom
} // namespace mozilla
#endif /* MOZILLA_MEDIASOURCEINPUTADAPTER_H_ */

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

@ -0,0 +1,249 @@
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 "SourceBuffer.h"
#include "nsContentUtils.h"
#ifdef PR_LOGGING
extern PRLogModuleInfo* gMediaSourceLog;
#define LOG(type, msg) PR_LOG(gMediaSourceLog, type, msg)
#else
#define LOG(type, msg)
#endif
namespace mozilla {
namespace dom {
void
SourceBuffer::SetMode(SourceBufferAppendMode aMode, ErrorResult& aRv)
{
if (!mAttached || mUpdating) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
mMediaSource->SetReadyState(MediaSourceReadyState::Open);
}
// TODO:: Test append state.
// TODO:: If aMode is "sequence", set sequence start time.
mAppendMode = aMode;
}
void
SourceBuffer::SetTimestampOffset(double aTimestampOffset, ErrorResult& aRv)
{
if (!mAttached || mUpdating) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
mMediaSource->SetReadyState(MediaSourceReadyState::Open);
}
// TODO: Test append state.
// TODO: If aMode is "sequence", set sequence start time.
mTimestampOffset = aTimestampOffset;
}
already_AddRefed<TimeRanges>
SourceBuffer::GetBuffered(ErrorResult& aRv)
{
if (!mAttached) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return nullptr;
}
nsRefPtr<TimeRanges> ranges = new TimeRanges();
// TODO: Populate ranges.
return ranges.forget();
}
void
SourceBuffer::SetAppendWindowStart(double aAppendWindowStart, ErrorResult& aRv)
{
if (!mAttached || mUpdating) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
if (aAppendWindowStart < 0 || aAppendWindowStart >= mAppendWindowEnd) {
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return;
}
mAppendWindowStart = aAppendWindowStart;
}
void
SourceBuffer::SetAppendWindowEnd(double aAppendWindowEnd, ErrorResult& aRv)
{
if (!mAttached || mUpdating) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
if (IsNaN(aAppendWindowEnd) ||
aAppendWindowEnd <= mAppendWindowStart) {
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return;
}
mAppendWindowEnd = aAppendWindowEnd;
}
void
SourceBuffer::AppendBuffer(ArrayBuffer& aData, ErrorResult& aRv)
{
AppendData(aData.Data(), aData.Length(), aRv);
}
void
SourceBuffer::AppendBuffer(ArrayBufferView& aData, ErrorResult& aRv)
{
AppendData(aData.Data(), aData.Length(), aRv);
}
void
SourceBuffer::Abort(ErrorResult& aRv)
{
if (!mAttached) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
if (mMediaSource->ReadyState() != MediaSourceReadyState::Open) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
if (mUpdating) {
// TODO: Abort segment parser loop, buffer append, and stream append loop algorithms.
AbortUpdating();
}
// TODO: Run reset parser algorithm.
// XXX: Need to run these two resets through setters?
mAppendWindowStart = 0;
mAppendWindowEnd = PositiveInfinity();
}
void
SourceBuffer::Remove(double aStart, double aEnd, ErrorResult& aRv)
{
if (aStart < 0 || aStart > mMediaSource->Duration() ||
aEnd <= aStart) {
aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return;
}
if (!mAttached || mUpdating ||
mMediaSource->ReadyState() != MediaSourceReadyState::Open) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
StartUpdating();
/// TODO: Run coded frame removal algorithm asynchronously (would call StopUpdating()).
StopUpdating();
}
void
SourceBuffer::Attach()
{
MOZ_ASSERT(!mAttached);
mAttached = true;
}
void
SourceBuffer::Detach()
{
MOZ_ASSERT(mAttached);
mAttached = false;
}
SourceBuffer::SourceBuffer(MediaSource* aMediaSource)
: nsDOMEventTargetHelper(aMediaSource->GetParentObject())
, mMediaSource(aMediaSource)
, mAppendWindowStart(0)
, mAppendWindowEnd(PositiveInfinity())
, mTimestampOffset(0)
, mAppendMode(SourceBufferAppendMode::Segments)
, mUpdating(false)
, mAttached(false)
{
MOZ_ASSERT(aMediaSource);
}
MediaSource*
SourceBuffer::GetParentObject() const
{
return mMediaSource;
}
JSObject*
SourceBuffer::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
{
return SourceBufferBinding::Wrap(aCx, aScope, this);
}
void
SourceBuffer::DispatchSimpleEvent(const char* aName)
{
LOG(PR_LOG_DEBUG, ("%p Dispatching event %s to SourceBuffer", this, aName));
DispatchTrustedEvent(NS_ConvertUTF8toUTF16(aName));
}
void
SourceBuffer::QueueAsyncSimpleEvent(const char* aName)
{
LOG(PR_LOG_DEBUG, ("%p Queuing event %s to SourceBuffer", this, aName));
nsCOMPtr<nsIRunnable> event = new AsyncEventRunnner<SourceBuffer>(this, aName);
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
}
void
SourceBuffer::StartUpdating()
{
MOZ_ASSERT(!mUpdating);
mUpdating = true;
QueueAsyncSimpleEvent("updatestart");
}
void
SourceBuffer::StopUpdating()
{
MOZ_ASSERT(mUpdating);
mUpdating = false;
QueueAsyncSimpleEvent("update");
QueueAsyncSimpleEvent("updateend");
}
void
SourceBuffer::AbortUpdating()
{
MOZ_ASSERT(mUpdating);
mUpdating = false;
QueueAsyncSimpleEvent("abort");
QueueAsyncSimpleEvent("updateend");
}
void
SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
{
if (!mAttached || mUpdating) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
mMediaSource->SetReadyState(MediaSourceReadyState::Open);
}
// TODO: Run coded frame eviction algorithm.
// TODO: Test buffer full flag.
mMediaSource->AppendData(aData, aLength, aRv); // XXX: Appending to input buffer.
StartUpdating();
// TODO: Run buffer append algorithm asynchronously (would call StopUpdating()).
StopUpdating();
}
NS_IMPL_CYCLE_COLLECTION_INHERITED_1(SourceBuffer, nsDOMEventTargetHelper, mMediaSource)
NS_IMPL_ADDREF_INHERITED(SourceBuffer, nsDOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(SourceBuffer, nsDOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(SourceBuffer)
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
} // namespace dom
} // namespace mozilla

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

@ -0,0 +1,115 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef mozilla_dom_SourceBuffer_h_
#define mozilla_dom_SourceBuffer_h_
#include "AsyncEventRunner.h"
#include "MediaSource.h"
#include "mozilla/Attributes.h"
#include "mozilla/dom/SourceBufferBinding.h"
#include "mozilla/dom/TimeRanges.h"
#include "mozilla/dom/TypedArray.h"
#include "mozilla/ErrorResult.h"
#include "nsCOMPtr.h"
#include "nscore.h"
#include "nsCycleCollectionParticipant.h"
#include "nsDOMEventTargetHelper.h"
#include "nsWrapperCache.h"
namespace mozilla {
namespace dom {
class SourceBuffer MOZ_FINAL : public nsDOMEventTargetHelper
{
public:
/** WebIDL Methods. */
SourceBufferAppendMode Mode() const
{
return mAppendMode;
}
void SetMode(SourceBufferAppendMode aMode, ErrorResult& aRv);
bool Updating() const
{
return mUpdating;
}
already_AddRefed<TimeRanges> GetBuffered(ErrorResult& aRv);
double TimestampOffset() const
{
return mTimestampOffset;
}
void SetTimestampOffset(double aTimestampOffset, ErrorResult& aRv);
double AppendWindowStart() const
{
return mAppendWindowStart;
}
void SetAppendWindowStart(double aAppendWindowStart, ErrorResult& aRv);
double AppendWindowEnd() const
{
return mAppendWindowEnd;
}
void SetAppendWindowEnd(double aAppendWindowEnd, ErrorResult& aRv);
void AppendBuffer(ArrayBuffer& aData, ErrorResult& aRv);
void AppendBuffer(ArrayBufferView& aData, ErrorResult& aRv);
void Abort(ErrorResult& aRv);
void Remove(double aStart, double aEnd, ErrorResult& aRv);
/** End WebIDL Methods. */
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SourceBuffer, nsDOMEventTargetHelper)
explicit SourceBuffer(MediaSource* aMediaSource);
MediaSource* GetParentObject() const;
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
// Notify the SourceBuffer that it has been attached to or detached from
// the MediaSource's sourceBuffer list.
void Attach();
void Detach();
private:
friend class AsyncEventRunnner<SourceBuffer>;
void DispatchSimpleEvent(const char* aName);
void QueueAsyncSimpleEvent(const char* aName);
// Update mUpdating and fire the appropriate events.
void StartUpdating();
void StopUpdating();
void AbortUpdating();
// Shared implementation of AppendBuffer overloads.
void AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv);
nsRefPtr<MediaSource> mMediaSource;
double mAppendWindowStart;
double mAppendWindowEnd;
double mTimestampOffset;
SourceBufferAppendMode mAppendMode;
bool mUpdating;
bool mAttached;
};
} // namespace dom
} // namespace mozilla
#endif /* mozilla_dom_SourceBuffer_h_ */

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

@ -0,0 +1,143 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 "SourceBufferList.h"
#include "mozilla/dom/SourceBufferListBinding.h"
#include "nsContentUtils.h"
#ifdef PR_LOGGING
extern PRLogModuleInfo* gMediaSourceLog;
#define LOG(type, msg) PR_LOG(gMediaSourceLog, type, msg)
#else
#define LOG(type, msg)
#endif
namespace mozilla {
namespace dom {
SourceBuffer*
SourceBufferList::IndexedGetter(uint32_t aIndex, bool& aFound)
{
aFound = aIndex < mSourceBuffers.Length();
return aFound ? mSourceBuffers[aIndex] : nullptr;
}
uint32_t
SourceBufferList::Length()
{
return mSourceBuffers.Length();
}
void
SourceBufferList::Append(SourceBuffer* aSourceBuffer)
{
mSourceBuffers.AppendElement(aSourceBuffer);
QueueAsyncSimpleEvent("addsourcebuffer");
}
void
SourceBufferList::Remove(SourceBuffer* aSourceBuffer)
{
MOZ_ALWAYS_TRUE(mSourceBuffers.RemoveElement(aSourceBuffer));
QueueAsyncSimpleEvent("removesourcebuffer");
}
bool
SourceBufferList::Contains(SourceBuffer* aSourceBuffer)
{
return mSourceBuffers.Contains(aSourceBuffer);
}
void
SourceBufferList::Clear()
{
mSourceBuffers.Clear();
QueueAsyncSimpleEvent("removesourcebuffer");
}
bool
SourceBufferList::IsEmpty()
{
return mSourceBuffers.IsEmpty();
}
void
SourceBufferList::DetachAndClear()
{
for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) {
mSourceBuffers[i]->Detach();
}
Clear();
}
bool
SourceBufferList::AnyUpdating()
{
for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) {
if (mSourceBuffers[i]->Updating()) {
return true;
}
}
return false;
}
void
SourceBufferList::Remove(double aStart, double aEnd, ErrorResult& aRv)
{
for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) {
mSourceBuffers[i]->Remove(aStart, aEnd, aRv);
if (aRv.Failed()) {
return;
}
}
}
void
SourceBufferList::DispatchSimpleEvent(const char* aName)
{
LOG(PR_LOG_DEBUG, ("%p Dispatching event %s to SourceBufferList", this, aName));
DispatchTrustedEvent(NS_ConvertUTF8toUTF16(aName));
}
void
SourceBufferList::QueueAsyncSimpleEvent(const char* aName)
{
LOG(PR_LOG_DEBUG, ("%p Queuing event %s to SourceBufferList", this, aName));
nsCOMPtr<nsIRunnable> event = new AsyncEventRunnner<SourceBufferList>(this, aName);
NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
}
SourceBufferList::SourceBufferList(MediaSource* aMediaSource)
: nsDOMEventTargetHelper(aMediaSource->GetParentObject())
, mMediaSource(aMediaSource)
{
MOZ_ASSERT(aMediaSource);
}
MediaSource*
SourceBufferList::GetParentObject() const
{
return mMediaSource;
}
JSObject*
SourceBufferList::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
{
return SourceBufferListBinding::Wrap(aCx, aScope, this);
}
NS_IMPL_CYCLE_COLLECTION_INHERITED_2(SourceBufferList, nsDOMEventTargetHelper,
mMediaSource, mSourceBuffers)
NS_IMPL_ADDREF_INHERITED(SourceBufferList, nsDOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(SourceBufferList, nsDOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(SourceBufferList)
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
} // namespace dom
} // namespace mozilla

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

@ -0,0 +1,79 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef mozilla_dom_SourceBufferList_h_
#define mozilla_dom_SourceBufferList_h_
#include "AsyncEventRunner.h"
#include "MediaSource.h"
#include "SourceBuffer.h"
#include "mozilla/Attributes.h"
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsDOMEventTargetHelper.h"
#include "nsWrapperCache.h"
#include "nscore.h"
namespace mozilla {
namespace dom {
class MediaSource;
class SourceBufferList MOZ_FINAL : public nsDOMEventTargetHelper
{
public:
/** WebIDL Methods. */
SourceBuffer* IndexedGetter(uint32_t aIndex, bool& aFound);
uint32_t Length();
/** End WebIDL methods. */
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SourceBufferList, nsDOMEventTargetHelper)
explicit SourceBufferList(MediaSource* aMediaSource);
MediaSource* GetParentObject() const;
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
// Append a SourceBuffer and fire "addsourcebuffer" at the list.
void Append(SourceBuffer* aSourceBuffer);
// Remove a SourceBuffer and fire "removesourcebuffer" at the list.
void Remove(SourceBuffer* aSourceBuffer);
// Returns true if aSourceBuffer is present in the list.
bool Contains(SourceBuffer* aSourceBuffer);
// Remove all SourceBuffers and fire a single "removesourcebuffer" at the list.
void Clear();
// True if list has zero entries.
bool IsEmpty();
// Detach and remove all SourceBuffers and fire a single "removesourcebuffer" at the list.
void DetachAndClear();
// Returns true if updating is true on any SourceBuffers in the list.
bool AnyUpdating();
// Calls Remove(aStart, aEnd) on each SourceBuffer in the list. Aborts on
// first error, with result returned in aRv.
void Remove(double aStart, double aEnd, ErrorResult& aRv);
private:
friend class AsyncEventRunnner<SourceBufferList>;
void DispatchSimpleEvent(const char* aName);
void QueueAsyncSimpleEvent(const char* aName);
nsRefPtr<MediaSource> mMediaSource;
nsTArray<nsRefPtr<SourceBuffer> > mSourceBuffers;
};
} // namespace dom
} // namespace mozilla
#endif /* mozilla_dom_SourceBufferList_h_ */

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

@ -0,0 +1,24 @@
# vim: set filetype=python:
# 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/.
MODULE = 'content'
EXPORTS += [
'AsyncEventRunner.h',
]
EXPORTS.mozilla.dom += [
'MediaSource.h',
'SourceBuffer.h',
'SourceBufferList.h',
]
CPP_SOURCES += [
'MediaSource.cpp',
'MediaSourceInputAdapter.cpp',
'SourceBuffer.cpp',
'SourceBufferList.cpp',
]

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

@ -6,6 +6,8 @@
PARALLEL_DIRS += ['encoder']
PARALLEL_DIRS += ['mediasource']
PARALLEL_DIRS += ['webaudio']
if CONFIG['MOZ_RAW']:

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

@ -609,6 +609,15 @@ DOMInterfaces = {
'register': False
},
'MediaSource': [{
'resultNotAddRefed': [ 'sourceBuffers', 'activeSourceBuffers' ],
},
{
'nativeType': 'JSObject',
'workers': True,
'skipGen': True
}],
'MediaStream': [{
'headerFile': 'DOMMediaStream.h',
'nativeType': 'mozilla::DOMMediaStream'
@ -807,6 +816,10 @@ DOMInterfaces = {
'nativeType': 'nsDOMSimpleGestureEvent',
},
'SourceBufferList': {
'resultNotAddRefed': [ '__indexedGetter' ],
},
'StyleSheet': {
'nativeType': 'nsCSSStyleSheet',
},

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

@ -27,6 +27,7 @@ DOM_SRCDIRS = \
content/base/src \
content/html/content/src \
content/html/document/src \
content/media/mediasource \
content/media/webaudio \
content/svg/content/src \
layout/generic \

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

@ -0,0 +1,38 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/.
*
* The origin of this IDL file is
* http://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html
*
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
*/
enum MediaSourceReadyState {
"closed",
"open",
"ended"
};
enum MediaSourceEndOfStreamError {
"network",
"decode"
};
[Constructor, Pref="media.mediasource.enabled"]
interface MediaSource : EventTarget {
readonly attribute SourceBufferList sourceBuffers;
readonly attribute SourceBufferList activeSourceBuffers;
readonly attribute MediaSourceReadyState readyState;
[SetterThrows]
attribute unrestricted double duration;
[Creator, Throws]
SourceBuffer addSourceBuffer(DOMString type);
[Throws]
void removeSourceBuffer(SourceBuffer sourceBuffer);
[Throws]
void endOfStream(optional MediaSourceEndOfStreamError error);
static boolean isTypeSupported(DOMString type);
};

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

@ -0,0 +1,44 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/.
*
* The origin of this IDL file is
* http://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html
*
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
*/
enum SourceBufferAppendMode {
"segments",
"sequence"
};
[Pref="media.mediasource.enabled"]
interface SourceBuffer : EventTarget {
[SetterThrows]
attribute SourceBufferAppendMode mode;
readonly attribute boolean updating;
[Creator, Throws]
readonly attribute TimeRanges buffered;
[SetterThrows]
attribute double timestampOffset;
//readonly attribute AudioTrackList audioTracks;
//readonly attribute VideoTrackList videoTracks;
//readonly attribute TextTrackList textTracks;
[SetterThrows]
attribute double appendWindowStart;
[SetterThrows]
attribute unrestricted double appendWindowEnd;
[Throws]
void appendBuffer(ArrayBuffer data);
[Throws]
void appendBuffer(ArrayBufferView data);
//[Throws]
//void appendStream(Stream stream, [EnforceRange] optional unsigned long long maxSize);
[Throws]
void abort();
[Throws]
void remove(double start, double end);
};

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

@ -0,0 +1,17 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/.
*
* The origin of this IDL file is
* http://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html
*
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
*/
[Pref="media.mediasource.enabled"]
interface SourceBufferList : EventTarget {
readonly attribute unsigned long length;
getter SourceBuffer (unsigned long index);
};

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

@ -174,6 +174,7 @@ webidl_files = \
LocalMediaStream.webidl \
Location.webidl \
MediaError.webidl \
MediaSource.webidl \
MediaStream.webidl \
MediaStreamAudioDestinationNode.webidl \
MediaStreamEvent.webidl \
@ -222,6 +223,8 @@ webidl_files = \
ScriptProcessorNode.webidl \
ScrollAreaEvent.webidl \
SimpleGestureEvent.webidl \
SourceBufferList.webidl \
SourceBuffer.webidl \
StyleSheet.webidl \
SVGAElement.webidl \
SVGAltGlyphElement.webidl \

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

@ -192,6 +192,10 @@ SHARED_LIBRARY_LIBS += \
$(NULL)
endif
SHARED_LIBRARY_LIBS += \
$(DEPTH)/content/media/mediasource/$(LIB_PREFIX)gkconmediasource_s.$(LIB_SUFFIX) \
$(NULL)
ifdef MOZ_DASH
SHARED_LIBRARY_LIBS += \
$(DEPTH)/content/media/dash/$(LIB_PREFIX)gkcondash_s.$(LIB_SUFFIX) \

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

@ -218,6 +218,9 @@ pref("media.navigator.enabled", true);
// TextTrack support
pref("media.webvtt.enabled", false);
// Whether to enable MediaSource support
pref("media.mediasource.enabled", false);
#ifdef MOZ_WEBSPEECH
pref("media.webspeech.recognition.enable", false);
#endif