2012-05-11 21:35:36 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
|
2012-04-30 07:11:34 +04: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/. */
|
|
|
|
|
2013-02-15 12:01:58 +04:00
|
|
|
#include "DOMMediaStream.h"
|
2017-06-20 18:56:55 +03:00
|
|
|
|
2019-10-02 13:23:02 +03:00
|
|
|
#include "AudioCaptureTrack.h"
|
2015-08-25 11:29:51 +03:00
|
|
|
#include "AudioChannelAgent.h"
|
2017-06-20 18:56:55 +03:00
|
|
|
#include "AudioStreamTrack.h"
|
|
|
|
#include "Layers.h"
|
2019-10-02 13:23:02 +03:00
|
|
|
#include "MediaTrackGraph.h"
|
|
|
|
#include "MediaTrackGraphImpl.h"
|
|
|
|
#include "MediaTrackListener.h"
|
2017-06-20 18:56:55 +03:00
|
|
|
#include "VideoStreamTrack.h"
|
2014-05-23 13:34:14 +04:00
|
|
|
#include "mozilla/dom/AudioTrack.h"
|
|
|
|
#include "mozilla/dom/AudioTrackList.h"
|
2017-06-20 18:56:55 +03:00
|
|
|
#include "mozilla/dom/DocGroup.h"
|
|
|
|
#include "mozilla/dom/HTMLCanvasElement.h"
|
|
|
|
#include "mozilla/dom/MediaStreamBinding.h"
|
|
|
|
#include "mozilla/dom/MediaStreamTrackEvent.h"
|
2017-10-23 20:09:47 +03:00
|
|
|
#include "mozilla/dom/Promise.h"
|
2014-05-23 13:34:14 +04:00
|
|
|
#include "mozilla/dom/VideoTrack.h"
|
|
|
|
#include "mozilla/dom/VideoTrackList.h"
|
2016-03-16 18:00:34 +03:00
|
|
|
#include "mozilla/media/MediaUtils.h"
|
2017-06-20 18:56:55 +03:00
|
|
|
#include "nsContentUtils.h"
|
2019-07-31 10:58:17 +03:00
|
|
|
#include "nsGlobalWindowInner.h"
|
2017-06-20 18:56:55 +03:00
|
|
|
#include "nsIUUIDGenerator.h"
|
|
|
|
#include "nsPIDOMWindow.h"
|
2017-10-23 20:09:47 +03:00
|
|
|
#include "nsProxyRelease.h"
|
2017-06-20 18:56:55 +03:00
|
|
|
#include "nsRFPService.h"
|
|
|
|
#include "nsServiceManagerUtils.h"
|
2012-04-30 07:11:34 +04:00
|
|
|
|
2015-09-30 04:31:54 +03:00
|
|
|
#ifdef LOG
|
|
|
|
# undef LOG
|
|
|
|
#endif
|
|
|
|
|
2012-04-30 07:11:34 +04:00
|
|
|
using namespace mozilla;
|
2013-04-17 09:18:24 +04:00
|
|
|
using namespace mozilla::dom;
|
2015-06-18 01:21:00 +03:00
|
|
|
using namespace mozilla::layers;
|
2016-03-16 18:00:34 +03:00
|
|
|
using namespace mozilla::media;
|
2015-06-18 01:21:00 +03:00
|
|
|
|
2015-11-15 16:49:01 +03:00
|
|
|
static LazyLogModule gMediaStreamLog("MediaStream");
|
|
|
|
#define LOG(type, msg) MOZ_LOG(gMediaStreamLog, type, msg)
|
|
|
|
|
2016-09-15 15:18:22 +03:00
|
|
|
static bool ContainsLiveTracks(
|
2019-07-31 10:58:17 +03:00
|
|
|
const nsTArray<RefPtr<MediaStreamTrack>>& aTracks) {
|
|
|
|
for (const auto& track : aTracks) {
|
|
|
|
if (track->ReadyState() == MediaStreamTrackState::Live) {
|
2016-09-15 15:18:22 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2015-10-22 07:36:22 +03:00
|
|
|
|
2019-09-02 16:53:50 +03:00
|
|
|
static bool ContainsLiveAudioTracks(
|
|
|
|
const nsTArray<RefPtr<MediaStreamTrack>>& aTracks) {
|
|
|
|
for (const auto& track : aTracks) {
|
|
|
|
if (track->AsAudioStreamTrack() &&
|
|
|
|
track->ReadyState() == MediaStreamTrackState::Live) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-09-23 18:03:13 +03:00
|
|
|
class DOMMediaStream::PlaybackTrackListener : public MediaStreamTrackConsumer {
|
|
|
|
public:
|
|
|
|
explicit PlaybackTrackListener(DOMMediaStream* aStream) : mStream(aStream) {}
|
|
|
|
|
2017-10-10 21:48:58 +03:00
|
|
|
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(PlaybackTrackListener)
|
|
|
|
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(PlaybackTrackListener)
|
2016-09-23 18:03:13 +03:00
|
|
|
|
|
|
|
void NotifyEnded(MediaStreamTrack* aTrack) override {
|
|
|
|
if (!mStream) {
|
|
|
|
MOZ_ASSERT(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!aTrack) {
|
|
|
|
MOZ_ASSERT(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(mStream->HasTrack(*aTrack));
|
|
|
|
mStream->NotifyTrackRemoved(aTrack);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
2020-03-04 18:39:20 +03:00
|
|
|
virtual ~PlaybackTrackListener() = default;
|
2016-09-23 18:03:13 +03:00
|
|
|
|
|
|
|
RefPtr<DOMMediaStream> mStream;
|
|
|
|
};
|
|
|
|
|
2017-10-10 21:48:58 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(DOMMediaStream::PlaybackTrackListener,
|
|
|
|
AddRef)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(DOMMediaStream::PlaybackTrackListener,
|
|
|
|
Release)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION(DOMMediaStream::PlaybackTrackListener, mStream)
|
2016-09-23 18:03:13 +03:00
|
|
|
|
2014-11-02 02:56:10 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(DOMMediaStream)
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DOMMediaStream,
|
|
|
|
DOMEventTargetHelper)
|
2014-11-10 18:26:00 +03:00
|
|
|
tmp->Destroy();
|
2014-11-02 02:56:10 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTracks)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsumersToKeepAlive)
|
2016-09-23 18:03:13 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPlaybackTrackListener)
|
2020-02-25 22:44:39 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_PTR
|
2014-11-02 02:56:10 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DOMMediaStream,
|
|
|
|
DOMEventTargetHelper)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTracks)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsumersToKeepAlive)
|
2016-09-23 18:03:13 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlaybackTrackListener)
|
2014-11-02 02:56:10 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
|
|
|
|
NS_IMPL_ADDREF_INHERITED(DOMMediaStream, DOMEventTargetHelper)
|
|
|
|
NS_IMPL_RELEASE_INHERITED(DOMMediaStream, DOMEventTargetHelper)
|
|
|
|
|
2017-08-30 02:02:48 +03:00
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMMediaStream)
|
2014-11-02 02:56:10 +03:00
|
|
|
NS_INTERFACE_MAP_ENTRY(DOMMediaStream)
|
|
|
|
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
|
|
|
|
2018-11-23 18:02:03 +03:00
|
|
|
DOMMediaStream::DOMMediaStream(nsPIDOMWindowInner* aWindow)
|
2018-10-29 19:38:19 +03:00
|
|
|
: mWindow(aWindow),
|
2019-09-02 16:53:50 +03:00
|
|
|
mPlaybackTrackListener(MakeAndAddRef<PlaybackTrackListener>(this)) {
|
2015-02-19 20:59:00 +03:00
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIUUIDGenerator> uuidgen =
|
|
|
|
do_GetService("@mozilla.org/uuid-generator;1", &rv);
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(rv) && uuidgen) {
|
|
|
|
nsID uuid;
|
|
|
|
memset(&uuid, 0, sizeof(uuid));
|
|
|
|
rv = uuidgen->GenerateUUIDInPlace(&uuid);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
char buffer[NSID_LENGTH];
|
|
|
|
uuid.ToProvidedString(buffer);
|
|
|
|
mID = NS_ConvertASCIItoUTF16(buffer);
|
|
|
|
}
|
|
|
|
}
|
2013-04-17 09:18:24 +04:00
|
|
|
}
|
|
|
|
|
2013-02-15 12:01:58 +04:00
|
|
|
DOMMediaStream::~DOMMediaStream() { Destroy(); }
|
2013-05-01 15:24:16 +04:00
|
|
|
|
|
|
|
void DOMMediaStream::Destroy() {
|
2015-09-30 04:31:54 +03:00
|
|
|
LOG(LogLevel::Debug, ("DOMMediaStream %p Being destroyed.", this));
|
2019-07-31 10:58:17 +03:00
|
|
|
for (const auto& track : mTracks) {
|
2016-03-16 18:08:43 +03:00
|
|
|
// We must remove ourselves from each track's principal change observer list
|
2019-07-31 10:58:17 +03:00
|
|
|
// before we die.
|
|
|
|
if (!track->Ended()) {
|
|
|
|
track->RemoveConsumer(mPlaybackTrackListener);
|
2016-03-16 18:08:43 +03:00
|
|
|
}
|
|
|
|
}
|
2016-06-29 13:27:13 +03:00
|
|
|
mTrackListeners.Clear();
|
2012-04-30 07:11:34 +04:00
|
|
|
}
|
|
|
|
|
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 17:13:33 +03:00
|
|
|
JSObject* DOMMediaStream::WrapObject(JSContext* aCx,
|
|
|
|
JS::Handle<JSObject*> aGivenProto) {
|
2018-06-26 00:20:54 +03:00
|
|
|
return dom::MediaStream_Binding::Wrap(aCx, this, aGivenProto);
|
2012-04-30 07:11:34 +04:00
|
|
|
}
|
|
|
|
|
2019-02-26 01:05:29 +03:00
|
|
|
/* static */
|
|
|
|
already_AddRefed<DOMMediaStream> DOMMediaStream::Constructor(
|
2015-10-14 20:08:33 +03:00
|
|
|
const GlobalObject& aGlobal, ErrorResult& aRv) {
|
|
|
|
Sequence<OwningNonNull<MediaStreamTrack>> emptyTrackSeq;
|
|
|
|
return Constructor(aGlobal, emptyTrackSeq, aRv);
|
|
|
|
}
|
|
|
|
|
2019-02-26 01:05:29 +03:00
|
|
|
/* static */
|
|
|
|
already_AddRefed<DOMMediaStream> DOMMediaStream::Constructor(
|
2015-10-14 20:08:33 +03:00
|
|
|
const GlobalObject& aGlobal, const DOMMediaStream& aStream,
|
|
|
|
ErrorResult& aRv) {
|
2015-10-18 08:24:48 +03:00
|
|
|
nsTArray<RefPtr<MediaStreamTrack>> tracks;
|
2015-10-14 20:08:33 +03:00
|
|
|
aStream.GetTracks(tracks);
|
|
|
|
|
|
|
|
Sequence<OwningNonNull<MediaStreamTrack>> nonNullTrackSeq;
|
|
|
|
if (!nonNullTrackSeq.SetLength(tracks.Length(), fallible)) {
|
|
|
|
MOZ_ASSERT(false);
|
|
|
|
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t i = 0; i < tracks.Length(); ++i) {
|
|
|
|
nonNullTrackSeq[i] = tracks[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
return Constructor(aGlobal, nonNullTrackSeq, aRv);
|
|
|
|
}
|
|
|
|
|
2019-02-26 01:05:29 +03:00
|
|
|
/* static */
|
|
|
|
already_AddRefed<DOMMediaStream> DOMMediaStream::Constructor(
|
2015-10-14 20:08:33 +03:00
|
|
|
const GlobalObject& aGlobal,
|
|
|
|
const Sequence<OwningNonNull<MediaStreamTrack>>& aTracks,
|
|
|
|
ErrorResult& aRv) {
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowInner> ownerWindow =
|
|
|
|
do_QueryInterface(aGlobal.GetAsSupports());
|
2015-10-14 20:08:33 +03:00
|
|
|
if (!ownerWindow) {
|
|
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2018-11-23 18:02:03 +03:00
|
|
|
auto newStream = MakeRefPtr<DOMMediaStream>(ownerWindow);
|
2015-10-14 20:08:33 +03:00
|
|
|
for (MediaStreamTrack& track : aTracks) {
|
|
|
|
newStream->AddTrack(track);
|
|
|
|
}
|
|
|
|
return newStream.forget();
|
|
|
|
}
|
|
|
|
|
2017-10-23 20:09:47 +03:00
|
|
|
already_AddRefed<Promise> DOMMediaStream::CountUnderlyingStreams(
|
|
|
|
const GlobalObject& aGlobal, ErrorResult& aRv) {
|
|
|
|
nsCOMPtr<nsPIDOMWindowInner> window =
|
|
|
|
do_QueryInterface(aGlobal.GetAsSupports());
|
|
|
|
if (!window) {
|
|
|
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(aGlobal.GetAsSupports());
|
|
|
|
if (!go) {
|
|
|
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
RefPtr<Promise> p = Promise::Create(go, aRv);
|
|
|
|
if (aRv.Failed()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2019-10-02 13:23:02 +03:00
|
|
|
MediaTrackGraph* graph = MediaTrackGraph::GetInstanceIfExists(
|
2020-03-16 15:56:20 +03:00
|
|
|
window, MediaTrackGraph::REQUEST_DEFAULT_SAMPLE_RATE,
|
|
|
|
MediaTrackGraph::DEFAULT_OUTPUT_DEVICE);
|
2017-10-23 20:09:47 +03:00
|
|
|
if (!graph) {
|
|
|
|
p->MaybeResolve(0);
|
|
|
|
return p.forget();
|
|
|
|
}
|
|
|
|
|
2019-10-02 13:23:02 +03:00
|
|
|
auto* graphImpl = static_cast<MediaTrackGraphImpl*>(graph);
|
2017-10-23 20:09:47 +03:00
|
|
|
|
|
|
|
class Counter : public ControlMessage {
|
|
|
|
public:
|
2019-10-02 13:23:02 +03:00
|
|
|
Counter(MediaTrackGraphImpl* aGraph, const RefPtr<Promise>& aPromise)
|
2018-12-18 18:39:54 +03:00
|
|
|
: ControlMessage(nullptr), mGraph(aGraph), mPromise(aPromise) {
|
2017-10-23 20:09:47 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Run() override {
|
|
|
|
uint32_t streams =
|
2019-10-02 13:23:02 +03:00
|
|
|
mGraph->mTracks.Length() + mGraph->mSuspendedTracks.Length();
|
2018-12-19 07:34:10 +03:00
|
|
|
mGraph->DispatchToMainThreadStableState(NS_NewRunnableFunction(
|
2018-12-18 18:39:54 +03:00
|
|
|
"DOMMediaStream::CountUnderlyingStreams (stable state)",
|
|
|
|
[promise = std::move(mPromise), streams]() mutable {
|
|
|
|
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
|
|
|
"DOMMediaStream::CountUnderlyingStreams",
|
|
|
|
[promise = std::move(promise), streams]() {
|
|
|
|
promise->MaybeResolve(streams);
|
|
|
|
}));
|
2017-10-23 20:09:47 +03:00
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
2018-12-18 18:39:54 +03:00
|
|
|
// mPromise can only be AddRefed/Released on main thread.
|
|
|
|
// In case of shutdown, Run() does not run, so we dispatch mPromise to be
|
|
|
|
// released on main thread here.
|
|
|
|
void RunDuringShutdown() override {
|
2020-04-07 18:16:23 +03:00
|
|
|
NS_ReleaseOnMainThread(
|
2018-12-18 18:39:54 +03:00
|
|
|
"DOMMediaStream::CountUnderlyingStreams::Counter::RunDuringShutdown",
|
|
|
|
mPromise.forget());
|
|
|
|
}
|
|
|
|
|
2017-10-23 20:09:47 +03:00
|
|
|
private:
|
|
|
|
// mGraph owns this Counter instance and decides its lifetime.
|
2019-10-02 13:23:02 +03:00
|
|
|
MediaTrackGraphImpl* mGraph;
|
2018-12-18 18:39:54 +03:00
|
|
|
RefPtr<Promise> mPromise;
|
2017-10-23 20:09:47 +03:00
|
|
|
};
|
|
|
|
graphImpl->AppendMessage(MakeUnique<Counter>(graphImpl, p));
|
|
|
|
|
|
|
|
return p.forget();
|
|
|
|
}
|
|
|
|
|
2015-02-05 19:03:00 +03:00
|
|
|
void DOMMediaStream::GetId(nsAString& aID) const { aID = mID; }
|
|
|
|
|
2018-10-11 18:36:11 +03:00
|
|
|
void DOMMediaStream::GetAudioTracks(
|
|
|
|
nsTArray<RefPtr<AudioStreamTrack>>& aTracks) const {
|
2019-07-31 10:58:17 +03:00
|
|
|
for (const auto& track : mTracks) {
|
|
|
|
if (AudioStreamTrack* t = track->AsAudioStreamTrack()) {
|
2013-04-17 09:18:37 +04:00
|
|
|
aTracks.AppendElement(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-11 18:36:11 +03:00
|
|
|
void DOMMediaStream::GetAudioTracks(
|
|
|
|
nsTArray<RefPtr<MediaStreamTrack>>& aTracks) const {
|
2019-07-31 10:58:17 +03:00
|
|
|
for (const auto& track : mTracks) {
|
|
|
|
if (track->AsAudioStreamTrack()) {
|
|
|
|
aTracks.AppendElement(track);
|
2018-10-11 18:36:11 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DOMMediaStream::GetVideoTracks(
|
|
|
|
nsTArray<RefPtr<VideoStreamTrack>>& aTracks) const {
|
2019-07-31 10:58:17 +03:00
|
|
|
for (const auto& track : mTracks) {
|
|
|
|
if (VideoStreamTrack* t = track->AsVideoStreamTrack()) {
|
2013-04-17 09:18:37 +04:00
|
|
|
aTracks.AppendElement(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-11 18:36:11 +03:00
|
|
|
void DOMMediaStream::GetVideoTracks(
|
|
|
|
nsTArray<RefPtr<MediaStreamTrack>>& aTracks) const {
|
2019-07-31 10:58:17 +03:00
|
|
|
for (const auto& track : mTracks) {
|
|
|
|
if (track->AsVideoStreamTrack()) {
|
|
|
|
aTracks.AppendElement(track);
|
2018-10-11 18:36:11 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
void DOMMediaStream::GetTracks(
|
|
|
|
nsTArray<RefPtr<MediaStreamTrack>>& aTracks) const {
|
2019-07-31 10:58:17 +03:00
|
|
|
for (const auto& track : mTracks) {
|
|
|
|
aTracks.AppendElement(track);
|
2015-09-30 04:31:54 +03:00
|
|
|
}
|
2014-08-14 05:40:54 +04:00
|
|
|
}
|
|
|
|
|
2015-09-30 04:32:05 +03:00
|
|
|
void DOMMediaStream::AddTrack(MediaStreamTrack& aTrack) {
|
2019-10-02 13:23:02 +03:00
|
|
|
LOG(LogLevel::Info, ("DOMMediaStream %p Adding track %p (from track %p)",
|
|
|
|
this, &aTrack, aTrack.GetTrack()));
|
2015-10-14 20:08:33 +03:00
|
|
|
|
2015-09-30 04:32:05 +03:00
|
|
|
if (HasTrack(aTrack)) {
|
|
|
|
LOG(LogLevel::Debug,
|
|
|
|
("DOMMediaStream %p already contains track %p", this, &aTrack));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-07-31 10:58:17 +03:00
|
|
|
mTracks.AppendElement(&aTrack);
|
2020-11-17 04:47:33 +03:00
|
|
|
|
|
|
|
if (!aTrack.Ended()) {
|
|
|
|
NotifyTrackAdded(&aTrack);
|
|
|
|
}
|
2015-09-30 04:32:05 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void DOMMediaStream::RemoveTrack(MediaStreamTrack& aTrack) {
|
2019-10-02 13:23:02 +03:00
|
|
|
LOG(LogLevel::Info, ("DOMMediaStream %p Removing track %p (from track %p)",
|
|
|
|
this, &aTrack, aTrack.GetTrack()));
|
2015-09-30 04:32:05 +03:00
|
|
|
|
2019-07-31 10:58:17 +03:00
|
|
|
if (!mTracks.RemoveElement(&aTrack)) {
|
2015-09-30 04:32:05 +03:00
|
|
|
LOG(LogLevel::Debug,
|
|
|
|
("DOMMediaStream %p does not contain track %p", this, &aTrack));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-05-31 15:55:51 +03:00
|
|
|
if (!aTrack.Ended()) {
|
2016-12-01 21:35:48 +03:00
|
|
|
NotifyTrackRemoved(&aTrack);
|
2016-09-08 14:44:49 +03:00
|
|
|
}
|
2015-09-30 04:32:05 +03:00
|
|
|
}
|
|
|
|
|
2016-01-22 11:51:37 +03:00
|
|
|
already_AddRefed<DOMMediaStream> DOMMediaStream::Clone() {
|
2018-11-23 18:02:03 +03:00
|
|
|
auto newStream = MakeRefPtr<DOMMediaStream>(GetParentObject());
|
2016-01-22 11:51:37 +03:00
|
|
|
|
|
|
|
LOG(LogLevel::Info,
|
2018-11-23 18:02:03 +03:00
|
|
|
("DOMMediaStream %p created clone %p", this, newStream.get()));
|
2016-01-22 11:51:37 +03:00
|
|
|
|
2019-07-31 10:58:17 +03:00
|
|
|
for (const auto& track : mTracks) {
|
2016-01-22 11:51:37 +03:00
|
|
|
LOG(LogLevel::Debug,
|
|
|
|
("DOMMediaStream %p forwarding external track %p to clone %p", this,
|
2019-07-31 10:58:17 +03:00
|
|
|
track.get(), newStream.get()));
|
|
|
|
RefPtr<MediaStreamTrack> clone = track->Clone();
|
|
|
|
newStream->AddTrack(*clone);
|
2016-01-22 11:51:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return newStream.forget();
|
|
|
|
}
|
|
|
|
|
2016-09-08 14:44:49 +03:00
|
|
|
bool DOMMediaStream::Active() const { return mActive; }
|
2019-11-14 01:39:53 +03:00
|
|
|
bool DOMMediaStream::Audible() const { return mAudible; }
|
2016-09-08 14:44:49 +03:00
|
|
|
|
2016-05-20 14:01:30 +03:00
|
|
|
MediaStreamTrack* DOMMediaStream::GetTrackById(const nsAString& aId) const {
|
2019-07-31 10:58:17 +03:00
|
|
|
for (const auto& track : mTracks) {
|
2016-01-05 05:16:23 +03:00
|
|
|
nsString id;
|
2019-07-31 10:58:17 +03:00
|
|
|
track->GetId(id);
|
2016-01-05 05:16:23 +03:00
|
|
|
if (id == aId) {
|
2019-07-31 10:58:17 +03:00
|
|
|
return track;
|
2016-01-05 05:16:23 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2014-08-14 05:40:54 +04:00
|
|
|
bool DOMMediaStream::HasTrack(const MediaStreamTrack& aTrack) const {
|
2019-07-31 10:58:17 +03:00
|
|
|
return mTracks.Contains(&aTrack);
|
2012-04-30 07:11:34 +04:00
|
|
|
}
|
2013-02-15 12:04:11 +04:00
|
|
|
|
2016-08-12 14:50:41 +03:00
|
|
|
void DOMMediaStream::AddTrackInternal(MediaStreamTrack* aTrack) {
|
|
|
|
LOG(LogLevel::Debug,
|
|
|
|
("DOMMediaStream %p Adding owned track %p", this, aTrack));
|
2019-07-31 10:58:17 +03:00
|
|
|
AddTrack(*aTrack);
|
2016-08-12 14:50:41 +03:00
|
|
|
DispatchTrackEvent(u"addtrack"_ns, aTrack);
|
|
|
|
}
|
|
|
|
|
2019-11-20 18:24:10 +03:00
|
|
|
void DOMMediaStream::RemoveTrackInternal(MediaStreamTrack* aTrack) {
|
|
|
|
LOG(LogLevel::Debug,
|
|
|
|
("DOMMediaStream %p Removing owned track %p", this, aTrack));
|
|
|
|
if (!HasTrack(*aTrack)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
RemoveTrack(*aTrack);
|
|
|
|
DispatchTrackEvent(u"removetrack"_ns, aTrack);
|
|
|
|
}
|
|
|
|
|
2019-07-31 10:58:17 +03:00
|
|
|
already_AddRefed<nsIPrincipal> DOMMediaStream::GetPrincipal() {
|
|
|
|
nsCOMPtr<nsIPrincipal> principal =
|
|
|
|
nsGlobalWindowInner::Cast(mWindow)->GetPrincipal();
|
|
|
|
for (const auto& t : mTracks) {
|
|
|
|
if (t->Ended()) {
|
|
|
|
continue;
|
2013-04-17 09:18:24 +04:00
|
|
|
}
|
2019-07-31 10:58:17 +03:00
|
|
|
nsContentUtils::CombineResourcePrincipals(&principal, t->GetPrincipal());
|
2013-04-17 09:18:24 +04:00
|
|
|
}
|
2019-07-31 10:58:17 +03:00
|
|
|
return principal.forget();
|
2015-09-30 04:32:05 +03:00
|
|
|
}
|
|
|
|
|
2016-09-08 14:44:49 +03:00
|
|
|
void DOMMediaStream::NotifyActive() {
|
|
|
|
LOG(LogLevel::Info, ("DOMMediaStream %p NotifyActive(). ", this));
|
|
|
|
|
|
|
|
MOZ_ASSERT(mActive);
|
|
|
|
for (int32_t i = mTrackListeners.Length() - 1; i >= 0; --i) {
|
|
|
|
mTrackListeners[i]->NotifyActive();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DOMMediaStream::NotifyInactive() {
|
|
|
|
LOG(LogLevel::Info, ("DOMMediaStream %p NotifyInactive(). ", this));
|
|
|
|
|
|
|
|
MOZ_ASSERT(!mActive);
|
|
|
|
for (int32_t i = mTrackListeners.Length() - 1; i >= 0; --i) {
|
|
|
|
mTrackListeners[i]->NotifyInactive();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-02 16:53:50 +03:00
|
|
|
void DOMMediaStream::NotifyAudible() {
|
|
|
|
LOG(LogLevel::Info, ("DOMMediaStream %p NotifyAudible(). ", this));
|
|
|
|
|
|
|
|
MOZ_ASSERT(mAudible);
|
|
|
|
for (int32_t i = mTrackListeners.Length() - 1; i >= 0; --i) {
|
|
|
|
mTrackListeners[i]->NotifyAudible();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DOMMediaStream::NotifyInaudible() {
|
|
|
|
LOG(LogLevel::Info, ("DOMMediaStream %p NotifyInaudible(). ", this));
|
|
|
|
|
|
|
|
MOZ_ASSERT(!mAudible);
|
|
|
|
for (int32_t i = mTrackListeners.Length() - 1; i >= 0; --i) {
|
|
|
|
mTrackListeners[i]->NotifyInaudible();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-30 04:32:06 +03:00
|
|
|
void DOMMediaStream::RegisterTrackListener(TrackListener* aListener) {
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2015-09-25 23:08:44 +03:00
|
|
|
|
2015-09-30 04:32:06 +03:00
|
|
|
mTrackListeners.AppendElement(aListener);
|
2014-05-23 13:34:14 +04:00
|
|
|
}
|
|
|
|
|
2015-09-30 04:32:06 +03:00
|
|
|
void DOMMediaStream::UnregisterTrackListener(TrackListener* aListener) {
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
mTrackListeners.RemoveElement(aListener);
|
2014-05-23 13:34:14 +04:00
|
|
|
}
|
|
|
|
|
2016-01-21 14:05:53 +03:00
|
|
|
void DOMMediaStream::NotifyTrackAdded(const RefPtr<MediaStreamTrack>& aTrack) {
|
2015-09-30 04:32:06 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2015-09-25 23:08:44 +03:00
|
|
|
|
2016-09-23 18:03:13 +03:00
|
|
|
aTrack->AddConsumer(mPlaybackTrackListener);
|
2016-03-16 18:08:43 +03:00
|
|
|
|
2015-09-30 04:32:06 +03:00
|
|
|
for (int32_t i = mTrackListeners.Length() - 1; i >= 0; --i) {
|
2016-01-05 05:16:28 +03:00
|
|
|
mTrackListeners[i]->NotifyTrackAdded(aTrack);
|
2014-10-04 01:29:29 +04:00
|
|
|
}
|
2016-09-08 14:44:49 +03:00
|
|
|
|
2019-09-02 16:53:50 +03:00
|
|
|
if (!mActive) {
|
|
|
|
// Check if we became active.
|
|
|
|
if (ContainsLiveTracks(mTracks)) {
|
|
|
|
mActive = true;
|
|
|
|
NotifyActive();
|
|
|
|
}
|
2016-09-08 14:44:49 +03:00
|
|
|
}
|
|
|
|
|
2019-09-02 16:53:50 +03:00
|
|
|
if (!mAudible) {
|
|
|
|
// Check if we became audible.
|
|
|
|
if (ContainsLiveAudioTracks(mTracks)) {
|
|
|
|
mAudible = true;
|
|
|
|
NotifyAudible();
|
|
|
|
}
|
2016-09-08 14:44:49 +03:00
|
|
|
}
|
2014-10-04 01:29:29 +04:00
|
|
|
}
|
|
|
|
|
2016-01-21 14:05:53 +03:00
|
|
|
void DOMMediaStream::NotifyTrackRemoved(
|
|
|
|
const RefPtr<MediaStreamTrack>& aTrack) {
|
2015-09-30 04:32:06 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2014-12-12 06:54:12 +03:00
|
|
|
|
2018-11-23 17:59:56 +03:00
|
|
|
if (aTrack) {
|
|
|
|
// aTrack may be null to allow HTMLMediaElement::MozCaptureStream streams
|
|
|
|
// to be played until the source media element has ended. The source media
|
|
|
|
// element will then call NotifyTrackRemoved(nullptr) to signal that we can
|
|
|
|
// go inactive, regardless of the timing of the last track ending.
|
2016-03-16 18:08:43 +03:00
|
|
|
|
2018-11-23 17:59:56 +03:00
|
|
|
aTrack->RemoveConsumer(mPlaybackTrackListener);
|
|
|
|
|
|
|
|
for (int32_t i = mTrackListeners.Length() - 1; i >= 0; --i) {
|
|
|
|
mTrackListeners[i]->NotifyTrackRemoved(aTrack);
|
|
|
|
}
|
2016-03-16 18:08:43 +03:00
|
|
|
|
2018-11-23 17:59:56 +03:00
|
|
|
if (!mActive) {
|
|
|
|
NS_ASSERTION(false, "Shouldn't remove a live track if already inactive");
|
|
|
|
return;
|
|
|
|
}
|
2016-09-08 14:44:49 +03:00
|
|
|
}
|
|
|
|
|
2019-09-02 16:53:50 +03:00
|
|
|
if (mAudible) {
|
|
|
|
// Check if we became inaudible.
|
|
|
|
if (!ContainsLiveAudioTracks(mTracks)) {
|
|
|
|
mAudible = false;
|
|
|
|
NotifyInaudible();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-15 15:18:22 +03:00
|
|
|
// Check if we became inactive.
|
|
|
|
if (!ContainsLiveTracks(mTracks)) {
|
2016-09-08 14:44:49 +03:00
|
|
|
mActive = false;
|
|
|
|
NotifyInactive();
|
|
|
|
}
|
2014-05-23 13:34:14 +04:00
|
|
|
}
|
|
|
|
|
2016-05-31 10:29:52 +03:00
|
|
|
nsresult DOMMediaStream::DispatchTrackEvent(
|
|
|
|
const nsAString& aName, const RefPtr<MediaStreamTrack>& aTrack) {
|
|
|
|
MediaStreamTrackEventInit init;
|
|
|
|
init.mTrack = aTrack;
|
|
|
|
|
|
|
|
RefPtr<MediaStreamTrackEvent> event =
|
|
|
|
MediaStreamTrackEvent::Constructor(this, aName, init);
|
|
|
|
|
|
|
|
return DispatchTrustedEvent(event);
|
|
|
|
}
|