2013-06-21 03:14:42 +00:00
|
|
|
/* -*- 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"
|
|
|
|
|
2013-09-27 05:22:37 +00:00
|
|
|
#include "AsyncEventRunner.h"
|
|
|
|
#include "DecoderTraits.h"
|
2016-03-03 02:57:11 +00:00
|
|
|
#include "Benchmark.h"
|
2016-04-19 07:36:19 +00:00
|
|
|
#include "DecoderDoctorDiagnostics.h"
|
2017-01-18 00:59:03 +00:00
|
|
|
#include "MediaContainerType.h"
|
2016-09-11 22:54:10 +00:00
|
|
|
#include "MediaResult.h"
|
2017-05-09 10:23:11 +00:00
|
|
|
#include "MediaSourceDemuxer.h"
|
2014-08-20 08:07:00 +00:00
|
|
|
#include "MediaSourceUtils.h"
|
2013-06-21 03:14:42 +00:00
|
|
|
#include "SourceBuffer.h"
|
|
|
|
#include "SourceBufferList.h"
|
2013-09-27 05:22:37 +00:00
|
|
|
#include "mozilla/ErrorResult.h"
|
|
|
|
#include "mozilla/FloatingPoint.h"
|
2018-06-24 18:40:40 +00:00
|
|
|
#include "mozilla/StaticPrefs.h"
|
2013-09-27 05:22:37 +00:00
|
|
|
#include "mozilla/dom/BindingDeclarations.h"
|
|
|
|
#include "mozilla/dom/HTMLMediaElement.h"
|
|
|
|
#include "mozilla/mozalloc.h"
|
|
|
|
#include "nsDebug.h"
|
|
|
|
#include "nsError.h"
|
|
|
|
#include "nsIRunnable.h"
|
2014-10-15 01:17:03 +00:00
|
|
|
#include "nsIScriptObjectPrincipal.h"
|
2013-09-27 05:22:37 +00:00
|
|
|
#include "nsPIDOMWindow.h"
|
2018-03-06 16:43:57 +00:00
|
|
|
#include "nsMimeTypes.h"
|
2014-08-20 08:14:00 +00:00
|
|
|
#include "nsString.h"
|
2013-09-27 05:22:37 +00:00
|
|
|
#include "nsThreadUtils.h"
|
2015-05-19 18:15:34 +00:00
|
|
|
#include "mozilla/Logging.h"
|
2015-01-09 07:37:00 +00:00
|
|
|
#include "nsServiceManagerUtils.h"
|
2016-08-25 03:48:35 +00:00
|
|
|
#include "mozilla/gfx/gfxVars.h"
|
2016-08-15 06:43:21 +00:00
|
|
|
#include "mozilla/Sprintf.h"
|
2013-09-27 05:22:37 +00:00
|
|
|
|
2016-10-26 09:08:21 +00:00
|
|
|
#ifdef MOZ_WIDGET_ANDROID
|
|
|
|
# include "AndroidBridge.h"
|
|
|
|
#endif
|
|
|
|
|
2013-09-27 05:22:37 +00:00
|
|
|
struct JSContext;
|
|
|
|
class JSObject;
|
2013-06-21 03:14:42 +00:00
|
|
|
|
2015-11-15 13:49:01 +00:00
|
|
|
mozilla::LogModule* GetMediaSourceLog() {
|
|
|
|
static mozilla::LazyLogModule sLogModule("MediaSource");
|
2014-08-11 01:21:17 +00:00
|
|
|
return sLogModule;
|
|
|
|
}
|
|
|
|
|
2015-11-15 13:49:01 +00:00
|
|
|
mozilla::LogModule* GetMediaSourceAPILog() {
|
|
|
|
static mozilla::LazyLogModule sLogModule("MediaSource");
|
2014-08-11 01:21:17 +00:00
|
|
|
return sLogModule;
|
|
|
|
}
|
|
|
|
|
2017-10-13 05:31:59 +00:00
|
|
|
#define MSE_DEBUG(arg, ...) \
|
|
|
|
DDMOZ_LOG(GetMediaSourceLog(), mozilla::LogLevel::Debug, "::%s: " arg, \
|
|
|
|
__func__, ##__VA_ARGS__)
|
|
|
|
#define MSE_API(arg, ...) \
|
|
|
|
DDMOZ_LOG(GetMediaSourceAPILog(), mozilla::LogLevel::Debug, "::%s: " arg, \
|
|
|
|
__func__, ##__VA_ARGS__)
|
2013-06-21 03:14:42 +00:00
|
|
|
|
2013-09-27 05:22:37 +00:00
|
|
|
// Arbitrary limit.
|
|
|
|
static const unsigned int MAX_SOURCE_BUFFERS = 16;
|
|
|
|
|
2013-06-21 03:14:42 +00:00
|
|
|
namespace mozilla {
|
|
|
|
|
2015-10-27 01:52:28 +00:00
|
|
|
// Returns true if we should enable MSE webm regardless of preferences.
|
|
|
|
// 1. If MP4/H264 isn't supported:
|
|
|
|
// * Windows XP
|
|
|
|
// * Windows Vista and Server 2008 without the optional "Platform Update
|
|
|
|
// Supplement"
|
|
|
|
// * N/KN editions (Europe and Korea) of Windows 7/8/8.1/10 without the
|
|
|
|
// optional "Windows Media Feature Pack"
|
2015-10-28 03:14:11 +00:00
|
|
|
// 2. If H264 hardware acceleration is not available.
|
2016-03-03 02:57:11 +00:00
|
|
|
// 3. The CPU is considered to be fast enough
|
2016-04-19 07:36:19 +00:00
|
|
|
static bool IsWebMForced(DecoderDoctorDiagnostics* aDiagnostics) {
|
2018-03-06 16:43:57 +00:00
|
|
|
bool mp4supported = DecoderTraits::IsMP4SupportedType(
|
|
|
|
MediaContainerType(MEDIAMIMETYPE(VIDEO_MP4)), aDiagnostics);
|
2016-08-25 03:48:35 +00:00
|
|
|
bool hwsupported = gfx::gfxVars::CanUseHardwareVideoDecoding();
|
2016-10-26 09:08:21 +00:00
|
|
|
#ifdef MOZ_WIDGET_ANDROID
|
|
|
|
return !mp4supported || !hwsupported || VP9Benchmark::IsVP9DecodeFast() ||
|
|
|
|
java::HardwareCodecCapabilityUtils::HasHWVP9();
|
|
|
|
#else
|
2016-03-09 04:34:50 +00:00
|
|
|
return !mp4supported || !hwsupported || VP9Benchmark::IsVP9DecodeFast();
|
2016-10-26 09:08:21 +00:00
|
|
|
#endif
|
2015-10-27 01:52:28 +00:00
|
|
|
}
|
|
|
|
|
2016-07-01 01:36:57 +00:00
|
|
|
namespace dom {
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
nsresult MediaSource::IsTypeSupported(const nsAString& aType,
|
|
|
|
DecoderDoctorDiagnostics* aDiagnostics) {
|
2014-03-05 03:35:47 +00:00
|
|
|
if (aType.IsEmpty()) {
|
2016-07-14 10:47:02 +00:00
|
|
|
return NS_ERROR_DOM_TYPE_ERR;
|
2014-03-05 03:35:47 +00:00
|
|
|
}
|
2016-09-29 13:10:15 +00:00
|
|
|
|
2017-01-18 00:59:03 +00:00
|
|
|
Maybe<MediaContainerType> containerType = MakeMediaContainerType(aType);
|
|
|
|
if (!containerType) {
|
2017-01-13 03:58:23 +00:00
|
|
|
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
2014-03-05 03:35:47 +00:00
|
|
|
}
|
2015-07-21 04:03:57 +00:00
|
|
|
|
2017-01-18 00:59:03 +00:00
|
|
|
if (DecoderTraits::CanHandleContainerType(*containerType, aDiagnostics) ==
|
2016-09-29 13:10:15 +00:00
|
|
|
CANPLAY_NO) {
|
|
|
|
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
|
|
|
}
|
2015-07-21 04:03:57 +00:00
|
|
|
|
2016-09-29 13:10:15 +00:00
|
|
|
// Now we know that this media type could be played.
|
|
|
|
// MediaSource imposes extra restrictions, and some prefs.
|
2017-01-18 00:59:03 +00:00
|
|
|
const MediaMIMEType& mimeType = containerType->Type();
|
2016-12-31 22:24:24 +00:00
|
|
|
if (mimeType == MEDIAMIMETYPE("video/mp4") ||
|
|
|
|
mimeType == MEDIAMIMETYPE("audio/mp4")) {
|
2019-07-18 13:06:17 +00:00
|
|
|
if (!StaticPrefs::media_mediasource_mp4_enabled()) {
|
2016-09-29 13:10:15 +00:00
|
|
|
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2016-12-31 22:24:24 +00:00
|
|
|
if (mimeType == MEDIAMIMETYPE("video/webm")) {
|
2019-07-18 13:06:17 +00:00
|
|
|
if (!(StaticPrefs::media_mediasource_webm_enabled() ||
|
2019-06-28 04:09:05 +00:00
|
|
|
StaticPrefs::media_media_capabilities_enabled() ||
|
2017-02-21 18:07:15 +00:00
|
|
|
containerType->ExtendedType().Codecs().Contains(
|
|
|
|
NS_LITERAL_STRING("vp8")) ||
|
2017-06-28 00:20:00 +00:00
|
|
|
#ifdef MOZ_AV1
|
2019-06-28 04:09:05 +00:00
|
|
|
(StaticPrefs::media_av1_enabled() &&
|
2018-07-20 08:24:56 +00:00
|
|
|
IsAV1CodecString(
|
|
|
|
containerType->ExtendedType().Codecs().AsString())) ||
|
2017-06-28 00:20:00 +00:00
|
|
|
#endif
|
2016-09-29 13:10:15 +00:00
|
|
|
IsWebMForced(aDiagnostics))) {
|
|
|
|
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
2014-03-05 03:35:47 +00:00
|
|
|
}
|
2016-09-29 13:10:15 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2016-12-31 22:24:24 +00:00
|
|
|
if (mimeType == MEDIAMIMETYPE("audio/webm")) {
|
2019-07-18 13:06:17 +00:00
|
|
|
if (!(StaticPrefs::media_mediasource_webm_enabled() ||
|
|
|
|
StaticPrefs::media_mediasource_webm_audio_enabled())) {
|
2016-09-29 13:10:15 +00:00
|
|
|
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
2014-03-05 03:35:47 +00:00
|
|
|
}
|
2015-06-28 02:17:35 +00:00
|
|
|
|
2015-07-21 04:03:57 +00:00
|
|
|
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
2014-03-05 03:35:47 +00:00
|
|
|
}
|
|
|
|
|
2019-02-25 22:05:29 +00:00
|
|
|
/* static */
|
|
|
|
already_AddRefed<MediaSource> MediaSource::Constructor(
|
2013-08-23 05:17:08 +00:00
|
|
|
const GlobalObject& aGlobal, ErrorResult& aRv) {
|
2016-01-30 17:05:36 +00:00
|
|
|
nsCOMPtr<nsPIDOMWindowInner> window =
|
|
|
|
do_QueryInterface(aGlobal.GetAsSupports());
|
2013-06-21 03:14:42 +00:00
|
|
|
if (!window) {
|
|
|
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2015-10-18 05:24:48 +00:00
|
|
|
RefPtr<MediaSource> mediaSource = new MediaSource(window);
|
2013-06-21 03:14:42 +00:00
|
|
|
return mediaSource.forget();
|
|
|
|
}
|
|
|
|
|
2014-06-14 14:04:01 +00:00
|
|
|
MediaSource::~MediaSource() {
|
2014-08-11 01:21:18 +00:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2015-02-12 07:52:13 +00:00
|
|
|
MSE_API("");
|
2014-08-28 03:44:58 +00:00
|
|
|
if (mDecoder) {
|
|
|
|
mDecoder->DetachMediaSource();
|
|
|
|
}
|
2014-06-14 14:04:01 +00:00
|
|
|
}
|
|
|
|
|
2013-06-21 03:14:42 +00:00
|
|
|
SourceBufferList* MediaSource::SourceBuffers() {
|
2014-08-11 01:21:18 +00:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2013-06-21 03:14:42 +00:00
|
|
|
MOZ_ASSERT_IF(mReadyState == MediaSourceReadyState::Closed,
|
|
|
|
mSourceBuffers->IsEmpty());
|
|
|
|
return mSourceBuffers;
|
|
|
|
}
|
|
|
|
|
|
|
|
SourceBufferList* MediaSource::ActiveSourceBuffers() {
|
2014-08-11 01:21:18 +00:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2013-06-21 03:14:42 +00:00
|
|
|
MOZ_ASSERT_IF(mReadyState == MediaSourceReadyState::Closed,
|
|
|
|
mActiveSourceBuffers->IsEmpty());
|
|
|
|
return mActiveSourceBuffers;
|
|
|
|
}
|
|
|
|
|
|
|
|
MediaSourceReadyState MediaSource::ReadyState() {
|
2014-08-11 01:21:18 +00:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2013-06-21 03:14:42 +00:00
|
|
|
return mReadyState;
|
|
|
|
}
|
|
|
|
|
|
|
|
double MediaSource::Duration() {
|
2014-08-11 01:21:18 +00:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2013-06-21 03:14:42 +00:00
|
|
|
if (mReadyState == MediaSourceReadyState::Closed) {
|
2014-02-27 15:23:16 +00:00
|
|
|
return UnspecifiedNaN<double>();
|
2013-06-21 03:14:42 +00:00
|
|
|
}
|
2014-11-12 04:11:33 +00:00
|
|
|
MOZ_ASSERT(mDecoder);
|
2016-07-15 13:38:33 +00:00
|
|
|
return mDecoder->GetDuration();
|
2013-06-21 03:14:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MediaSource::SetDuration(double aDuration, ErrorResult& aRv) {
|
2014-08-11 01:21:18 +00:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2015-02-12 07:52:13 +00:00
|
|
|
MSE_API("SetDuration(aDuration=%f, ErrorResult)", aDuration);
|
2013-06-21 03:14:42 +00:00
|
|
|
if (aDuration < 0 || IsNaN(aDuration)) {
|
2016-07-14 10:47:02 +00:00
|
|
|
aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
|
2013-06-21 03:14:42 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (mReadyState != MediaSourceReadyState::Open ||
|
|
|
|
mSourceBuffers->AnyUpdating()) {
|
|
|
|
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
|
|
|
return;
|
|
|
|
}
|
2016-07-15 13:38:33 +00:00
|
|
|
DurationChange(aDuration, aRv);
|
2015-01-09 01:34:41 +00:00
|
|
|
}
|
|
|
|
|
2016-07-15 13:38:33 +00:00
|
|
|
void MediaSource::SetDuration(double aDuration) {
|
2015-01-09 01:34:41 +00:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2015-02-12 07:52:13 +00:00
|
|
|
MSE_API("SetDuration(aDuration=%f)", aDuration);
|
2016-07-15 13:38:33 +00:00
|
|
|
mDecoder->SetMediaSourceDuration(aDuration);
|
2013-06-21 03:14:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<SourceBuffer> MediaSource::AddSourceBuffer(
|
|
|
|
const nsAString& aType, ErrorResult& aRv) {
|
2014-08-11 01:21:18 +00:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2016-04-19 07:36:19 +00:00
|
|
|
DecoderDoctorDiagnostics diagnostics;
|
2016-07-01 01:36:57 +00:00
|
|
|
nsresult rv = IsTypeSupported(aType, &diagnostics);
|
2016-04-22 03:42:11 +00:00
|
|
|
diagnostics.StoreFormatDiagnostics(
|
|
|
|
GetOwner() ? GetOwner()->GetExtantDoc() : nullptr, aType,
|
|
|
|
NS_SUCCEEDED(rv), __func__);
|
2015-02-12 07:52:13 +00:00
|
|
|
MSE_API("AddSourceBuffer(aType=%s)%s", NS_ConvertUTF16toUTF8(aType).get(),
|
2014-08-11 01:21:17 +00:00
|
|
|
rv == NS_OK ? "" : " [not supported]");
|
2014-03-05 03:35:47 +00:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
aRv.Throw(rv);
|
2013-06-21 03:14:42 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
2013-09-27 05:22:37 +00:00
|
|
|
if (mSourceBuffers->Length() >= MAX_SOURCE_BUFFERS) {
|
2013-06-21 03:14:42 +00:00
|
|
|
aRv.Throw(NS_ERROR_DOM_QUOTA_EXCEEDED_ERR);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
if (mReadyState != MediaSourceReadyState::Open) {
|
|
|
|
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
|
|
|
return nullptr;
|
|
|
|
}
|
2017-01-18 00:59:03 +00:00
|
|
|
Maybe<MediaContainerType> containerType = MakeMediaContainerType(aType);
|
|
|
|
if (!containerType) {
|
2013-09-27 05:22:37 +00:00
|
|
|
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
|
|
|
return nullptr;
|
|
|
|
}
|
Bug 1331289 - Use MediaContainerType in MediaResource, SourceBuffer, TrackBuffersManager, and dependencies - r=jya
Continuing the work of replacing MIME strings with MediaContainerType, starting
from MediaResource and following the dependencies.
Most changes are mechanical: Just change ns*String into MediaContainerType, and
MIME string literals into MEDIAMIMETYPE("a/b").
Some checks for empty/invalid strings and lowercase comparisons can go, thanks
to the always-valid always-lowercase-MIME invariants of MediaContainerType.
One special case in is MediaSourceResource, which used to have an empty string
as its type (because its own type is not relevant, but its SourceBuffers carry
types). Because the inherited GetContentType *must* be overridden, and must
return a MediaContainerType, we needed a valid type even though it should not
be seen in the real world. I've chosen "application/x.mediasource" for that.
MozReview-Commit-ID: 1aCH75Kh2e6
--HG--
extra : rebase_source : 0d9cd9b69c264e5dcfc3845f80ee107f4bcbcd9a
2016-12-28 07:59:02 +00:00
|
|
|
RefPtr<SourceBuffer> sourceBuffer = new SourceBuffer(this, *containerType);
|
2014-04-21 13:31:00 +00:00
|
|
|
if (!sourceBuffer) {
|
2014-04-14 11:24:00 +00:00
|
|
|
aRv.Throw(NS_ERROR_FAILURE); // XXX need a better error here
|
|
|
|
return nullptr;
|
|
|
|
}
|
2013-06-21 03:14:42 +00:00
|
|
|
mSourceBuffers->Append(sourceBuffer);
|
Bug 1407810 - Use DDLogger in media stack - r=jwwang
Mostly-mechanical additions:
- Log constructions&destructions, usually by just inheriting from
DecoderDoctorLifeLogger, otherwise with explicit log commands (for internal
classes for which DecoderDoctorTraits can't be specialized),
- Log links between most objects, e.g.: Media element -> decoder -> state
machine -> reader -> demuxer -> resource, etc.
And logging some important properties and events (JS events, duration change,
frames being decoded, etc.)
More will be added later on, from just converting MOZ_LOGs, and as needed.
MozReview-Commit-ID: KgNhHSz35t0
--HG--
extra : rebase_source : dd7206e350e32671adc6f3b9e54ebf777251de2c
2017-10-10 06:55:27 +00:00
|
|
|
DDLINKCHILD("sourcebuffer[]", sourceBuffer.get());
|
2015-02-12 07:52:13 +00:00
|
|
|
MSE_DEBUG("sourceBuffer=%p", sourceBuffer.get());
|
2013-06-21 03:14:42 +00:00
|
|
|
return sourceBuffer.forget();
|
|
|
|
}
|
|
|
|
|
2017-05-09 10:23:11 +00:00
|
|
|
RefPtr<MediaSource::ActiveCompletionPromise> MediaSource::SourceBufferIsActive(
|
2015-03-18 03:10:56 +00:00
|
|
|
SourceBuffer* aSourceBuffer) {
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
mActiveSourceBuffers->ClearSimple();
|
2017-05-09 10:23:11 +00:00
|
|
|
bool initMissing = false;
|
2015-03-18 03:10:56 +00:00
|
|
|
bool found = false;
|
|
|
|
for (uint32_t i = 0; i < mSourceBuffers->Length(); i++) {
|
|
|
|
SourceBuffer* sourceBuffer = mSourceBuffers->IndexedGetter(i, found);
|
|
|
|
MOZ_ALWAYS_TRUE(found);
|
|
|
|
if (sourceBuffer == aSourceBuffer) {
|
|
|
|
mActiveSourceBuffers->Append(aSourceBuffer);
|
|
|
|
} else if (sourceBuffer->IsActive()) {
|
|
|
|
mActiveSourceBuffers->AppendSimple(sourceBuffer);
|
2017-05-09 10:23:11 +00:00
|
|
|
} else {
|
|
|
|
// Some source buffers haven't yet received an init segment.
|
|
|
|
// There's nothing more we can do at this stage.
|
|
|
|
initMissing = true;
|
2015-03-18 03:10:56 +00:00
|
|
|
}
|
|
|
|
}
|
2017-05-09 10:23:11 +00:00
|
|
|
if (initMissing || !mDecoder) {
|
|
|
|
return ActiveCompletionPromise::CreateAndResolve(true, __func__);
|
|
|
|
}
|
|
|
|
|
|
|
|
mDecoder->NotifyInitDataArrived();
|
|
|
|
|
|
|
|
// Add our promise to the queue.
|
|
|
|
// It will be resolved once the HTMLMediaElement modifies its readyState.
|
|
|
|
MozPromiseHolder<ActiveCompletionPromise> holder;
|
|
|
|
RefPtr<ActiveCompletionPromise> promise = holder.Ensure(__func__);
|
2018-05-30 19:15:35 +00:00
|
|
|
mCompletionPromises.AppendElement(std::move(holder));
|
2017-05-09 10:23:11 +00:00
|
|
|
return promise;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MediaSource::CompletePendingTransactions() {
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
MSE_DEBUG("Resolving %u promises", unsigned(mCompletionPromises.Length()));
|
|
|
|
for (auto& promise : mCompletionPromises) {
|
|
|
|
promise.Resolve(true, __func__);
|
|
|
|
}
|
|
|
|
mCompletionPromises.Clear();
|
2015-03-18 03:10:56 +00:00
|
|
|
}
|
|
|
|
|
2013-06-21 03:14:42 +00:00
|
|
|
void MediaSource::RemoveSourceBuffer(SourceBuffer& aSourceBuffer,
|
|
|
|
ErrorResult& aRv) {
|
2014-08-11 01:21:18 +00:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2013-06-21 03:14:42 +00:00
|
|
|
SourceBuffer* sourceBuffer = &aSourceBuffer;
|
2015-02-12 07:52:13 +00:00
|
|
|
MSE_API("RemoveSourceBuffer(aSourceBuffer=%p)", sourceBuffer);
|
2013-06-21 03:14:42 +00:00
|
|
|
if (!mSourceBuffers->Contains(sourceBuffer)) {
|
|
|
|
aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
|
|
|
|
return;
|
|
|
|
}
|
2015-02-04 09:20:16 +00:00
|
|
|
|
|
|
|
sourceBuffer->AbortBufferAppend();
|
|
|
|
// TODO:
|
|
|
|
// abort stream append loop (if running)
|
|
|
|
|
2013-06-21 03:14:42 +00:00
|
|
|
// 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);
|
Bug 1407810 - Use DDLogger in media stack - r=jwwang
Mostly-mechanical additions:
- Log constructions&destructions, usually by just inheriting from
DecoderDoctorLifeLogger, otherwise with explicit log commands (for internal
classes for which DecoderDoctorTraits can't be specialized),
- Log links between most objects, e.g.: Media element -> decoder -> state
machine -> reader -> demuxer -> resource, etc.
And logging some important properties and events (JS events, duration change,
frames being decoded, etc.)
More will be added later on, from just converting MOZ_LOGs, and as needed.
MozReview-Commit-ID: KgNhHSz35t0
--HG--
extra : rebase_source : dd7206e350e32671adc6f3b9e54ebf777251de2c
2017-10-10 06:55:27 +00:00
|
|
|
DDUNLINKCHILD(sourceBuffer);
|
2013-06-21 03:14:42 +00:00
|
|
|
// TODO: Free all resources associated with sourceBuffer
|
|
|
|
}
|
|
|
|
|
|
|
|
void MediaSource::EndOfStream(
|
|
|
|
const Optional<MediaSourceEndOfStreamError>& aError, ErrorResult& aRv) {
|
2014-08-11 01:21:18 +00:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2015-02-12 07:52:13 +00:00
|
|
|
MSE_API("EndOfStream(aError=%d)",
|
|
|
|
aError.WasPassed() ? uint32_t(aError.Value()) : 0);
|
2013-06-21 03:14:42 +00:00
|
|
|
if (mReadyState != MediaSourceReadyState::Open ||
|
|
|
|
mSourceBuffers->AnyUpdating()) {
|
|
|
|
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
|
|
|
return;
|
|
|
|
}
|
2014-03-05 03:35:47 +00:00
|
|
|
|
|
|
|
SetReadyState(MediaSourceReadyState::Ended);
|
|
|
|
mSourceBuffers->Ended();
|
|
|
|
if (!aError.WasPassed()) {
|
2016-07-15 13:38:33 +00:00
|
|
|
DurationChange(mSourceBuffers->GetHighestBufferedEndTime(), aRv);
|
2015-03-23 10:08:05 +00:00
|
|
|
// Notify reader that all data is now available.
|
|
|
|
mDecoder->Ended(true);
|
2014-03-05 03:35:47 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
switch (aError.Value()) {
|
|
|
|
case MediaSourceEndOfStreamError::Network:
|
2017-11-17 03:07:30 +00:00
|
|
|
mDecoder->NetworkError(MediaResult(NS_ERROR_FAILURE, "MSE network"));
|
2014-03-05 03:35:47 +00:00
|
|
|
break;
|
|
|
|
case MediaSourceEndOfStreamError::Decode:
|
2016-09-10 14:56:09 +00:00
|
|
|
mDecoder->DecodeError(NS_ERROR_DOM_MEDIA_FATAL_ERR);
|
2014-03-05 03:35:47 +00:00
|
|
|
break;
|
|
|
|
default:
|
2016-07-14 10:47:02 +00:00
|
|
|
aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
|
2014-03-05 03:35:47 +00:00
|
|
|
}
|
2013-06-21 03:14:42 +00:00
|
|
|
}
|
|
|
|
|
2016-09-11 22:54:10 +00:00
|
|
|
void MediaSource::EndOfStream(const MediaResult& aError) {
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2017-09-28 16:37:45 +00:00
|
|
|
MSE_API("EndOfStream(aError=%s)", aError.ErrorName().get());
|
2016-09-11 22:54:10 +00:00
|
|
|
|
|
|
|
SetReadyState(MediaSourceReadyState::Ended);
|
|
|
|
mSourceBuffers->Ended();
|
|
|
|
mDecoder->DecodeError(aError);
|
|
|
|
}
|
|
|
|
|
2019-04-11 09:53:26 +00:00
|
|
|
static bool AreExtraParametersSane(const nsAString& aType) {
|
|
|
|
Maybe<MediaContainerType> containerType = MakeMediaContainerType(aType);
|
|
|
|
if (!containerType) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
auto extendedType = containerType->ExtendedType();
|
|
|
|
auto bitrate = extendedType.GetBitrate();
|
|
|
|
if (bitrate && *bitrate > 10000000) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (containerType->Type().HasVideoMajorType()) {
|
|
|
|
auto width = extendedType.GetWidth();
|
|
|
|
if (width && *width > MAX_VIDEO_WIDTH) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
auto height = extendedType.GetHeight();
|
|
|
|
if (height && *height > MAX_VIDEO_HEIGHT) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
auto framerate = extendedType.GetFramerate();
|
|
|
|
if (framerate && *framerate > 1000) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
auto eotf = extendedType.GetEOTF();
|
|
|
|
if (eotf && *eotf == EOTF::NOT_SUPPORTED) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else if (containerType->Type().HasAudioMajorType()) {
|
|
|
|
auto channels = extendedType.GetChannels();
|
|
|
|
if (channels && *channels > 6) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
auto samplerate = extendedType.GetSamplerate();
|
|
|
|
if (samplerate && *samplerate > 192000) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool IsYouTube(const GlobalObject& aOwner) {
|
|
|
|
nsCString domain;
|
|
|
|
return aOwner.GetSubjectPrincipal() &&
|
|
|
|
NS_SUCCEEDED(aOwner.GetSubjectPrincipal()->GetBaseDomain(domain)) &&
|
|
|
|
domain.EqualsLiteral("youtube.com");
|
|
|
|
}
|
|
|
|
|
2019-02-25 22:05:29 +00:00
|
|
|
/* static */
|
|
|
|
bool MediaSource::IsTypeSupported(const GlobalObject& aOwner,
|
|
|
|
const nsAString& aType) {
|
2014-08-11 01:21:18 +00:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2016-04-19 07:36:19 +00:00
|
|
|
DecoderDoctorDiagnostics diagnostics;
|
2016-07-01 01:36:57 +00:00
|
|
|
nsresult rv = IsTypeSupported(aType, &diagnostics);
|
2019-04-11 09:53:26 +00:00
|
|
|
if (NS_SUCCEEDED(rv) && IsYouTube(aOwner) && !AreExtraParametersSane(aType)) {
|
|
|
|
rv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
|
|
|
}
|
2016-04-19 07:36:19 +00:00
|
|
|
nsCOMPtr<nsPIDOMWindowInner> window =
|
|
|
|
do_QueryInterface(aOwner.GetAsSupports());
|
2016-04-22 03:42:11 +00:00
|
|
|
diagnostics.StoreFormatDiagnostics(window ? window->GetExtantDoc() : nullptr,
|
|
|
|
aType, NS_SUCCEEDED(rv), __func__);
|
2017-10-13 05:31:59 +00:00
|
|
|
MOZ_LOG(GetMediaSourceAPILog(), mozilla::LogLevel::Debug,
|
|
|
|
("MediaSource::%s: IsTypeSupported(aType=%s) %s", __func__,
|
|
|
|
NS_ConvertUTF16toUTF8(aType).get(),
|
|
|
|
rv == NS_OK ? "OK" : "[not supported]"));
|
2014-04-14 11:24:00 +00:00
|
|
|
return NS_SUCCEEDED(rv);
|
2013-06-21 03:14:42 +00:00
|
|
|
}
|
|
|
|
|
2016-07-14 04:34:45 +00:00
|
|
|
void MediaSource::SetLiveSeekableRange(double aStart, double aEnd,
|
|
|
|
ErrorResult& aRv) {
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
|
|
|
// 1. If the readyState attribute is not "open" then throw an
|
|
|
|
// InvalidStateError exception and abort these steps.
|
2016-07-16 04:35:02 +00:00
|
|
|
if (mReadyState != MediaSourceReadyState::Open) {
|
2016-07-14 04:34:45 +00:00
|
|
|
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-07-16 04:35:02 +00:00
|
|
|
// 2. If start is negative or greater than end, then throw a TypeError
|
2016-07-14 04:34:45 +00:00
|
|
|
// exception and abort these steps.
|
|
|
|
if (aStart < 0 || aStart > aEnd) {
|
|
|
|
aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-07-16 04:35:02 +00:00
|
|
|
// 3. Set live seekable range to be a new normalized TimeRanges object
|
2016-07-14 04:34:45 +00:00
|
|
|
// containing a single range whose start position is start and end position is
|
|
|
|
// end.
|
|
|
|
mLiveSeekableRange =
|
|
|
|
Some(media::TimeInterval(media::TimeUnit::FromSeconds(aStart),
|
|
|
|
media::TimeUnit::FromSeconds(aEnd)));
|
|
|
|
}
|
|
|
|
|
|
|
|
void MediaSource::ClearLiveSeekableRange(ErrorResult& aRv) {
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
|
|
|
// 1. If the readyState attribute is not "open" then throw an
|
|
|
|
// InvalidStateError exception and abort these steps.
|
2016-07-16 04:35:02 +00:00
|
|
|
if (mReadyState != MediaSourceReadyState::Open) {
|
2016-07-14 04:34:45 +00:00
|
|
|
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-07-16 04:35:02 +00:00
|
|
|
// 2. If live seekable range contains a range, then set live seekable range to
|
2016-07-14 04:34:45 +00:00
|
|
|
// be a new empty TimeRanges object.
|
|
|
|
mLiveSeekableRange.reset();
|
|
|
|
}
|
|
|
|
|
2013-09-27 05:22:37 +00:00
|
|
|
bool MediaSource::Attach(MediaSourceDecoder* aDecoder) {
|
2014-08-11 01:21:18 +00:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2015-02-12 07:52:13 +00:00
|
|
|
MSE_DEBUG("Attach(aDecoder=%p) owner=%p", aDecoder, aDecoder->GetOwner());
|
2013-09-27 05:22:37 +00:00
|
|
|
MOZ_ASSERT(aDecoder);
|
2014-12-29 03:18:41 +00:00
|
|
|
MOZ_ASSERT(aDecoder->GetOwner());
|
2013-06-21 03:14:42 +00:00
|
|
|
if (mReadyState != MediaSourceReadyState::Closed) {
|
|
|
|
return false;
|
|
|
|
}
|
2014-12-29 03:18:41 +00:00
|
|
|
MOZ_ASSERT(!mMediaElement);
|
|
|
|
mMediaElement = aDecoder->GetOwner()->GetMediaElement();
|
2014-08-28 03:44:58 +00:00
|
|
|
MOZ_ASSERT(!mDecoder);
|
2013-09-27 05:22:37 +00:00
|
|
|
mDecoder = aDecoder;
|
|
|
|
mDecoder->AttachMediaSource(this);
|
2013-06-21 03:14:42 +00:00
|
|
|
SetReadyState(MediaSourceReadyState::Open);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-09-27 05:22:37 +00:00
|
|
|
void MediaSource::Detach() {
|
2014-08-11 01:21:18 +00:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2017-05-09 10:23:11 +00:00
|
|
|
MOZ_RELEASE_ASSERT(mCompletionPromises.IsEmpty());
|
2015-02-12 07:52:13 +00:00
|
|
|
MSE_DEBUG("mDecoder=%p owner=%p", mDecoder.get(),
|
|
|
|
mDecoder ? mDecoder->GetOwner() : nullptr);
|
2014-08-28 03:44:58 +00:00
|
|
|
if (!mDecoder) {
|
|
|
|
MOZ_ASSERT(mReadyState == MediaSourceReadyState::Closed);
|
|
|
|
MOZ_ASSERT(mActiveSourceBuffers->IsEmpty() && mSourceBuffers->IsEmpty());
|
|
|
|
return;
|
|
|
|
}
|
2014-12-29 03:18:41 +00:00
|
|
|
mMediaElement = nullptr;
|
2014-08-28 03:44:58 +00:00
|
|
|
SetReadyState(MediaSourceReadyState::Closed);
|
2014-08-29 00:47:14 +00:00
|
|
|
if (mActiveSourceBuffers) {
|
|
|
|
mActiveSourceBuffers->Clear();
|
|
|
|
}
|
|
|
|
if (mSourceBuffers) {
|
|
|
|
mSourceBuffers->Clear();
|
|
|
|
}
|
2015-06-11 23:26:57 +00:00
|
|
|
mDecoder->DetachMediaSource();
|
|
|
|
mDecoder = nullptr;
|
2013-06-21 03:14:42 +00:00
|
|
|
}
|
|
|
|
|
2016-01-30 17:05:36 +00:00
|
|
|
MediaSource::MediaSource(nsPIDOMWindowInner* aWindow)
|
2014-04-01 06:13:50 +00:00
|
|
|
: DOMEventTargetHelper(aWindow),
|
2013-09-27 05:22:37 +00:00
|
|
|
mDecoder(nullptr),
|
2014-10-15 01:17:03 +00:00
|
|
|
mPrincipal(nullptr),
|
2016-11-29 05:03:36 +00:00
|
|
|
mAbstractMainThread(
|
|
|
|
GetOwnerGlobal()->AbstractMainThreadFor(TaskCategory::Other)),
|
2013-06-21 03:14:42 +00:00
|
|
|
mReadyState(MediaSourceReadyState::Closed) {
|
2014-08-11 01:21:18 +00:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2013-06-21 03:14:42 +00:00
|
|
|
mSourceBuffers = new SourceBufferList(this);
|
|
|
|
mActiveSourceBuffers = new SourceBufferList(this);
|
2014-10-15 01:17:03 +00:00
|
|
|
|
|
|
|
nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(aWindow);
|
|
|
|
if (sop) {
|
|
|
|
mPrincipal = sop->GetPrincipal();
|
|
|
|
}
|
|
|
|
|
2015-02-12 07:52:13 +00:00
|
|
|
MSE_API("MediaSource(aWindow=%p) mSourceBuffers=%p mActiveSourceBuffers=%p",
|
|
|
|
aWindow, mSourceBuffers.get(), mActiveSourceBuffers.get());
|
2013-06-21 03:14:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MediaSource::SetReadyState(MediaSourceReadyState aState) {
|
2014-08-11 01:21:18 +00:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2013-06-21 03:14:42 +00:00
|
|
|
MOZ_ASSERT(aState != mReadyState);
|
2016-12-16 03:16:31 +00:00
|
|
|
MSE_DEBUG("SetReadyState(aState=%" PRIu32 ") mReadyState=%" PRIu32,
|
|
|
|
static_cast<uint32_t>(aState), static_cast<uint32_t>(mReadyState));
|
2013-06-21 03:14:42 +00:00
|
|
|
|
2013-10-05 08:03:50 +00:00
|
|
|
MediaSourceReadyState oldState = mReadyState;
|
|
|
|
mReadyState = aState;
|
|
|
|
|
|
|
|
if (mReadyState == MediaSourceReadyState::Open &&
|
|
|
|
(oldState == MediaSourceReadyState::Closed ||
|
|
|
|
oldState == MediaSourceReadyState::Ended)) {
|
2013-06-21 03:14:42 +00:00
|
|
|
QueueAsyncSimpleEvent("sourceopen");
|
2015-03-23 10:08:05 +00:00
|
|
|
if (oldState == MediaSourceReadyState::Ended) {
|
|
|
|
// Notify reader that more data may come.
|
|
|
|
mDecoder->Ended(false);
|
|
|
|
}
|
2013-06-21 03:14:42 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-10-05 08:03:50 +00:00
|
|
|
if (mReadyState == MediaSourceReadyState::Ended &&
|
|
|
|
oldState == MediaSourceReadyState::Open) {
|
2013-06-21 03:14:42 +00:00
|
|
|
QueueAsyncSimpleEvent("sourceended");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-10-05 08:03:50 +00:00
|
|
|
if (mReadyState == MediaSourceReadyState::Closed &&
|
|
|
|
(oldState == MediaSourceReadyState::Open ||
|
|
|
|
oldState == MediaSourceReadyState::Ended)) {
|
2013-06-21 03:14:42 +00:00
|
|
|
QueueAsyncSimpleEvent("sourceclose");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_WARNING("Invalid MediaSource readyState transition");
|
|
|
|
}
|
|
|
|
|
|
|
|
void MediaSource::DispatchSimpleEvent(const char* aName) {
|
2014-08-11 01:21:18 +00:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2015-02-12 07:52:13 +00:00
|
|
|
MSE_API("Dispatch event '%s'", aName);
|
2013-06-21 03:14:42 +00:00
|
|
|
DispatchTrustedEvent(NS_ConvertUTF8toUTF16(aName));
|
|
|
|
}
|
|
|
|
|
|
|
|
void MediaSource::QueueAsyncSimpleEvent(const char* aName) {
|
2015-02-12 07:52:13 +00:00
|
|
|
MSE_DEBUG("Queuing event '%s'", aName);
|
2013-09-27 05:22:37 +00:00
|
|
|
nsCOMPtr<nsIRunnable> event = new AsyncEventRunner<MediaSource>(this, aName);
|
2017-03-01 07:08:50 +00:00
|
|
|
mAbstractMainThread->Dispatch(event.forget());
|
2013-06-21 03:14:42 +00:00
|
|
|
}
|
|
|
|
|
2016-07-15 13:38:33 +00:00
|
|
|
void MediaSource::DurationChange(double aNewDuration, ErrorResult& aRv) {
|
2014-08-11 01:21:18 +00:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2016-07-15 13:38:33 +00:00
|
|
|
MSE_DEBUG("DurationChange(aNewDuration=%f)", aNewDuration);
|
2014-11-12 04:11:33 +00:00
|
|
|
|
2016-07-15 13:38:33 +00:00
|
|
|
// 1. If the current value of duration is equal to new duration, then return.
|
|
|
|
if (mDecoder->GetDuration() == aNewDuration) {
|
|
|
|
return;
|
2013-06-21 03:14:42 +00:00
|
|
|
}
|
2016-07-15 13:38:33 +00:00
|
|
|
|
|
|
|
// 2. If new duration is less than the highest starting presentation timestamp
|
|
|
|
// of any buffered coded frames for all SourceBuffer objects in sourceBuffers,
|
|
|
|
// then throw an InvalidStateError exception and abort these steps.
|
|
|
|
if (aNewDuration < mSourceBuffers->HighestStartTime()) {
|
|
|
|
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-08-26 04:39:36 +00:00
|
|
|
// 3. Let highest end time be the largest track buffer ranges end time across
|
|
|
|
// all the track buffers across all SourceBuffer objects in sourceBuffers.
|
|
|
|
double highestEndTime = mSourceBuffers->HighestEndTime();
|
|
|
|
// 4. If new duration is less than highest end time, then
|
|
|
|
// 4.1 Update new duration to equal highest end time.
|
|
|
|
aNewDuration = std::max(aNewDuration, highestEndTime);
|
2016-07-15 13:38:33 +00:00
|
|
|
|
|
|
|
// 5. Update the media duration to new duration and run the HTMLMediaElement
|
|
|
|
// duration change algorithm.
|
|
|
|
mDecoder->SetMediaSourceDuration(aNewDuration);
|
2013-06-21 03:14:42 +00:00
|
|
|
}
|
|
|
|
|
2019-05-27 16:15:33 +00:00
|
|
|
already_AddRefed<Promise> MediaSource::MozDebugReaderData(ErrorResult& aRv) {
|
|
|
|
// Creating a JS promise
|
|
|
|
nsPIDOMWindowInner* win = GetOwner();
|
|
|
|
if (!win) {
|
|
|
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
RefPtr<Promise> domPromise = Promise::Create(win->AsGlobal(), aRv);
|
|
|
|
if (NS_WARN_IF(aRv.Failed())) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
MOZ_ASSERT(domPromise);
|
|
|
|
MediaSourceDecoderDebugInfo info;
|
|
|
|
mDecoder->GetDebugInfo(info);
|
|
|
|
domPromise->MaybeResolve(info);
|
|
|
|
return domPromise.forget();
|
2015-01-29 02:35:55 +00:00
|
|
|
}
|
|
|
|
|
2014-08-11 01:21:17 +00:00
|
|
|
nsPIDOMWindowInner* MediaSource::GetParentObject() const { return GetOwner(); }
|
|
|
|
|
Bug 1117172 part 3. Change the wrappercached WrapObject methods to allow passing in aGivenProto. r=peterv
The only manual changes here are to BindingUtils.h, BindingUtils.cpp,
Codegen.py, Element.cpp, IDBFileRequest.cpp, IDBObjectStore.cpp,
dom/workers/Navigator.cpp, WorkerPrivate.cpp, DeviceStorageRequestChild.cpp,
Notification.cpp, nsGlobalWindow.cpp, MessagePort.cpp, nsJSEnvironment.cpp,
Sandbox.cpp, XPCConvert.cpp, ExportHelpers.cpp, and DataStoreService.cpp. The
rest of this diff was generated by running the following commands:
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObject\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(Binding(?:_workers)?::Wrap\((?:aCx|cx|aContext|aCtx|js), [^,)]+)\)/\1, aGivenProto)/g'
2015-03-19 14:13:33 +00:00
|
|
|
JSObject* MediaSource::WrapObject(JSContext* aCx,
|
|
|
|
JS::Handle<JSObject*> aGivenProto) {
|
2018-06-25 21:20:54 +00:00
|
|
|
return MediaSource_Binding::Wrap(aCx, this, aGivenProto);
|
2014-06-02 22:25:42 +00:00
|
|
|
}
|
|
|
|
|
2014-04-25 16:49:00 +00:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_INHERITED(MediaSource, DOMEventTargetHelper,
|
|
|
|
mMediaElement, mSourceBuffers,
|
|
|
|
mActiveSourceBuffers)
|
2013-06-21 03:14:42 +00:00
|
|
|
|
2014-04-01 06:13:50 +00:00
|
|
|
NS_IMPL_ADDREF_INHERITED(MediaSource, DOMEventTargetHelper)
|
|
|
|
NS_IMPL_RELEASE_INHERITED(MediaSource, DOMEventTargetHelper)
|
2013-06-21 03:14:42 +00:00
|
|
|
|
2017-08-29 23:02:48 +00:00
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaSource)
|
2013-06-21 03:15:15 +00:00
|
|
|
NS_INTERFACE_MAP_ENTRY(mozilla::dom::MediaSource)
|
2014-04-01 06:13:50 +00:00
|
|
|
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
2013-06-21 03:14:42 +00:00
|
|
|
|
2015-02-12 07:52:13 +00:00
|
|
|
#undef MSE_DEBUG
|
|
|
|
#undef MSE_API
|
|
|
|
|
2013-06-21 03:14:42 +00:00
|
|
|
} // namespace dom
|
2013-09-27 05:22:37 +00:00
|
|
|
|
2013-06-21 03:14:42 +00:00
|
|
|
} // namespace mozilla
|