mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-15 06:15:43 +00:00
Bug 969372: part2: 1. Let Session hold a reference to MediaRecorder. 2. MediaRecorder implement nsIDocumentActivity. r=roc
This commit is contained in:
parent
e1204d9e47
commit
1f65ce65cb
@ -37,6 +37,7 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED(MediaRecorder, DOMEventTargetHelper,
|
||||
mStream)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaRecorder)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDocumentActivity)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(MediaRecorder, DOMEventTargetHelper)
|
||||
@ -68,10 +69,15 @@ NS_IMPL_RELEASE_INHERITED(MediaRecorder, DOMEventTargetHelper)
|
||||
* Switch from Extract stage to Destroy stage by calling Session::Stop.
|
||||
* Release session resource and remove associated streams from MSG.
|
||||
*
|
||||
* Lifetime of a Session object.
|
||||
* Lifetime of MediaRecorder and Session objects.
|
||||
* 1) MediaRecorder creates a Session in MediaRecorder::Start function.
|
||||
* And the Session registers itself to ShutdownObserver and also holds a
|
||||
* MediaRecorder. Therefore, the reference dependency in gecko is:
|
||||
* ShutdownObserver -> Session -> MediaRecorder
|
||||
* 2) A Session is destroyed in DestroyRunnable after MediaRecorder::Stop being called
|
||||
* _and_ all encoded media data been passed to OnDataAvailable handler.
|
||||
* 3) MediaRecorder::Stop is called by user or the document is going to
|
||||
* inactive or invisible.
|
||||
*/
|
||||
class MediaRecorder::Session: public nsIObserver
|
||||
{
|
||||
@ -93,7 +99,7 @@ class MediaRecorder::Session: public nsIObserver
|
||||
|
||||
nsRefPtr<MediaRecorder> recorder = mSession->mRecorder;
|
||||
if (!recorder) {
|
||||
return NS_OK;
|
||||
return NS_OK;
|
||||
}
|
||||
recorder->SetMimeType(mSession->mMimeType);
|
||||
if (mSession->IsEncoderError()) {
|
||||
@ -291,11 +297,7 @@ public:
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void ForgetMediaRecorder()
|
||||
{
|
||||
LOG(PR_LOG_DEBUG, ("Session.ForgetMediaRecorder (%p)", mRecorder));
|
||||
mRecorder = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Pull encoded meida data from MediaEncoder and put into EncodedBufferCache.
|
||||
@ -340,7 +342,7 @@ private:
|
||||
mInputPort = mTrackUnionStream->AllocateInputPort(mRecorder->mStream->GetStream(), MediaInputPort::FLAG_BLOCK_OUTPUT);
|
||||
|
||||
// Allocate encoder and bind with the Track Union Stream.
|
||||
TracksAvailableCallback* tracksAvailableCallback = new TracksAvailableCallback(mRecorder->mSessions.LastElement());
|
||||
TracksAvailableCallback* tracksAvailableCallback = new TracksAvailableCallback(this);
|
||||
mRecorder->mStream->OnTracksAvailable(tracksAvailableCallback);
|
||||
}
|
||||
|
||||
@ -441,8 +443,9 @@ private:
|
||||
}
|
||||
|
||||
private:
|
||||
// Hold weak a reference to MediaRecoder and can be accessed ONLY on main thread.
|
||||
MediaRecorder* mRecorder;
|
||||
// Hold reference to MediaRecoder that ensure MediaRecorder is alive
|
||||
// if there is an active session. Access ONLY on main thread.
|
||||
nsRefPtr<MediaRecorder> mRecorder;
|
||||
|
||||
// Receive track data from source and dispatch to Encoder.
|
||||
// Pause/ Resume controller.
|
||||
@ -473,12 +476,7 @@ NS_IMPL_ISUPPORTS(MediaRecorder::Session, nsIObserver)
|
||||
MediaRecorder::~MediaRecorder()
|
||||
{
|
||||
LOG(PR_LOG_DEBUG, ("~MediaRecorder (%p)", this));
|
||||
for (uint32_t i = 0; i < mSessions.Length(); i ++) {
|
||||
if (mSessions[i]) {
|
||||
mSessions[i]->ForgetMediaRecorder();
|
||||
mSessions[i]->Stop();
|
||||
}
|
||||
}
|
||||
UnRegisterActivityObserver();
|
||||
}
|
||||
|
||||
MediaRecorder::MediaRecorder(DOMMediaStream& aStream, nsPIDOMWindow* aOwnerWindow)
|
||||
@ -494,6 +492,33 @@ MediaRecorder::MediaRecorder(DOMMediaStream& aStream, nsPIDOMWindow* aOwnerWindo
|
||||
gMediaRecorderLog = PR_NewLogModule("MediaRecorder");
|
||||
}
|
||||
#endif
|
||||
RegisterActivityObserver();
|
||||
}
|
||||
|
||||
void
|
||||
MediaRecorder::RegisterActivityObserver()
|
||||
{
|
||||
nsPIDOMWindow* window = GetOwner();
|
||||
if (window) {
|
||||
nsIDocument* doc = window->GetExtantDoc();
|
||||
if (doc) {
|
||||
doc->RegisterActivityObserver(
|
||||
NS_ISUPPORTS_CAST(nsIDocumentActivity*, this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MediaRecorder::UnRegisterActivityObserver()
|
||||
{
|
||||
nsPIDOMWindow* window = GetOwner();
|
||||
if (window) {
|
||||
nsIDocument* doc = window->GetExtantDoc();
|
||||
if (doc) {
|
||||
doc->UnregisterActivityObserver(
|
||||
NS_ISUPPORTS_CAST(nsIDocumentActivity*, this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -561,9 +586,8 @@ MediaRecorder::Stop(ErrorResult& aResult)
|
||||
return;
|
||||
}
|
||||
mState = RecordingState::Inactive;
|
||||
if (mSessions.Length() > 0) {
|
||||
mSessions.LastElement()->Stop();
|
||||
}
|
||||
MOZ_ASSERT(mSessions.Length() > 0);
|
||||
mSessions.LastElement()->Stop();
|
||||
}
|
||||
|
||||
void
|
||||
@ -628,7 +652,7 @@ MediaRecorder::RequestData(ErrorResult& aResult)
|
||||
aResult.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mSessions.Length() > 0);
|
||||
NS_DispatchToMainThread(
|
||||
new CreateAndDispatchBlobEventRunnable(mSessions.LastElement()->GetEncodedData(),
|
||||
this));
|
||||
@ -778,5 +802,22 @@ MediaRecorder::RemoveSession(Session* aSession)
|
||||
mSessions.RemoveElement(aSession);
|
||||
}
|
||||
|
||||
void
|
||||
MediaRecorder::NotifyOwnerDocumentActivityChanged()
|
||||
{
|
||||
nsPIDOMWindow* window = GetOwner();
|
||||
NS_ENSURE_TRUE_VOID(window);
|
||||
nsIDocument* doc = window->GetExtantDoc();
|
||||
NS_ENSURE_TRUE_VOID(doc);
|
||||
|
||||
LOG(PR_LOG_DEBUG, ("MediaRecorder %p document IsActive %d isVisible %d\n",
|
||||
this, doc->IsActive(), doc->IsVisible()));
|
||||
if (!doc->IsActive() || !doc->IsVisible()) {
|
||||
// Stop the session.
|
||||
ErrorResult result;
|
||||
Stop(result);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "mozilla/dom/MediaRecorderBinding.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "nsIDocumentActivity.h"
|
||||
|
||||
// Max size for allowing queue encoded data in memory
|
||||
#define MAX_ALLOW_MEMORY_BUFFER 1024000
|
||||
@ -35,7 +36,8 @@ namespace dom {
|
||||
* Also extract the encoded data and create blobs on every timeslice passed from start function or RequestData function called by UA.
|
||||
*/
|
||||
|
||||
class MediaRecorder : public DOMEventTargetHelper
|
||||
class MediaRecorder : public DOMEventTargetHelper,
|
||||
public nsIDocumentActivity
|
||||
{
|
||||
class Session;
|
||||
friend class CreateAndDispatchBlobEventRunnable;
|
||||
@ -85,6 +87,8 @@ public:
|
||||
IMPL_EVENT_HANDLER(stop)
|
||||
IMPL_EVENT_HANDLER(warning)
|
||||
|
||||
NS_DECL_NSIDOCUMENTACTIVITY
|
||||
|
||||
protected:
|
||||
MediaRecorder& operator = (const MediaRecorder& x) MOZ_DELETE;
|
||||
// Create dataavailable event with Blob data and it runs in main thread
|
||||
@ -105,12 +109,18 @@ protected:
|
||||
nsRefPtr<DOMMediaStream> mStream;
|
||||
// The current state of the MediaRecorder object.
|
||||
RecordingState mState;
|
||||
// Hold the sessions pointer in media recorder and clean in the destructor of recorder.
|
||||
// Hold the sessions pointer and clean it when the DestroyRunnable for a
|
||||
// session is running.
|
||||
nsTArray<Session*> mSessions;
|
||||
// Thread safe for mMimeType.
|
||||
Mutex mMutex;
|
||||
// It specifies the container format as well as the audio and video capture formats.
|
||||
nsString mMimeType;
|
||||
|
||||
private:
|
||||
// Register MediaRecorder into Document to listen the activity changes.
|
||||
void RegisterActivityObserver();
|
||||
void UnRegisterActivityObserver();
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user