зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1081819 - Let the output stream itself process input data from MediaStreamAudioDestinationNode::mStream. r=roc
This commit is contained in:
Родитель
b1a684cc86
Коммит
307e15ba05
|
@ -50,8 +50,7 @@ PRLogModuleInfo* gTrackUnionStreamLog;
|
|||
#endif
|
||||
|
||||
TrackUnionStream::TrackUnionStream(DOMMediaStream* aWrapper) :
|
||||
ProcessedMediaStream(aWrapper),
|
||||
mFilterCallback(nullptr)
|
||||
ProcessedMediaStream(aWrapper)
|
||||
{
|
||||
#ifdef PR_LOGGING
|
||||
if (!gTrackUnionStreamLog) {
|
||||
|
@ -114,7 +113,7 @@ TrackUnionStream::TrackUnionStream(DOMMediaStream* aWrapper) :
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (!found && (!mFilterCallback || mFilterCallback(tracks.get()))) {
|
||||
if (!found) {
|
||||
bool trackFinished = false;
|
||||
trackAdded = true;
|
||||
uint32_t mapIndex = AddTrack(mInputs[i], tracks.get(), aFrom);
|
||||
|
@ -153,14 +152,6 @@ TrackUnionStream::TrackUnionStream(DOMMediaStream* aWrapper) :
|
|||
}
|
||||
}
|
||||
|
||||
// Consumers may specify a filtering callback to apply to every input track.
|
||||
// Returns true to allow the track to act as an input; false to reject it entirely.
|
||||
|
||||
void TrackUnionStream::SetTrackIDFilter(TrackIDFilterCallback aCallback)
|
||||
{
|
||||
mFilterCallback = aCallback;
|
||||
}
|
||||
|
||||
// Forward SetTrackEnabled(output_track_id, enabled) to the Source MediaStream,
|
||||
// translating the output track ID into the correct ID in the source.
|
||||
void TrackUnionStream::ForwardTrackEnabled(TrackID aOutputID, bool aEnabled)
|
||||
|
|
|
@ -21,19 +21,11 @@ public:
|
|||
virtual void RemoveInput(MediaInputPort* aPort) MOZ_OVERRIDE;
|
||||
virtual void ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) MOZ_OVERRIDE;
|
||||
|
||||
// Consumers may specify a filtering callback to apply to every input track.
|
||||
// Returns true to allow the track to act as an input; false to reject it entirely.
|
||||
typedef bool (*TrackIDFilterCallback)(StreamBuffer::Track*);
|
||||
|
||||
void SetTrackIDFilter(TrackIDFilterCallback aCallback);
|
||||
|
||||
// Forward SetTrackEnabled(output_track_id, enabled) to the Source MediaStream,
|
||||
// translating the output track ID into the correct ID in the source.
|
||||
virtual void ForwardTrackEnabled(TrackID aOutputID, bool aEnabled) MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
TrackIDFilterCallback mFilterCallback;
|
||||
|
||||
// Only non-ended tracks are allowed to persist in this map.
|
||||
struct TrackMapEntry {
|
||||
// mEndOfConsumedInputTicks is the end of the input ticks that we've consumed.
|
||||
|
|
|
@ -23,60 +23,21 @@ NS_INTERFACE_MAP_END_INHERITING(AudioNode)
|
|||
NS_IMPL_ADDREF_INHERITED(MediaStreamAudioDestinationNode, AudioNode)
|
||||
NS_IMPL_RELEASE_INHERITED(MediaStreamAudioDestinationNode, AudioNode)
|
||||
|
||||
static const int MEDIA_STREAM_DEST_TRACK_ID = 2;
|
||||
static_assert(MEDIA_STREAM_DEST_TRACK_ID != AudioNodeStream::AUDIO_TRACK,
|
||||
"MediaStreamAudioDestinationNode::MEDIA_STREAM_DEST_TRACK_ID must be a different value than AudioNodeStream::AUDIO_TRACK");
|
||||
|
||||
class MediaStreamDestinationEngine : public AudioNodeEngine {
|
||||
public:
|
||||
MediaStreamDestinationEngine(AudioNode* aNode, ProcessedMediaStream* aOutputStream)
|
||||
: AudioNodeEngine(aNode)
|
||||
, mOutputStream(aOutputStream)
|
||||
{
|
||||
MOZ_ASSERT(mOutputStream);
|
||||
}
|
||||
|
||||
virtual void ProcessBlock(AudioNodeStream* aStream,
|
||||
const AudioChunk& aInput,
|
||||
AudioChunk* aOutput,
|
||||
bool* aFinished) MOZ_OVERRIDE
|
||||
{
|
||||
*aOutput = aInput;
|
||||
StreamBuffer::Track* track = mOutputStream->EnsureTrack(MEDIA_STREAM_DEST_TRACK_ID);
|
||||
AudioSegment* segment = track->Get<AudioSegment>();
|
||||
segment->AppendAndConsumeChunk(aOutput);
|
||||
}
|
||||
|
||||
virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
|
||||
{
|
||||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
private:
|
||||
ProcessedMediaStream* mOutputStream;
|
||||
};
|
||||
|
||||
// This callback is used to ensure that only the audio data for this track is audible
|
||||
static bool FilterAudioNodeStreamTrack(StreamBuffer::Track* aTrack)
|
||||
{
|
||||
return aTrack->GetID() == MEDIA_STREAM_DEST_TRACK_ID;
|
||||
}
|
||||
|
||||
MediaStreamAudioDestinationNode::MediaStreamAudioDestinationNode(AudioContext* aContext)
|
||||
: AudioNode(aContext,
|
||||
2,
|
||||
ChannelCountMode::Explicit,
|
||||
ChannelInterpretation::Speakers)
|
||||
, mDOMStream(DOMAudioNodeMediaStream::CreateTrackUnionStream(GetOwner(),
|
||||
this))
|
||||
, mDOMStream(DOMAudioNodeMediaStream::CreateTrackUnionStream(GetOwner(), this))
|
||||
{
|
||||
TrackUnionStream* tus = static_cast<TrackUnionStream*>(mDOMStream->GetStream());
|
||||
MOZ_ASSERT(tus == mDOMStream->GetStream()->AsProcessedStream());
|
||||
tus->SetTrackIDFilter(FilterAudioNodeStreamTrack);
|
||||
// Ensure an audio track with the correct ID is exposed to JS
|
||||
mDOMStream->CreateDOMTrack(AudioNodeStream::AUDIO_TRACK, MediaSegment::AUDIO);
|
||||
|
||||
MediaStreamDestinationEngine* engine = new MediaStreamDestinationEngine(this, tus);
|
||||
mStream = aContext->Graph()->CreateAudioNodeStream(engine, MediaStreamGraph::INTERNAL_STREAM);
|
||||
mPort = tus->AllocateInputPort(mStream, 0);
|
||||
ProcessedMediaStream* outputStream = mDOMStream->GetStream()->AsProcessedStream();
|
||||
MOZ_ASSERT(!!outputStream);
|
||||
AudioNodeEngine* engine = new AudioNodeEngine(this);
|
||||
mStream = aContext->Graph()->CreateAudioNodeStream(engine, MediaStreamGraph::EXTERNAL_STREAM);
|
||||
mPort = outputStream->AllocateInputPort(mStream);
|
||||
|
||||
nsIDocument* doc = aContext->GetParentObject()->GetExtantDoc();
|
||||
if (doc) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче