mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1195187. Part 1 - Move output stream connection/disconnection code to OutputStreamData. r=roc.
This commit is contained in:
parent
aa532c9d31
commit
b8318dfe81
@ -197,8 +197,7 @@ DecodedStreamData::SetPlaying(bool aPlaying)
|
|||||||
class OutputStreamListener : public MediaStreamListener {
|
class OutputStreamListener : public MediaStreamListener {
|
||||||
typedef MediaStreamListener::MediaStreamGraphEvent MediaStreamGraphEvent;
|
typedef MediaStreamListener::MediaStreamGraphEvent MediaStreamGraphEvent;
|
||||||
public:
|
public:
|
||||||
OutputStreamListener(DecodedStream* aDecodedStream, MediaStream* aStream)
|
OutputStreamListener(OutputStreamData* aOwner) : mOwner(aOwner) {}
|
||||||
: mDecodedStream(aDecodedStream), mStream(aStream) {}
|
|
||||||
|
|
||||||
void NotifyEvent(MediaStreamGraph* aGraph, MediaStreamGraphEvent event) override
|
void NotifyEvent(MediaStreamGraph* aGraph, MediaStreamGraphEvent event) override
|
||||||
{
|
{
|
||||||
@ -212,37 +211,88 @@ public:
|
|||||||
void Forget()
|
void Forget()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
mDecodedStream = nullptr;
|
mOwner = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void DoNotifyFinished()
|
void DoNotifyFinished()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
if (mDecodedStream) {
|
if (mOwner) {
|
||||||
// Remove the finished stream so it won't block the decoded stream.
|
// Remove the finished stream so it won't block the decoded stream.
|
||||||
mDecodedStream->Remove(mStream);
|
mOwner->Remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main thread only
|
// Main thread only
|
||||||
DecodedStream* mDecodedStream;
|
OutputStreamData* mOwner;
|
||||||
nsRefPtr<MediaStream> mStream;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
OutputStreamData::~OutputStreamData()
|
OutputStreamData::~OutputStreamData()
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
mListener->Forget();
|
mListener->Forget();
|
||||||
|
// Break the connection to the input stream if necessary.
|
||||||
|
if (mPort) {
|
||||||
|
mPort->Destroy();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
OutputStreamData::Init(DecodedStream* aDecodedStream, ProcessedMediaStream* aStream)
|
OutputStreamData::Init(DecodedStream* aOwner, ProcessedMediaStream* aStream)
|
||||||
{
|
{
|
||||||
|
mOwner = aOwner;
|
||||||
mStream = aStream;
|
mStream = aStream;
|
||||||
mListener = new OutputStreamListener(aDecodedStream, aStream);
|
mListener = new OutputStreamListener(this);
|
||||||
aStream->AddListener(mListener);
|
aStream->AddListener(mListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
OutputStreamData::Connect(MediaStream* aStream)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
MOZ_ASSERT(!mPort, "Already connected?");
|
||||||
|
MOZ_ASSERT(!mStream->IsDestroyed(), "Can't connect a destroyed stream.");
|
||||||
|
|
||||||
|
// The output stream must stay in sync with the input stream, so if
|
||||||
|
// either stream is blocked, we block the other.
|
||||||
|
mPort = mStream->AllocateInputPort(aStream,
|
||||||
|
MediaInputPort::FLAG_BLOCK_INPUT | MediaInputPort::FLAG_BLOCK_OUTPUT);
|
||||||
|
// Unblock the output stream now. The input stream is responsible for
|
||||||
|
// controlling blocking from now on.
|
||||||
|
mStream->ChangeExplicitBlockerCount(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
OutputStreamData::Disconnect()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
// During cycle collection, DOMMediaStream can be destroyed and send
|
||||||
|
// its Destroy message before this decoder is destroyed. So we have to
|
||||||
|
// be careful not to send any messages after the Destroy().
|
||||||
|
if (mStream->IsDestroyed()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disconnect the existing port if necessary.
|
||||||
|
if (mPort) {
|
||||||
|
mPort->Destroy();
|
||||||
|
mPort = nullptr;
|
||||||
|
}
|
||||||
|
// Block the stream again. It will be unlocked when connecting
|
||||||
|
// to the input stream.
|
||||||
|
mStream->ChangeExplicitBlockerCount(1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
OutputStreamData::Remove()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
mOwner->Remove(mStream);
|
||||||
|
}
|
||||||
|
|
||||||
DecodedStream::DecodedStream(MediaQueue<MediaData>& aAudioQueue,
|
DecodedStream::DecodedStream(MediaQueue<MediaData>& aAudioQueue,
|
||||||
MediaQueue<MediaData>& aVideoQueue)
|
MediaQueue<MediaData>& aVideoQueue)
|
||||||
: mMonitor("DecodedStream::mMonitor")
|
: mMonitor("DecodedStream::mMonitor")
|
||||||
@ -289,24 +339,12 @@ DecodedStream::DestroyData()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// All streams are having their SourceMediaStream disconnected, so they
|
|
||||||
// need to be explicitly blocked again.
|
|
||||||
auto& outputStreams = OutputStreams();
|
auto& outputStreams = OutputStreams();
|
||||||
for (int32_t i = outputStreams.Length() - 1; i >= 0; --i) {
|
for (int32_t i = outputStreams.Length() - 1; i >= 0; --i) {
|
||||||
OutputStreamData& os = outputStreams[i];
|
OutputStreamData& os = outputStreams[i];
|
||||||
// Explicitly remove all existing ports.
|
if (!os.Disconnect()) {
|
||||||
// This is not strictly necessary but it's good form.
|
// Probably the DOMMediaStream was GCed. Clean up.
|
||||||
MOZ_ASSERT(os.mPort, "Double-delete of the ports!");
|
|
||||||
os.mPort->Destroy();
|
|
||||||
os.mPort = nullptr;
|
|
||||||
// During cycle collection, nsDOMMediaStream can be destroyed and send
|
|
||||||
// its Destroy message before this decoder is destroyed. So we have to
|
|
||||||
// be careful not to send any messages after the Destroy().
|
|
||||||
if (os.mStream->IsDestroyed()) {
|
|
||||||
// Probably the DOM MediaStream was GCed. Clean up.
|
|
||||||
outputStreams.RemoveElementAt(i);
|
outputStreams.RemoveElementAt(i);
|
||||||
} else {
|
|
||||||
os.mStream->ChangeExplicitBlockerCount(1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,8 +382,7 @@ DecodedStream::RecreateData(MediaStreamGraph* aGraph)
|
|||||||
auto& outputStreams = OutputStreams();
|
auto& outputStreams = OutputStreams();
|
||||||
for (int32_t i = outputStreams.Length() - 1; i >= 0; --i) {
|
for (int32_t i = outputStreams.Length() - 1; i >= 0; --i) {
|
||||||
OutputStreamData& os = outputStreams[i];
|
OutputStreamData& os = outputStreams[i];
|
||||||
MOZ_ASSERT(!os.mStream->IsDestroyed(), "Should've been removed in DestroyData()");
|
os.Connect(mData->mStream);
|
||||||
Connect(&os);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,22 +408,6 @@ DecodedStream::GetReentrantMonitor() const
|
|||||||
return mMonitor;
|
return mMonitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
DecodedStream::Connect(OutputStreamData* aStream)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
GetReentrantMonitor().AssertCurrentThreadIn();
|
|
||||||
NS_ASSERTION(!aStream->mPort, "Already connected?");
|
|
||||||
|
|
||||||
// The output stream must stay in sync with the decoded stream, so if
|
|
||||||
// either stream is blocked, we block the other.
|
|
||||||
aStream->mPort = aStream->mStream->AllocateInputPort(mData->mStream,
|
|
||||||
MediaInputPort::FLAG_BLOCK_INPUT | MediaInputPort::FLAG_BLOCK_OUTPUT);
|
|
||||||
// Unblock the output stream now. While it's connected to DecodedStream,
|
|
||||||
// DecodedStream is responsible for controlling blocking.
|
|
||||||
aStream->mStream->ChangeExplicitBlockerCount(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
DecodedStream::Connect(ProcessedMediaStream* aStream, bool aFinishWhenEnded)
|
DecodedStream::Connect(ProcessedMediaStream* aStream, bool aFinishWhenEnded)
|
||||||
{
|
{
|
||||||
@ -399,7 +420,7 @@ DecodedStream::Connect(ProcessedMediaStream* aStream, bool aFinishWhenEnded)
|
|||||||
|
|
||||||
OutputStreamData* os = OutputStreams().AppendElement();
|
OutputStreamData* os = OutputStreams().AppendElement();
|
||||||
os->Init(this, aStream);
|
os->Init(this, aStream);
|
||||||
Connect(os);
|
os->Connect(mData->mStream);
|
||||||
if (aFinishWhenEnded) {
|
if (aFinishWhenEnded) {
|
||||||
// Ensure that aStream finishes the moment mDecodedStream does.
|
// Ensure that aStream finishes the moment mDecodedStream does.
|
||||||
aStream->SetAutofinish(true);
|
aStream->SetAutofinish(true);
|
||||||
@ -415,12 +436,7 @@ DecodedStream::Remove(MediaStream* aStream)
|
|||||||
auto& streams = OutputStreams();
|
auto& streams = OutputStreams();
|
||||||
for (int32_t i = streams.Length() - 1; i >= 0; --i) {
|
for (int32_t i = streams.Length() - 1; i >= 0; --i) {
|
||||||
auto& os = streams[i];
|
auto& os = streams[i];
|
||||||
MediaStream* p = os.mStream.get();
|
if (os.Equals(aStream)) {
|
||||||
if (p == aStream) {
|
|
||||||
if (os.mPort) {
|
|
||||||
os.mPort->Destroy();
|
|
||||||
os.mPort = nullptr;
|
|
||||||
}
|
|
||||||
streams.RemoveElementAt(i);
|
streams.RemoveElementAt(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -39,9 +39,27 @@ class Image;
|
|||||||
class OutputStreamData {
|
class OutputStreamData {
|
||||||
public:
|
public:
|
||||||
~OutputStreamData();
|
~OutputStreamData();
|
||||||
void Init(DecodedStream* aDecodedStream, ProcessedMediaStream* aStream);
|
void Init(DecodedStream* aOwner, ProcessedMediaStream* aStream);
|
||||||
|
|
||||||
|
// Connect mStream to the input stream.
|
||||||
|
void Connect(MediaStream* aStream);
|
||||||
|
// Disconnect mStream from its input stream.
|
||||||
|
// Return false is mStream is already destroyed, otherwise true.
|
||||||
|
bool Disconnect();
|
||||||
|
// Called by OutputStreamListener to remove self from the output streams
|
||||||
|
// managed by DecodedStream.
|
||||||
|
void Remove();
|
||||||
|
// Return true if aStream points to the same object as mStream.
|
||||||
|
// Used by DecodedStream to remove an output stream.
|
||||||
|
bool Equals(MediaStream* aStream)
|
||||||
|
{
|
||||||
|
return mStream == aStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DecodedStream* mOwner;
|
||||||
nsRefPtr<ProcessedMediaStream> mStream;
|
nsRefPtr<ProcessedMediaStream> mStream;
|
||||||
// mPort connects DecodedStreamData::mStream to our mStream.
|
// mPort connects our mStream to an input stream.
|
||||||
nsRefPtr<MediaInputPort> mPort;
|
nsRefPtr<MediaInputPort> mPort;
|
||||||
nsRefPtr<OutputStreamListener> mListener;
|
nsRefPtr<OutputStreamListener> mListener;
|
||||||
};
|
};
|
||||||
@ -84,7 +102,6 @@ protected:
|
|||||||
private:
|
private:
|
||||||
ReentrantMonitor& GetReentrantMonitor() const;
|
ReentrantMonitor& GetReentrantMonitor() const;
|
||||||
void RecreateData(MediaStreamGraph* aGraph);
|
void RecreateData(MediaStreamGraph* aGraph);
|
||||||
void Connect(OutputStreamData* aStream);
|
|
||||||
nsTArray<OutputStreamData>& OutputStreams();
|
nsTArray<OutputStreamData>& OutputStreams();
|
||||||
void InitTracks();
|
void InitTracks();
|
||||||
void AdvanceTracks();
|
void AdvanceTracks();
|
||||||
|
Loading…
Reference in New Issue
Block a user