Bug 1129263 - Part 1. Add an event to MediaStreamListener for handling atomically added tracks. r=roc,jesup

This commit is contained in:
Andreas Pehrson 2015-02-06 17:38:11 +08:00
Родитель 786e0c77ee
Коммит f400cd176d
6 изменённых файлов: 72 добавлений и 4 удалений

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

@ -127,6 +127,7 @@ CameraPreviewMediaStream::OnPreviewStateChange(bool aActive)
l->NotifyQueuedTrackChanges(mFakeMediaStreamGraph, TRACK_VIDEO, 0,
MediaStreamListener::TRACK_EVENT_CREATED,
tmpSegment);
l->NotifyFinishedTrackCreation(mFakeMediaStreamGraph);
}
}
}

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

@ -98,6 +98,35 @@ public:
}
}
class TracksCreatedRunnable : public nsRunnable {
public:
explicit TracksCreatedRunnable(StreamListener* aListener)
: mListener(aListener)
{
}
NS_IMETHOD Run()
{
MOZ_ASSERT(NS_IsMainThread());
DOMMediaStream* stream = mListener->GetStream();
if (!stream) {
return NS_OK;
}
stream->TracksCreated();
return NS_OK;
}
nsRefPtr<StreamListener> mListener;
};
virtual void NotifyFinishedTrackCreation(MediaStreamGraph* aGraph) MOZ_OVERRIDE
{
nsRefPtr<TracksCreatedRunnable> runnable = new TracksCreatedRunnable(this);
aGraph->DispatchToMainThreadAfterStreamStateUpdate(runnable.forget());
}
private:
// These fields may only be accessed on the main thread
DOMMediaStream* mStream;
@ -145,7 +174,7 @@ NS_INTERFACE_MAP_END_INHERITING(DOMMediaStream)
DOMMediaStream::DOMMediaStream()
: mLogicalStreamStartTime(0),
mStream(nullptr), mHintContents(0), mTrackTypesAvailable(0),
mStream(nullptr), mTracksCreated(false),
mNotifiedOfMediaStreamGraphShutdown(false), mCORSMode(CORS_NONE)
{
nsresult rv;
@ -475,10 +504,18 @@ DOMMediaStream::OnTracksAvailable(OnTracksAvailableCallback* aRunnable)
CheckTracksAvailable();
}
void
DOMMediaStream::TracksCreated()
{
MOZ_ASSERT(!mTracks.IsEmpty());
mTracksCreated = true;
CheckTracksAvailable();
}
void
DOMMediaStream::CheckTracksAvailable()
{
if (mTrackTypesAvailable == 0) {
if (!mTracksCreated) {
return;
}
nsTArray<nsAutoPtr<OnTracksAvailableCallback> > callbacks;

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

@ -279,6 +279,10 @@ protected:
already_AddRefed<AudioTrack> CreateAudioTrack(AudioStreamTrack* aStreamTrack);
already_AddRefed<VideoTrack> CreateVideoTrack(VideoStreamTrack* aStreamTrack);
// Called when MediaStreamGraph has finished an iteration where tracks were
// created.
void TracksCreated();
void CheckTracksAvailable();
class StreamListener;
@ -299,6 +303,9 @@ protected:
nsTArray<nsAutoPtr<OnTracksAvailableCallback> > mRunOnTracksAvailable;
// Set to true after MediaStreamGraph has created tracks for mStream.
bool mTracksCreated;
nsString mID;
// Keep these alive until the stream finishes

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

@ -190,11 +190,11 @@ MediaStreamGraphImpl::ExtractPendingInput(SourceMediaStream* aStream,
}
}
finished = aStream->mUpdateFinished;
bool notifiedTrackCreated = false;
for (int32_t i = aStream->mUpdateTracks.Length() - 1; i >= 0; --i) {
SourceMediaStream::TrackData* data = &aStream->mUpdateTracks[i];
aStream->ApplyTrackDisabling(data->mID, data->mData);
for (uint32_t j = 0; j < aStream->mListeners.Length(); ++j) {
MediaStreamListener* l = aStream->mListeners[j];
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,
@ -212,6 +212,7 @@ MediaStreamGraphImpl::ExtractPendingInput(SourceMediaStream* aStream,
// data->mData with an empty clone.
data->mData = segment->CreateEmptyClone();
data->mCommands &= ~SourceMediaStream::TRACK_CREATE;
notifiedTrackCreated = true;
} else if (data->mData->GetDuration() > 0) {
MediaSegment* dest = aStream->mBuffer.FindTrack(data->mID)->GetSegment();
STREAM_LOG(PR_LOG_DEBUG+1, ("SourceMediaStream %p track %d, advancing end from %lld to %lld",
@ -226,6 +227,11 @@ MediaStreamGraphImpl::ExtractPendingInput(SourceMediaStream* aStream,
aStream->mUpdateTracks.RemoveElementAt(i);
}
}
if (notifiedTrackCreated) {
for (MediaStreamListener* l : aStream->mListeners) {
l->NotifyFinishedTrackCreation(this);
}
}
if (!aStream->mFinished) {
aStream->mBuffer.AdvanceKnownTracksTime(aStream->mUpdateKnownTracksTime);
}
@ -1938,6 +1944,9 @@ MediaStream::EnsureTrack(TrackID aTrackId)
l->NotifyQueuedTrackChanges(Graph(), aTrackId, 0,
MediaStreamListener::TRACK_EVENT_CREATED,
*segment);
// TODO If we ever need to ensure several tracks at once, we will have to
// change this.
l->NotifyFinishedTrackCreation(Graph());
}
track = &mBuffer.AddTrack(aTrackId, 0, segment.forget());
}

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

@ -177,6 +177,13 @@ public:
StreamTime aTrackOffset,
uint32_t aTrackEvents,
const MediaSegment& aQueuedMedia) {}
/**
* Notify that all new tracks this iteration have been created.
* This is to ensure that tracks added atomically to MediaStreamGraph
* are also notified of atomically to MediaStreamListeners.
*/
virtual void NotifyFinishedTrackCreation(MediaStreamGraph* aGraph) {}
};
/**

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

@ -94,6 +94,7 @@ TrackUnionStream::TrackUnionStream(DOMMediaStream* aWrapper) :
if (!stream->HasCurrentData()) {
allHaveCurrentData = false;
}
bool trackAdded = false;
for (StreamBuffer::TrackIter tracks(stream->GetStreamBuffer());
!tracks.IsEnded(); tracks.Next()) {
bool found = false;
@ -115,12 +116,18 @@ TrackUnionStream::TrackUnionStream(DOMMediaStream* aWrapper) :
}
if (!found && (!mFilterCallback || mFilterCallback(tracks.get()))) {
bool trackFinished = false;
trackAdded = true;
uint32_t mapIndex = AddTrack(mInputs[i], tracks.get(), aFrom);
CopyTrackData(tracks.get(), mapIndex, aFrom, aTo, &trackFinished);
mappedTracksFinished.AppendElement(trackFinished);
mappedTracksWithMatchingInputTracks.AppendElement(true);
}
}
if (trackAdded) {
for (MediaStreamListener* l : mListeners) {
l->NotifyFinishedTrackCreation(Graph());
}
}
}
for (int32_t i = mTrackMap.Length() - 1; i >= 0; --i) {
if (mappedTracksFinished[i]) {