Media: harden TrackID handling.

This commit is contained in:
wolfbeast 2018-06-07 16:04:56 +02:00 committed by Roy Tam
commit 0bdecfc6ea
9 changed files with 183 additions and 37 deletions

View file

@ -13,29 +13,41 @@ OutputStreamData::~OutputStreamData()
{
MOZ_ASSERT(NS_IsMainThread());
// Break the connection to the input stream if necessary.
if (mPort) {
mPort->Destroy();
for (RefPtr<MediaInputPort>& port : mPorts) {
port->Destroy();
}
}
void
OutputStreamData::Init(OutputStreamManager* aOwner, ProcessedMediaStream* aStream)
OutputStreamData::Init(OutputStreamManager* aOwner,
ProcessedMediaStream* aStream,
TrackID aNextAvailableTrackID)
{
mOwner = aOwner;
mStream = aStream;
mNextAvailableTrackID = aNextAvailableTrackID;
}
bool
OutputStreamData::Connect(MediaStream* aStream)
OutputStreamData::Connect(MediaStream* aStream,
TrackID aInputAudioTrackID,
TrackID aInputVideoTrackID)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mPort, "Already connected?");
MOZ_ASSERT(mPorts.IsEmpty(), "Already connected?");
if (mStream->IsDestroyed()) {
return false;
}
mPort = mStream->AllocateInputPort(aStream);
for (TrackID tid : {aInputAudioTrackID, aInputVideoTrackID}) {
if (tid == TRACK_NONE) {
continue;
}
MOZ_ASSERT(IsTrackIDExplicit(tid));
mPorts.AppendElement(mStream->AllocateInputPort(
aStream, tid, mNextAvailableTrackID++));
}
return true;
}
@ -51,11 +63,11 @@ OutputStreamData::Disconnect()
return false;
}
// Disconnect the existing port if necessary.
if (mPort) {
mPort->Destroy();
mPort = nullptr;
// Disconnect any existing port.
for (RefPtr<MediaInputPort>& port : mPorts) {
port->Destroy();
}
mPorts.Clear();
return true;
}
@ -71,8 +83,16 @@ OutputStreamData::Graph() const
return mStream->Graph();
}
TrackID
OutputStreamData::NextAvailableTrackID() const
{
return mNextAvailableTrackID;
}
void
OutputStreamManager::Add(ProcessedMediaStream* aStream, bool aFinishWhenEnded)
OutputStreamManager::Add(ProcessedMediaStream* aStream,
TrackID aNextAvailableTrackID,
bool aFinishWhenEnded)
{
MOZ_ASSERT(NS_IsMainThread());
// All streams must belong to the same graph.
@ -84,12 +104,12 @@ OutputStreamManager::Add(ProcessedMediaStream* aStream, bool aFinishWhenEnded)
}
OutputStreamData* p = mStreams.AppendElement();
p->Init(this, aStream);
p->Init(this, aStream, aNextAvailableTrackID);
// Connect to the input stream if we have one. Otherwise the output stream
// will be connected in Connect().
if (mInputStream) {
p->Connect(mInputStream);
p->Connect(mInputStream, mInputAudioTrackID, mInputVideoTrackID);
}
}
@ -106,12 +126,35 @@ OutputStreamManager::Remove(MediaStream* aStream)
}
void
OutputStreamManager::Connect(MediaStream* aStream)
OutputStreamManager::Clear()
{
MOZ_ASSERT(NS_IsMainThread());
mStreams.Clear();
}
TrackID
OutputStreamManager::NextAvailableTrackIDFor(MediaStream* aOutputStream) const
{
MOZ_ASSERT(NS_IsMainThread());
for (const OutputStreamData& out : mStreams) {
if (out.Equals(aOutputStream)) {
return out.NextAvailableTrackID();
}
}
return TRACK_INVALID;
}
void
OutputStreamManager::Connect(MediaStream* aStream,
TrackID aAudioTrackID,
TrackID aVideoTrackID)
{
MOZ_ASSERT(NS_IsMainThread());
mInputStream = aStream;
mInputAudioTrackID = aAudioTrackID;
mInputVideoTrackID = aVideoTrackID;
for (int32_t i = mStreams.Length() - 1; i >= 0; --i) {
if (!mStreams[i].Connect(aStream)) {
if (!mStreams[i].Connect(aStream, mInputAudioTrackID, mInputVideoTrackID)) {
// Probably the DOMMediaStream was GCed. Clean up.
mStreams.RemoveElementAt(i);
}
@ -123,6 +166,8 @@ OutputStreamManager::Disconnect()
{
MOZ_ASSERT(NS_IsMainThread());
mInputStream = nullptr;
mInputAudioTrackID = TRACK_INVALID;
mInputVideoTrackID = TRACK_INVALID;
for (int32_t i = mStreams.Length() - 1; i >= 0; --i) {
if (!mStreams[i].Disconnect()) {
// Probably the DOMMediaStream was GCed. Clean up.