Bug 843214. Make SourceMediaStream::AddTrack/AppendToTrack/HaveEnoughBuffered/DispatchWhenNotEnoughBuffered/EndTrack smoothly handle cases where track does not exist. r=jesup

This commit is contained in:
Robert O'Callahan 2013-02-25 22:25:07 +13:00
Родитель 260d9da13c
Коммит 2a0a9d9363
4 изменённых файлов: 31 добавлений и 12 удалений

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

@ -100,6 +100,10 @@ public:
* Insert aDuration of null data at the end of the segment. * Insert aDuration of null data at the end of the segment.
*/ */
virtual void AppendNullData(TrackTicks aDuration) = 0; virtual void AppendNullData(TrackTicks aDuration) = 0;
/**
* Remove all contents, setting duration to 0.
*/
virtual void Clear() = 0;
protected: protected:
MediaSegment(Type aType) : mDuration(0), mType(aType) MediaSegment(Type aType) : mDuration(0), mType(aType)
@ -186,6 +190,11 @@ public:
} }
mDuration += aDuration; mDuration += aDuration;
} }
virtual void Clear()
{
mDuration = 0;
mChunks.Clear();
}
class ChunkIterator { class ChunkIterator {
public: public:

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

@ -118,6 +118,9 @@ MediaStreamGraphImpl::ExtractPendingInput(SourceMediaStream* aStream,
StreamTime t = StreamTime t =
GraphTimeToStreamTime(aStream, mStateComputedTime) + GraphTimeToStreamTime(aStream, mStateComputedTime) +
(aDesiredUpToTime - mStateComputedTime); (aDesiredUpToTime - mStateComputedTime);
LOG(PR_LOG_DEBUG, ("Calling NotifyPull aStream=%p t=%f current end=%f", aStream,
MediaTimeToSeconds(t),
MediaTimeToSeconds(aStream->mBuffer.GetEnd())));
if (t > aStream->mBuffer.GetEnd()) { if (t > aStream->mBuffer.GetEnd()) {
*aEnsureNextIteration = true; *aEnsureNextIteration = true;
for (uint32_t j = 0; j < aStream->mListeners.Length(); ++j) { for (uint32_t j = 0; j < aStream->mListeners.Length(); ++j) {
@ -1637,22 +1640,25 @@ SourceMediaStream::AddTrack(TrackID aID, TrackRate aRate, TrackTicks aStart,
} }
} }
void bool
SourceMediaStream::AppendToTrack(TrackID aID, MediaSegment* aSegment) SourceMediaStream::AppendToTrack(TrackID aID, MediaSegment* aSegment)
{ {
MutexAutoLock lock(mMutex); MutexAutoLock lock(mMutex);
// ::EndAllTrackAndFinished() can end these before the sources notice // ::EndAllTrackAndFinished() can end these before the sources notice
bool appended = false;
if (!mFinished) { if (!mFinished) {
TrackData *track = FindDataForTrack(aID); TrackData *track = FindDataForTrack(aID);
if (track) { if (track) {
track->mData->AppendFrom(aSegment); track->mData->AppendFrom(aSegment);
appended = true;
} else { } else {
NS_ERROR("Append to non-existent track!"); aSegment->Clear();
} }
} }
if (!mDestroyed) { if (!mDestroyed) {
GraphImpl()->EnsureNextIteration(); GraphImpl()->EnsureNextIteration();
} }
return appended;
} }
bool bool
@ -1663,8 +1669,7 @@ SourceMediaStream::HaveEnoughBuffered(TrackID aID)
if (track) { if (track) {
return track->mHaveEnough; return track->mHaveEnough;
} }
NS_ERROR("No track in HaveEnoughBuffered!"); return false;
return true;
} }
void void
@ -1674,7 +1679,7 @@ SourceMediaStream::DispatchWhenNotEnoughBuffered(TrackID aID,
MutexAutoLock lock(mMutex); MutexAutoLock lock(mMutex);
TrackData* data = FindDataForTrack(aID); TrackData* data = FindDataForTrack(aID);
if (!data) { if (!data) {
NS_ERROR("No track in DispatchWhenNotEnoughBuffered"); aSignalThread->Dispatch(aSignalRunnable, 0);
return; return;
} }
@ -1694,8 +1699,6 @@ SourceMediaStream::EndTrack(TrackID aID)
TrackData *track = FindDataForTrack(aID); TrackData *track = FindDataForTrack(aID);
if (track) { if (track) {
track->mCommands |= TRACK_END; track->mCommands |= TRACK_END;
} else {
NS_ERROR("End of non-existant track");
} }
} }
if (!mDestroyed) { if (!mDestroyed) {

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

@ -567,22 +567,27 @@ public:
/** /**
* Append media data to a track. Ownership of aSegment remains with the caller, * Append media data to a track. Ownership of aSegment remains with the caller,
* but aSegment is emptied. * but aSegment is emptied.
* Returns false if the data was not appended because no such track exists
* or the stream was already finished.
*/ */
void AppendToTrack(TrackID aID, MediaSegment* aSegment); bool AppendToTrack(TrackID aID, MediaSegment* aSegment);
/** /**
* Returns true if the buffer currently has enough data. * Returns true if the buffer currently has enough data.
* Returns false if there isn't enough data or if no such track exists.
*/ */
bool HaveEnoughBuffered(TrackID aID); bool HaveEnoughBuffered(TrackID aID);
/** /**
* Ensures that aSignalRunnable will be dispatched to aSignalThread * Ensures that aSignalRunnable will be dispatched to aSignalThread
* when we don't have enough buffered data in the track (which could be * when we don't have enough buffered data in the track (which could be
* immediately). * immediately). Will dispatch the runnable immediately if the track
* does not exist.
*/ */
void DispatchWhenNotEnoughBuffered(TrackID aID, void DispatchWhenNotEnoughBuffered(TrackID aID,
nsIThread* aSignalThread, nsIRunnable* aSignalRunnable); nsIThread* aSignalThread, nsIRunnable* aSignalRunnable);
/** /**
* Indicate that a track has ended. Do not do any more API calls * Indicate that a track has ended. Do not do any more API calls
* affecting this track. * affecting this track.
* Ignored if the track does not exist.
*/ */
void EndTrack(TrackID aID); void EndTrack(TrackID aID);
/** /**
@ -653,7 +658,6 @@ protected:
return &mUpdateTracks[i]; return &mUpdateTracks[i];
} }
} }
NS_ERROR("Bad track ID!");
return nullptr; return nullptr;
} }

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

@ -124,8 +124,11 @@ MediaEngineWebRTCVideoSource::NotifyPull(MediaStreamGraph* aGraph,
if (delta > 0) { if (delta > 0) {
// NULL images are allowed // NULL images are allowed
segment.AppendFrame(image ? image.forget() : nullptr, delta, gfxIntSize(mWidth, mHeight)); segment.AppendFrame(image ? image.forget() : nullptr, delta, gfxIntSize(mWidth, mHeight));
aSource->AppendToTrack(aID, &(segment)); // This can fail if either a) we haven't added the track yet, or b)
aLastEndTime = target; // we've removed or finished the track.
if (aSource->AppendToTrack(aID, &(segment))) {
aLastEndTime = target;
}
} }
} }