mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-12-27 20:30:39 +00:00
* M1233650 Part 1 * M1233650 Part 2+3 * M1233650 Part 4
This commit is contained in:
parent
2f6fe15d30
commit
1ec3662359
@ -19,6 +19,7 @@
|
||||
#include "mediasink/AudioSinkWrapper.h"
|
||||
#include "mediasink/VideoSink.h"
|
||||
#include "mediasink/DecodedStream.h"
|
||||
#include "mediasink/OutputStreamManager.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/mozalloc.h"
|
||||
@ -288,7 +289,9 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
|
||||
mSentLoadedMetadataEvent(false),
|
||||
mSentFirstFrameLoadedEvent(false, "MediaDecoderStateMachine::mSentFirstFrameLoadedEvent"),
|
||||
mSentPlaybackEndedEvent(false),
|
||||
mStreamSink(new DecodedStream(mTaskQueue, mAudioQueue, mVideoQueue)),
|
||||
mOutputStreamManager(new OutputStreamManager()),
|
||||
mStreamSink(new DecodedStream(
|
||||
mTaskQueue, mAudioQueue, mVideoQueue, mOutputStreamManager)),
|
||||
mResource(aDecoder->GetResource()),
|
||||
mAudioOffloading(false),
|
||||
mBuffered(mTaskQueue, TimeIntervals(),
|
||||
@ -3141,7 +3144,7 @@ void MediaDecoderStateMachine::AddOutputStream(ProcessedMediaStream* aStream,
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
DECODER_LOG("AddOutputStream aStream=%p!", aStream);
|
||||
mStreamSink->AddOutput(aStream, aFinishWhenEnded);
|
||||
mOutputStreamManager->Add(aStream, aFinishWhenEnded);
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethodWithArg<bool>(
|
||||
this, &MediaDecoderStateMachine::SetAudioCaptured, true);
|
||||
OwnerThread()->Dispatch(r.forget());
|
||||
@ -3151,8 +3154,8 @@ void MediaDecoderStateMachine::RemoveOutputStream(MediaStream* aStream)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
DECODER_LOG("RemoveOutputStream=%p!", aStream);
|
||||
mStreamSink->RemoveOutput(aStream);
|
||||
if (!mStreamSink->HasConsumers()) {
|
||||
mOutputStreamManager->Remove(aStream);
|
||||
if (mOutputStreamManager->IsEmpty()) {
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethodWithArg<bool>(
|
||||
this, &MediaDecoderStateMachine::SetAudioCaptured, false);
|
||||
OwnerThread()->Dispatch(r.forget());
|
||||
|
@ -105,6 +105,7 @@ class MediaSink;
|
||||
|
||||
class AudioSegment;
|
||||
class DecodedStream;
|
||||
class OutputStreamManager;
|
||||
class TaskQueue;
|
||||
|
||||
extern LazyLogModule gMediaDecoderLog;
|
||||
@ -1185,6 +1186,9 @@ private:
|
||||
|
||||
bool mSentPlaybackEndedEvent;
|
||||
|
||||
// Data about MediaStreams that are being fed by the decoder.
|
||||
const RefPtr<OutputStreamManager> mOutputStreamManager;
|
||||
|
||||
// The SourceMediaStream we are using to feed the mOutputStreams. This stream
|
||||
// is never exposed outside the decoder.
|
||||
// Only written on the main thread while holding the monitor. Therefore it
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "MediaData.h"
|
||||
#include "MediaQueue.h"
|
||||
#include "MediaStreamGraph.h"
|
||||
#include "OutputStreamManager.h"
|
||||
#include "SharedBuffer.h"
|
||||
#include "VideoSegment.h"
|
||||
#include "VideoUtils.h"
|
||||
@ -126,7 +127,7 @@ UpdateStreamSuspended(MediaStream* aStream, bool aBlocking)
|
||||
*/
|
||||
class DecodedStreamData {
|
||||
public:
|
||||
DecodedStreamData(OutputStreamManager aOutputStreamManager,
|
||||
DecodedStreamData(OutputStreamManager* aOutputStreamManager,
|
||||
PlaybackInfoInit&& aInit,
|
||||
MozPromiseHolder<GenericPromise>&& aPromise);
|
||||
~DecodedStreamData();
|
||||
@ -160,10 +161,10 @@ public:
|
||||
// StreamTime going forward.
|
||||
bool mEOSVideoCompensation;
|
||||
|
||||
OutputStreamManager mOutputStreamManager;
|
||||
const RefPtr<OutputStreamManager> mOutputStreamManager;
|
||||
};
|
||||
|
||||
DecodedStreamData::DecodedStreamData(OutputStreamManager aOutputStreamManager,
|
||||
DecodedStreamData::DecodedStreamData(OutputStreamManager* aOutputStreamManager,
|
||||
PlaybackInfoInit&& aInit,
|
||||
MozPromiseHolder<GenericPromise>&& aPromise)
|
||||
: mAudioFramesWritten(0)
|
||||
@ -172,7 +173,7 @@ DecodedStreamData::DecodedStreamData(OutputStreamManager aOutputStreamManager,
|
||||
, mHaveSentFinish(false)
|
||||
, mHaveSentFinishAudio(false)
|
||||
, mHaveSentFinishVideo(false)
|
||||
, mStream(aOutputStreamManager.Graph()->CreateSourceStream(nullptr))
|
||||
, mStream(aOutputStreamManager->Graph()->CreateSourceStream(nullptr))
|
||||
// DecodedStreamGraphListener will resolve this promise.
|
||||
, mListener(new DecodedStreamGraphListener(mStream, Move(aPromise)))
|
||||
// mPlaying is initially true because MDSM won't start playback until playing
|
||||
@ -182,7 +183,7 @@ DecodedStreamData::DecodedStreamData(OutputStreamManager aOutputStreamManager,
|
||||
, mOutputStreamManager(aOutputStreamManager)
|
||||
{
|
||||
mStream->AddListener(mListener);
|
||||
mOutputStreamManager.Connect(mStream);
|
||||
mOutputStreamManager->Connect(mStream);
|
||||
|
||||
// Initialize tracks.
|
||||
if (aInit.mInfo.HasAudio()) {
|
||||
@ -197,7 +198,7 @@ DecodedStreamData::DecodedStreamData(OutputStreamManager aOutputStreamManager,
|
||||
|
||||
DecodedStreamData::~DecodedStreamData()
|
||||
{
|
||||
mOutputStreamManager.Disconnect();
|
||||
mOutputStreamManager->Disconnect();
|
||||
mListener->Forget();
|
||||
mStream->Destroy();
|
||||
}
|
||||
@ -223,119 +224,12 @@ DecodedStreamData::SetPlaying(bool aPlaying)
|
||||
}
|
||||
}
|
||||
|
||||
OutputStreamData::~OutputStreamData()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// Break the connection to the input stream if necessary.
|
||||
if (mPort) {
|
||||
mPort->Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OutputStreamData::Init(OutputStreamManager* aOwner, ProcessedMediaStream* aStream)
|
||||
{
|
||||
mOwner = aOwner;
|
||||
mStream = aStream;
|
||||
}
|
||||
|
||||
void
|
||||
OutputStreamData::Connect(MediaStream* aStream)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mPort, "Already connected?");
|
||||
MOZ_ASSERT(!mStream->IsDestroyed(), "Can't connect a destroyed stream.");
|
||||
|
||||
mPort = mStream->AllocateInputPort(aStream);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
MediaStreamGraph*
|
||||
OutputStreamData::Graph() const
|
||||
{
|
||||
return mStream->Graph();
|
||||
}
|
||||
|
||||
void
|
||||
OutputStreamManager::Add(ProcessedMediaStream* aStream, bool aFinishWhenEnded)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// All streams must belong to the same graph.
|
||||
MOZ_ASSERT(!Graph() || Graph() == aStream->Graph());
|
||||
|
||||
// Ensure that aStream finishes the moment mDecodedStream does.
|
||||
if (aFinishWhenEnded) {
|
||||
aStream->SetAutofinish(true);
|
||||
}
|
||||
|
||||
OutputStreamData* p = mStreams.AppendElement();
|
||||
p->Init(this, aStream);
|
||||
|
||||
// Connect to the input stream if we have one. Otherwise the output stream
|
||||
// will be connected in Connect().
|
||||
if (mInputStream) {
|
||||
p->Connect(mInputStream);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OutputStreamManager::Remove(MediaStream* aStream)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
for (int32_t i = mStreams.Length() - 1; i >= 0; --i) {
|
||||
if (mStreams[i].Equals(aStream)) {
|
||||
mStreams.RemoveElementAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OutputStreamManager::Connect(MediaStream* aStream)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mInputStream = aStream;
|
||||
for (auto&& os : mStreams) {
|
||||
os.Connect(aStream);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OutputStreamManager::Disconnect()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mInputStream = nullptr;
|
||||
for (int32_t i = mStreams.Length() - 1; i >= 0; --i) {
|
||||
if (!mStreams[i].Disconnect()) {
|
||||
// Probably the DOMMediaStream was GCed. Clean up.
|
||||
mStreams.RemoveElementAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DecodedStream::DecodedStream(AbstractThread* aOwnerThread,
|
||||
MediaQueue<MediaData>& aAudioQueue,
|
||||
MediaQueue<MediaData>& aVideoQueue)
|
||||
MediaQueue<MediaData>& aVideoQueue,
|
||||
OutputStreamManager* aOutputStreamManager)
|
||||
: mOwnerThread(aOwnerThread)
|
||||
, mOutputStreamManager(aOutputStreamManager)
|
||||
, mShuttingDown(false)
|
||||
, mPlaying(false)
|
||||
, mSameOrigin(false)
|
||||
@ -400,7 +294,7 @@ DecodedStream::Start(int64_t aStartTime, const MediaInfo& aInfo)
|
||||
class R : public nsRunnable {
|
||||
typedef MozPromiseHolder<GenericPromise> Promise;
|
||||
public:
|
||||
R(PlaybackInfoInit&& aInit, Promise&& aPromise, OutputStreamManager aManager)
|
||||
R(PlaybackInfoInit&& aInit, Promise&& aPromise, OutputStreamManager* aManager)
|
||||
: mInit(Move(aInit)), mOutputStreamManager(aManager)
|
||||
{
|
||||
mPromise = Move(aPromise);
|
||||
@ -410,7 +304,7 @@ DecodedStream::Start(int64_t aStartTime, const MediaInfo& aInfo)
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// No need to create a source stream when there are no output streams. This
|
||||
// happens when RemoveOutput() is called immediately after StartPlayback().
|
||||
if (!mOutputStreamManager.Graph()) {
|
||||
if (!mOutputStreamManager->Graph()) {
|
||||
// Resolve the promise to indicate the end of playback.
|
||||
mPromise.Resolve(true, __func__);
|
||||
return NS_OK;
|
||||
@ -426,7 +320,7 @@ DecodedStream::Start(int64_t aStartTime, const MediaInfo& aInfo)
|
||||
private:
|
||||
PlaybackInfoInit mInit;
|
||||
Promise mPromise;
|
||||
OutputStreamManager mOutputStreamManager;
|
||||
RefPtr<OutputStreamManager> mOutputStreamManager;
|
||||
UniquePtr<DecodedStreamData> mData;
|
||||
};
|
||||
|
||||
@ -491,28 +385,6 @@ DecodedStream::DestroyData(UniquePtr<DecodedStreamData> aData)
|
||||
AbstractThread::MainThread()->Dispatch(r.forget());
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
DecodedStream::HasConsumers() const
|
||||
{
|
||||
return !mOutputStreamManager.IsEmpty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
DecodedStream::AddOutput(ProcessedMediaStream* aStream, bool aFinishWhenEnded)
|
||||
{
|
||||
mOutputStreamManager.Add(aStream, aFinishWhenEnded);
|
||||
}
|
||||
|
||||
void
|
||||
DecodedStream::RemoveOutput(MediaStream* aStream)
|
||||
{
|
||||
mOutputStreamManager.Remove(aStream);
|
||||
}
|
||||
|
||||
void
|
||||
DecodedStream::SetPlaying(bool aPlaying)
|
||||
{
|
||||
|
@ -7,7 +7,6 @@
|
||||
#ifndef DecodedStream_h_
|
||||
#define DecodedStream_h_
|
||||
|
||||
#include "nsTArray.h"
|
||||
#include "MediaEventSource.h"
|
||||
#include "MediaInfo.h"
|
||||
#include "MediaSink.h"
|
||||
@ -20,12 +19,9 @@
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class DecodedStream;
|
||||
class DecodedStreamData;
|
||||
class MediaData;
|
||||
class MediaInputPort;
|
||||
class MediaStream;
|
||||
class MediaStreamGraph;
|
||||
class OutputStreamManager;
|
||||
struct PlaybackInfoInit;
|
||||
class ProcessedMediaStream;
|
||||
@ -33,69 +29,14 @@ class TimeStamp;
|
||||
|
||||
template <class T> class MediaQueue;
|
||||
|
||||
class OutputStreamData {
|
||||
public:
|
||||
~OutputStreamData();
|
||||
void Init(OutputStreamManager* 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();
|
||||
// Return true if aStream points to the same object as mStream.
|
||||
// Used by OutputStreamManager to remove an output stream.
|
||||
bool Equals(MediaStream* aStream)
|
||||
{
|
||||
return mStream == aStream;
|
||||
}
|
||||
// Return the graph mStream belongs to.
|
||||
MediaStreamGraph* Graph() const;
|
||||
|
||||
private:
|
||||
OutputStreamManager* mOwner;
|
||||
RefPtr<ProcessedMediaStream> mStream;
|
||||
// mPort connects our mStream to an input stream.
|
||||
RefPtr<MediaInputPort> mPort;
|
||||
};
|
||||
|
||||
class OutputStreamManager {
|
||||
public:
|
||||
// Add the output stream to the collection.
|
||||
void Add(ProcessedMediaStream* aStream, bool aFinishWhenEnded);
|
||||
// Remove the output stream from the collection.
|
||||
void Remove(MediaStream* aStream);
|
||||
// Return true if the collection empty.
|
||||
bool IsEmpty() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return mStreams.IsEmpty();
|
||||
}
|
||||
// Connect all output streams in the collection to the input stream.
|
||||
void Connect(MediaStream* aStream);
|
||||
// Disconnect all output streams from the input stream.
|
||||
void Disconnect();
|
||||
// Return the graph these streams belong to or null if empty.
|
||||
MediaStreamGraph* Graph() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return !IsEmpty() ? mStreams[0].Graph() : nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
// Keep the input stream so we can connect the output streams that
|
||||
// are added after Connect().
|
||||
RefPtr<MediaStream> mInputStream;
|
||||
nsTArray<OutputStreamData> mStreams;
|
||||
};
|
||||
|
||||
class DecodedStream : public media::MediaSink {
|
||||
using media::MediaSink::PlaybackParams;
|
||||
|
||||
public:
|
||||
DecodedStream(AbstractThread* aOwnerThread,
|
||||
MediaQueue<MediaData>& aAudioQueue,
|
||||
MediaQueue<MediaData>& aVideoQueue);
|
||||
MediaQueue<MediaData>& aVideoQueue,
|
||||
OutputStreamManager* aOutputStreamManager);
|
||||
|
||||
// MediaSink functions.
|
||||
const PlaybackParams& GetPlaybackParams() const override;
|
||||
@ -122,11 +63,8 @@ public:
|
||||
|
||||
// TODO: fix these functions that don't fit into the interface of MediaSink.
|
||||
void BeginShutdown();
|
||||
void AddOutput(ProcessedMediaStream* aStream, bool aFinishWhenEnded);
|
||||
void RemoveOutput(MediaStream* aStream);
|
||||
void SetSameOrigin(bool aSameOrigin);
|
||||
bool IsFinished() const;
|
||||
bool HasConsumers() const;
|
||||
|
||||
protected:
|
||||
virtual ~DecodedStream();
|
||||
@ -151,7 +89,7 @@ private:
|
||||
* Main thread only members.
|
||||
*/
|
||||
// Data about MediaStreams that are being fed by the decoder.
|
||||
OutputStreamManager mOutputStreamManager;
|
||||
const RefPtr<OutputStreamManager> mOutputStreamManager;
|
||||
// True if MDSM has begun shutdown.
|
||||
bool mShuttingDown;
|
||||
|
||||
|
127
dom/media/mediasink/OutputStreamManager.cpp
Normal file
127
dom/media/mediasink/OutputStreamManager.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MediaStreamGraph.h"
|
||||
#include "OutputStreamManager.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
OutputStreamData::~OutputStreamData()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// Break the connection to the input stream if necessary.
|
||||
if (mPort) {
|
||||
mPort->Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OutputStreamData::Init(OutputStreamManager* aOwner, ProcessedMediaStream* aStream)
|
||||
{
|
||||
mOwner = aOwner;
|
||||
mStream = aStream;
|
||||
}
|
||||
|
||||
void
|
||||
OutputStreamData::Connect(MediaStream* aStream)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mPort, "Already connected?");
|
||||
MOZ_ASSERT(!mStream->IsDestroyed(), "Can't connect a destroyed stream.");
|
||||
|
||||
mPort = mStream->AllocateInputPort(aStream);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
OutputStreamData::Equals(MediaStream* aStream) const
|
||||
{
|
||||
return mStream == aStream;
|
||||
}
|
||||
|
||||
MediaStreamGraph*
|
||||
OutputStreamData::Graph() const
|
||||
{
|
||||
return mStream->Graph();
|
||||
}
|
||||
|
||||
void
|
||||
OutputStreamManager::Add(ProcessedMediaStream* aStream, bool aFinishWhenEnded)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// All streams must belong to the same graph.
|
||||
MOZ_ASSERT(!Graph() || Graph() == aStream->Graph());
|
||||
|
||||
// Ensure that aStream finishes the moment mDecodedStream does.
|
||||
if (aFinishWhenEnded) {
|
||||
aStream->SetAutofinish(true);
|
||||
}
|
||||
|
||||
OutputStreamData* p = mStreams.AppendElement();
|
||||
p->Init(this, aStream);
|
||||
|
||||
// Connect to the input stream if we have one. Otherwise the output stream
|
||||
// will be connected in Connect().
|
||||
if (mInputStream) {
|
||||
p->Connect(mInputStream);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OutputStreamManager::Remove(MediaStream* aStream)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
for (int32_t i = mStreams.Length() - 1; i >= 0; --i) {
|
||||
if (mStreams[i].Equals(aStream)) {
|
||||
mStreams.RemoveElementAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OutputStreamManager::Connect(MediaStream* aStream)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mInputStream = aStream;
|
||||
for (auto&& os : mStreams) {
|
||||
os.Connect(aStream);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OutputStreamManager::Disconnect()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mInputStream = nullptr;
|
||||
for (int32_t i = mStreams.Length() - 1; i >= 0; --i) {
|
||||
if (!mStreams[i].Disconnect()) {
|
||||
// Probably the DOMMediaStream was GCed. Clean up.
|
||||
mStreams.RemoveElementAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
79
dom/media/mediasink/OutputStreamManager.h
Normal file
79
dom/media/mediasink/OutputStreamManager.h
Normal file
@ -0,0 +1,79 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef OutputStreamManager_h
|
||||
#define OutputStreamManager_h
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class MediaInputPort;
|
||||
class MediaStream;
|
||||
class MediaStreamGraph;
|
||||
class OutputStreamManager;
|
||||
class ProcessedMediaStream;
|
||||
|
||||
class OutputStreamData {
|
||||
public:
|
||||
~OutputStreamData();
|
||||
void Init(OutputStreamManager* 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();
|
||||
// Return true if aStream points to the same object as mStream.
|
||||
// Used by OutputStreamManager to remove an output stream.
|
||||
bool Equals(MediaStream* aStream) const;
|
||||
// Return the graph mStream belongs to.
|
||||
MediaStreamGraph* Graph() const;
|
||||
|
||||
private:
|
||||
OutputStreamManager* mOwner;
|
||||
RefPtr<ProcessedMediaStream> mStream;
|
||||
// mPort connects our mStream to an input stream.
|
||||
RefPtr<MediaInputPort> mPort;
|
||||
};
|
||||
|
||||
class OutputStreamManager {
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(OutputStreamManager);
|
||||
|
||||
public:
|
||||
// Add the output stream to the collection.
|
||||
void Add(ProcessedMediaStream* aStream, bool aFinishWhenEnded);
|
||||
// Remove the output stream from the collection.
|
||||
void Remove(MediaStream* aStream);
|
||||
// Return true if the collection empty.
|
||||
bool IsEmpty() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return mStreams.IsEmpty();
|
||||
}
|
||||
// Connect all output streams in the collection to the input stream.
|
||||
void Connect(MediaStream* aStream);
|
||||
// Disconnect all output streams from the input stream.
|
||||
void Disconnect();
|
||||
// Return the graph these streams belong to or null if empty.
|
||||
MediaStreamGraph* Graph() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return !IsEmpty() ? mStreams[0].Graph() : nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
~OutputStreamManager() {}
|
||||
// Keep the input stream so we can connect the output streams that
|
||||
// are added after Connect().
|
||||
RefPtr<MediaStream> mInputStream;
|
||||
nsTArray<OutputStreamData> mStreams;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // OutputStreamManager_h
|
@ -8,6 +8,7 @@ UNIFIED_SOURCES += [
|
||||
'AudioSinkWrapper.cpp',
|
||||
'DecodedAudioDataSink.cpp',
|
||||
'DecodedStream.cpp',
|
||||
'OutputStreamManager.cpp',
|
||||
'VideoSink.cpp',
|
||||
]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user