зеркало из https://github.com/mozilla/gecko-dev.git
Bug 912342 - Move code MediaOperationTask from .h to .cpp. r=jesup
--HG-- extra : commitid : L4YvvKBc9ft extra : rebase_source : 3f732a3e21b8a9038ce35f232c012169134248e9
This commit is contained in:
Родитель
f953fc2b69
Коммит
e5af2b70b2
|
@ -214,6 +214,151 @@ HostHasPermission(nsIURI &docURI)
|
|||
return false;
|
||||
}
|
||||
|
||||
// Generic class for running long media operations like Start off the main
|
||||
// thread, and then (because nsDOMMediaStreams aren't threadsafe),
|
||||
// ProxyReleases mStream since it's cycle collected.
|
||||
class MediaOperationTask : public Task
|
||||
{
|
||||
public:
|
||||
// so we can send Stop without AddRef()ing from the MSG thread
|
||||
MediaOperationTask(MediaOperation aType,
|
||||
GetUserMediaCallbackMediaStreamListener* aListener,
|
||||
DOMMediaStream* aStream,
|
||||
DOMMediaStream::OnTracksAvailableCallback* aOnTracksAvailableCallback,
|
||||
MediaEngineSource* aAudioSource,
|
||||
MediaEngineSource* aVideoSource,
|
||||
bool aBool,
|
||||
uint64_t aWindowID,
|
||||
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError)
|
||||
: mType(aType)
|
||||
, mStream(aStream)
|
||||
, mOnTracksAvailableCallback(aOnTracksAvailableCallback)
|
||||
, mAudioSource(aAudioSource)
|
||||
, mVideoSource(aVideoSource)
|
||||
, mListener(aListener)
|
||||
, mBool(aBool)
|
||||
, mWindowID(aWindowID)
|
||||
, mOnFailure(aError)
|
||||
{}
|
||||
|
||||
~MediaOperationTask()
|
||||
{
|
||||
// MediaStreams can be released on any thread.
|
||||
}
|
||||
|
||||
void
|
||||
ReturnCallbackError(nsresult rv, const char* errorLog);
|
||||
|
||||
void
|
||||
Run()
|
||||
{
|
||||
SourceMediaStream *source = mListener->GetSourceStream();
|
||||
// No locking between these is required as all the callbacks for the
|
||||
// same MediaStream will occur on the same thread.
|
||||
if (!source) // means the stream was never Activated()
|
||||
return;
|
||||
|
||||
switch (mType) {
|
||||
case MEDIA_START:
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Never call on main thread");
|
||||
nsresult rv;
|
||||
|
||||
if (mAudioSource) {
|
||||
rv = mAudioSource->Start(source, kAudioTrack);
|
||||
if (NS_FAILED(rv)) {
|
||||
ReturnCallbackError(rv, "Starting audio failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (mVideoSource) {
|
||||
rv = mVideoSource->Start(source, kVideoTrack);
|
||||
if (NS_FAILED(rv)) {
|
||||
ReturnCallbackError(rv, "Starting video failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Start() queued the tracks to be added synchronously to avoid races
|
||||
source->FinishAddTracks();
|
||||
|
||||
source->SetPullEnabled(true);
|
||||
source->AdvanceKnownTracksTime(STREAM_TIME_MAX);
|
||||
|
||||
MM_LOG(("started all sources"));
|
||||
// Forward mOnTracksAvailableCallback to GetUserMediaNotificationEvent,
|
||||
// because mOnTracksAvailableCallback needs to be added to mStream
|
||||
// on the main thread.
|
||||
nsIRunnable *event =
|
||||
new GetUserMediaNotificationEvent(GetUserMediaNotificationEvent::STARTING,
|
||||
mStream.forget(),
|
||||
mOnTracksAvailableCallback.forget(),
|
||||
mAudioSource != nullptr,
|
||||
mVideoSource != nullptr,
|
||||
mWindowID, mOnFailure.forget());
|
||||
// event must always be released on mainthread due to the JS callbacks
|
||||
// in the TracksAvailableCallback
|
||||
NS_DispatchToMainThread(event);
|
||||
}
|
||||
break;
|
||||
|
||||
case MEDIA_STOP:
|
||||
case MEDIA_STOP_TRACK:
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Never call on main thread");
|
||||
if (mAudioSource) {
|
||||
mAudioSource->Stop(source, kAudioTrack);
|
||||
mAudioSource->Deallocate();
|
||||
}
|
||||
if (mVideoSource) {
|
||||
mVideoSource->Stop(source, kVideoTrack);
|
||||
mVideoSource->Deallocate();
|
||||
}
|
||||
// Do this after stopping all tracks with EndTrack()
|
||||
if (mBool) {
|
||||
source->Finish();
|
||||
}
|
||||
|
||||
nsIRunnable *event =
|
||||
new GetUserMediaNotificationEvent(mListener,
|
||||
mType == MEDIA_STOP ?
|
||||
GetUserMediaNotificationEvent::STOPPING :
|
||||
GetUserMediaNotificationEvent::STOPPED_TRACK,
|
||||
mAudioSource != nullptr,
|
||||
mVideoSource != nullptr,
|
||||
mWindowID);
|
||||
// event must always be released on mainthread due to the JS callbacks
|
||||
// in the TracksAvailableCallback
|
||||
NS_DispatchToMainThread(event);
|
||||
}
|
||||
break;
|
||||
|
||||
case MEDIA_DIRECT_LISTENERS:
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Never call on main thread");
|
||||
if (mVideoSource) {
|
||||
mVideoSource->SetDirectListeners(mBool);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_ASSERT(false,"invalid MediaManager operation");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
MediaOperation mType;
|
||||
nsRefPtr<DOMMediaStream> mStream;
|
||||
nsAutoPtr<DOMMediaStream::OnTracksAvailableCallback> mOnTracksAvailableCallback;
|
||||
nsRefPtr<MediaEngineSource> mAudioSource; // threadsafe
|
||||
nsRefPtr<MediaEngineSource> mVideoSource; // threadsafe
|
||||
nsRefPtr<GetUserMediaCallbackMediaStreamListener> mListener; // threadsafe
|
||||
bool mBool;
|
||||
uint64_t mWindowID;
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
|
||||
};
|
||||
|
||||
/**
|
||||
* Send an error back to content.
|
||||
* Do this only on the main thread. The onSuccess callback is also passed here
|
||||
|
|
|
@ -310,151 +310,6 @@ private:
|
|||
nsAutoPtr<DOMMediaStream::OnTracksAvailableCallback> mOnTracksAvailableCallback;
|
||||
};
|
||||
|
||||
// Generic class for running long media operations like Start off the main
|
||||
// thread, and then (because nsDOMMediaStreams aren't threadsafe),
|
||||
// ProxyReleases mStream since it's cycle collected.
|
||||
class MediaOperationTask : public Task
|
||||
{
|
||||
public:
|
||||
// so we can send Stop without AddRef()ing from the MSG thread
|
||||
MediaOperationTask(MediaOperation aType,
|
||||
GetUserMediaCallbackMediaStreamListener* aListener,
|
||||
DOMMediaStream* aStream,
|
||||
DOMMediaStream::OnTracksAvailableCallback* aOnTracksAvailableCallback,
|
||||
MediaEngineSource* aAudioSource,
|
||||
MediaEngineSource* aVideoSource,
|
||||
bool aBool,
|
||||
uint64_t aWindowID,
|
||||
already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError)
|
||||
: mType(aType)
|
||||
, mStream(aStream)
|
||||
, mOnTracksAvailableCallback(aOnTracksAvailableCallback)
|
||||
, mAudioSource(aAudioSource)
|
||||
, mVideoSource(aVideoSource)
|
||||
, mListener(aListener)
|
||||
, mBool(aBool)
|
||||
, mWindowID(aWindowID)
|
||||
, mOnFailure(aError)
|
||||
{}
|
||||
|
||||
~MediaOperationTask()
|
||||
{
|
||||
// MediaStreams can be released on any thread.
|
||||
}
|
||||
|
||||
void
|
||||
ReturnCallbackError(nsresult rv, const char* errorLog);
|
||||
|
||||
void
|
||||
Run()
|
||||
{
|
||||
SourceMediaStream *source = mListener->GetSourceStream();
|
||||
// No locking between these is required as all the callbacks for the
|
||||
// same MediaStream will occur on the same thread.
|
||||
if (!source) // means the stream was never Activated()
|
||||
return;
|
||||
|
||||
switch (mType) {
|
||||
case MEDIA_START:
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Never call on main thread");
|
||||
nsresult rv;
|
||||
|
||||
if (mAudioSource) {
|
||||
rv = mAudioSource->Start(source, kAudioTrack);
|
||||
if (NS_FAILED(rv)) {
|
||||
ReturnCallbackError(rv, "Starting audio failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (mVideoSource) {
|
||||
rv = mVideoSource->Start(source, kVideoTrack);
|
||||
if (NS_FAILED(rv)) {
|
||||
ReturnCallbackError(rv, "Starting video failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Start() queued the tracks to be added synchronously to avoid races
|
||||
source->FinishAddTracks();
|
||||
|
||||
source->SetPullEnabled(true);
|
||||
source->AdvanceKnownTracksTime(STREAM_TIME_MAX);
|
||||
|
||||
MM_LOG(("started all sources"));
|
||||
// Forward mOnTracksAvailableCallback to GetUserMediaNotificationEvent,
|
||||
// because mOnTracksAvailableCallback needs to be added to mStream
|
||||
// on the main thread.
|
||||
nsIRunnable *event =
|
||||
new GetUserMediaNotificationEvent(GetUserMediaNotificationEvent::STARTING,
|
||||
mStream.forget(),
|
||||
mOnTracksAvailableCallback.forget(),
|
||||
mAudioSource != nullptr,
|
||||
mVideoSource != nullptr,
|
||||
mWindowID, mOnFailure.forget());
|
||||
// event must always be released on mainthread due to the JS callbacks
|
||||
// in the TracksAvailableCallback
|
||||
NS_DispatchToMainThread(event);
|
||||
}
|
||||
break;
|
||||
|
||||
case MEDIA_STOP:
|
||||
case MEDIA_STOP_TRACK:
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Never call on main thread");
|
||||
if (mAudioSource) {
|
||||
mAudioSource->Stop(source, kAudioTrack);
|
||||
mAudioSource->Deallocate();
|
||||
}
|
||||
if (mVideoSource) {
|
||||
mVideoSource->Stop(source, kVideoTrack);
|
||||
mVideoSource->Deallocate();
|
||||
}
|
||||
// Do this after stopping all tracks with EndTrack()
|
||||
if (mBool) {
|
||||
source->Finish();
|
||||
}
|
||||
|
||||
nsIRunnable *event =
|
||||
new GetUserMediaNotificationEvent(mListener,
|
||||
mType == MEDIA_STOP ?
|
||||
GetUserMediaNotificationEvent::STOPPING :
|
||||
GetUserMediaNotificationEvent::STOPPED_TRACK,
|
||||
mAudioSource != nullptr,
|
||||
mVideoSource != nullptr,
|
||||
mWindowID);
|
||||
// event must always be released on mainthread due to the JS callbacks
|
||||
// in the TracksAvailableCallback
|
||||
NS_DispatchToMainThread(event);
|
||||
}
|
||||
break;
|
||||
|
||||
case MEDIA_DIRECT_LISTENERS:
|
||||
{
|
||||
NS_ASSERTION(!NS_IsMainThread(), "Never call on main thread");
|
||||
if (mVideoSource) {
|
||||
mVideoSource->SetDirectListeners(mBool);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_ASSERT(false,"invalid MediaManager operation");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
MediaOperation mType;
|
||||
nsRefPtr<DOMMediaStream> mStream;
|
||||
nsAutoPtr<DOMMediaStream::OnTracksAvailableCallback> mOnTracksAvailableCallback;
|
||||
nsRefPtr<MediaEngineSource> mAudioSource; // threadsafe
|
||||
nsRefPtr<MediaEngineSource> mVideoSource; // threadsafe
|
||||
nsRefPtr<GetUserMediaCallbackMediaStreamListener> mListener; // threadsafe
|
||||
bool mBool;
|
||||
uint64_t mWindowID;
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
|
||||
};
|
||||
|
||||
typedef nsTArray<nsRefPtr<GetUserMediaCallbackMediaStreamListener> > StreamListeners;
|
||||
typedef nsClassHashtable<nsUint64HashKey, StreamListeners> WindowTable;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче