Bug 1208371 - Add a MediaStreamTrackListener to MediaStreamGraph. r=roc

MozReview-Commit-ID: 6KHzimw9kiP

--HG--
extra : rebase_source : 78e7f4b4bf18eaf390ee09c08f6f5c19d9f24d65
This commit is contained in:
Andreas Pehrson 2016-03-03 17:27:59 +01:00
Родитель 053fc72107
Коммит 8ee8a34873
5 изменённых файлов: 169 добавлений и 2 удалений

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

@ -183,12 +183,21 @@ MediaStreamGraphImpl::ExtractPendingInput(SourceMediaStream* aStream,
for (int32_t i = aStream->mUpdateTracks.Length() - 1; i >= 0; --i) {
SourceMediaStream::TrackData* data = &aStream->mUpdateTracks[i];
aStream->ApplyTrackDisabling(data->mID, data->mData);
StreamTime offset = (data->mCommands & SourceMediaStream::TRACK_CREATE)
? data->mStart : aStream->mBuffer.FindTrack(data->mID)->GetSegment()->GetDuration();
for (MediaStreamListener* l : aStream->mListeners) {
StreamTime offset = (data->mCommands & SourceMediaStream::TRACK_CREATE)
? data->mStart : aStream->mBuffer.FindTrack(data->mID)->GetSegment()->GetDuration();
l->NotifyQueuedTrackChanges(this, data->mID,
offset, data->mCommands, *data->mData);
}
for (TrackBound<MediaStreamTrackListener>& b : aStream->mTrackListeners) {
if (b.mTrackID != data->mID) {
continue;
}
b.mListener->NotifyQueuedChanges(this, offset, *data->mData);
if (data->mCommands & SourceMediaStream::TRACK_END) {
b.mListener->NotifyEnded();
}
}
if (data->mCommands & SourceMediaStream::TRACK_CREATE) {
MediaSegment* segment = data->mData.forget();
STREAM_LOG(LogLevel::Debug, ("SourceMediaStream %p creating track %d, start %lld, initial end %lld",
@ -2264,6 +2273,67 @@ MediaStream::RemoveListener(MediaStreamListener* aListener)
}
}
void
MediaStream::AddTrackListenerImpl(already_AddRefed<MediaStreamTrackListener> aListener,
TrackID aTrackID)
{
TrackBound<MediaStreamTrackListener>* l = mTrackListeners.AppendElement();
l->mListener = aListener;
l->mTrackID = aTrackID;
}
void
MediaStream::AddTrackListener(MediaStreamTrackListener* aListener,
TrackID aTrackID)
{
class Message : public ControlMessage {
public:
Message(MediaStream* aStream, MediaStreamTrackListener* aListener,
TrackID aTrackID) :
ControlMessage(aStream), mListener(aListener), mTrackID(aTrackID) {}
virtual void Run()
{
mStream->AddTrackListenerImpl(mListener.forget(), mTrackID);
}
RefPtr<MediaStreamTrackListener> mListener;
TrackID mTrackID;
};
GraphImpl()->AppendMessage(MakeUnique<Message>(this, aListener, aTrackID));
}
void
MediaStream::RemoveTrackListenerImpl(MediaStreamTrackListener* aListener,
TrackID aTrackID)
{
for (size_t i = 0; i < mTrackListeners.Length(); ++i) {
if (mTrackListeners[i].mListener == aListener &&
mTrackListeners[i].mTrackID == aTrackID) {
mTrackListeners[i].mListener->NotifyRemoved();
mTrackListeners.RemoveElementAt(i);
return;
}
}
}
void
MediaStream::RemoveTrackListener(MediaStreamTrackListener* aListener,
TrackID aTrackID)
{
class Message : public ControlMessage {
public:
Message(MediaStream* aStream, MediaStreamTrackListener* aListener,
TrackID aTrackID) :
ControlMessage(aStream), mListener(aListener), mTrackID(aTrackID) {}
virtual void Run()
{
mStream->RemoveTrackListenerImpl(mListener, mTrackID);
}
RefPtr<MediaStreamTrackListener> mListener;
TrackID mTrackID;
};
GraphImpl()->AppendMessage(MakeUnique<Message>(this, aListener, aTrackID));
}
void
MediaStream::RunAfterPendingUpdates(already_AddRefed<nsIRunnable> aRunnable)
{

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

@ -216,6 +216,41 @@ public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AudioDataListener)
};
/**
* This is a base class for media graph thread listener callbacks locked to
* specific tracks. Override methods to be notified of audio or video data or
* changes in track state.
*
* All notification methods are called from the media graph thread. Overriders
* of these methods are responsible for all synchronization. Beware!
* These methods are called without the media graph monitor held, so
* reentry into media graph methods is possible, although very much discouraged!
* You should do something non-blocking and non-reentrant (e.g. dispatch an
* event to some thread) and return.
* The listener is not allowed to add/remove any listeners from the parent
* stream.
*
* If a listener is attached to a track that has already ended, we guarantee
* to call NotifyEnded.
*/
class MediaStreamTrackListener
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaStreamTrackListener)
public:
virtual void NotifyQueuedChanges(MediaStreamGraph* aGraph,
StreamTime aTrackOffset,
const MediaSegment& aQueuedMedia) {}
virtual void NotifyEnded() {}
virtual void NotifyRemoved() {}
protected:
virtual ~MediaStreamTrackListener() {}
};
/**
* This is a base class for media graph thread listener direct callbacks
* from within AppendToTrack(). Note that your regular listener will
@ -278,6 +313,16 @@ class AudioNodeExternalInputStream;
class AudioNodeStream;
class CameraPreviewMediaStream;
/**
* Helper struct for binding a track listener to a specific TrackID.
*/
template<typename Listener>
struct TrackBound
{
RefPtr<Listener> mListener;
TrackID mTrackID;
};
/**
* A stream of synchronized audio and video data. All (not blocked) streams
* progress at the same rate --- "real time". Streams cannot seek. The only
@ -400,6 +445,10 @@ public:
// Events will be dispatched by calling methods of aListener.
virtual void AddListener(MediaStreamListener* aListener);
virtual void RemoveListener(MediaStreamListener* aListener);
virtual void AddTrackListener(MediaStreamTrackListener* aListener,
TrackID aTrackID);
virtual void RemoveTrackListener(MediaStreamTrackListener* aListener,
TrackID aTrackID);
// A disabled track has video replaced by black, and audio replaced by
// silence.
void SetTrackEnabled(TrackID aTrackID, bool aEnabled);
@ -496,6 +545,10 @@ public:
void AddListenerImpl(already_AddRefed<MediaStreamListener> aListener);
void RemoveListenerImpl(MediaStreamListener* aListener);
void RemoveAllListenersImpl();
virtual void AddTrackListenerImpl(already_AddRefed<MediaStreamTrackListener> aListener,
TrackID aTrackID);
virtual void RemoveTrackListenerImpl(MediaStreamTrackListener* aListener,
TrackID aTrackID);
virtual void SetTrackEnabledImpl(TrackID aTrackID, bool aEnabled);
void AddConsumer(MediaInputPort* aPort)
@ -649,6 +702,7 @@ protected:
// with a different frame id.
VideoFrame mLastPlayedVideoFrame;
nsTArray<RefPtr<MediaStreamListener> > mListeners;
nsTArray<TrackBound<MediaStreamTrackListener>> mTrackListeners;
nsTArray<MainThreadMediaStreamListener*> mMainThreadListeners;
nsTArray<TrackID> mDisabledTrackIDs;

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

@ -6,6 +6,7 @@
#include "MediaStreamTrack.h"
#include "DOMMediaStream.h"
#include "MediaStreamGraph.h"
#include "nsIUUIDGenerator.h"
#include "nsServiceManagerUtils.h"
@ -197,5 +198,23 @@ MediaStreamTrack::GetOwnedStream()
return GetStream()->GetOwnedStream();
}
void
MediaStreamTrack::AddListener(MediaStreamTrackListener* aListener)
{
LOG(LogLevel::Debug, ("MediaStreamTrack %p adding listener %p",
this, aListener));
GetOwnedStream()->AddTrackListener(aListener, mTrackID);
}
void
MediaStreamTrack::RemoveListener(MediaStreamTrackListener* aListener)
{
LOG(LogLevel::Debug, ("MediaStreamTrack %p removing listener %p",
this, aListener));
GetOwnedStream()->RemoveTrackListener(aListener, mTrackID);
}
} // namespace dom
} // namespace mozilla

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

@ -19,6 +19,7 @@ class DOMMediaStream;
class MediaEnginePhotoCallback;
class MediaStream;
class MediaStreamGraph;
class MediaStreamTrackListener;
class ProcessedMediaStream;
namespace dom {
@ -254,6 +255,18 @@ public:
*/
bool RemovePrincipalChangeObserver(PrincipalChangeObserver<MediaStreamTrack>* aObserver);
/**
* Adds a MediaStreamTrackListener to the MediaStreamGraph representation of
* this track.
*/
void AddListener(MediaStreamTrackListener* aListener);
/**
* Removes a MediaStreamTrackListener from the MediaStreamGraph representation
* of this track.
*/
void RemoveListener(MediaStreamTrackListener* aListener);
protected:
virtual ~MediaStreamTrack();

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

@ -239,6 +239,11 @@ TrackUnionStream::TrackUnionStream(DOMMediaStream* aWrapper) :
mTrackMap[aIndex].mInputPort->GetSource(),
mTrackMap[aIndex].mInputTrackID);
}
for (TrackBound<MediaStreamTrackListener>& b : mTrackListeners) {
if (b.mTrackID == outputTrack->GetID()) {
b.mListener->NotifyEnded();
}
}
outputTrack->SetEnded();
}
@ -300,6 +305,12 @@ TrackUnionStream::TrackUnionStream(DOMMediaStream* aWrapper) :
l->NotifyQueuedTrackChanges(Graph(), outputTrack->GetID(),
outputStart, 0, *segment);
}
for (TrackBound<MediaStreamTrackListener>& b : mTrackListeners) {
if (b.mTrackID != outputTrack->GetID()) {
continue;
}
b.mListener->NotifyQueuedChanges(Graph(), outputStart, *segment);
}
outputTrack->GetSegment()->AppendFrom(segment);
}
}