Bug 1400363 - Part 0: Expose the SourceMediaStream of MediaStreamTrack, and store tracks instead of the source streams. r=pehrsons

MozReview-Commit-ID: KSYFGHsr0qk

--HG--
extra : rebase_source : 657ea373fb69d1e85b28a5535028a650c33dce9e
This commit is contained in:
Byron Campen [:bwc] 2017-11-30 14:47:13 -06:00
Родитель f88164725a
Коммит 63a499f3be
9 изменённых файлов: 98 добавлений и 126 удалений

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

@ -509,6 +509,14 @@ public:
void SetMediaStreamSizeListener(DirectMediaStreamTrackListener* aListener);
// Returns the original DOMMediaStream's underlying input stream.
MediaStream* GetInputStream();
TrackID GetInputTrackId() const
{
return mInputTrackID;
}
protected:
virtual ~MediaStreamTrack();
@ -519,9 +527,6 @@ protected:
void Destroy();
// Returns the original DOMMediaStream's underlying input stream.
MediaStream* GetInputStream();
// Returns the owning DOMMediaStream's underlying owned stream.
ProcessedMediaStream* GetOwnedStream();

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

@ -20,7 +20,6 @@
#include "LayersLogging.h"
#include "ImageTypes.h"
#include "ImageContainer.h"
#include "DOMMediaStream.h"
#include "MediaStreamTrack.h"
#include "MediaStreamListener.h"
#include "MediaStreamVideoSink.h"
@ -1892,24 +1891,27 @@ class GenericReceiveCallback : public TrackAddedCallback
class GenericReceiveListener : public MediaStreamListener
{
public:
GenericReceiveListener(SourceMediaStream *source, TrackID track_id)
: source_(source),
track_id_(track_id),
explicit GenericReceiveListener(dom::MediaStreamTrack* track)
: track_(track),
played_ticks_(0),
last_log_(0),
principal_handle_(PRINCIPAL_HANDLE_NONE),
listening_(false)
{
MOZ_ASSERT(source);
MOZ_ASSERT(track->GetInputStream()->AsSourceStream());
}
virtual ~GenericReceiveListener() {}
virtual ~GenericReceiveListener()
{
NS_ReleaseOnMainThreadSystemGroup(
"GenericReceiveListener::track_", track_.forget());
}
void AddSelf()
{
if (!listening_) {
listening_ = true;
source_->AddListener(this);
track_->GetInputStream()->AddListener(this);
}
}
@ -1917,7 +1919,7 @@ class GenericReceiveListener : public MediaStreamListener
{
if (listening_) {
listening_ = false;
source_->RemoveListener(this);
track_->GetInputStream()->RemoveListener(this);
}
}
@ -1929,24 +1931,21 @@ class GenericReceiveListener : public MediaStreamListener
class Message : public ControlMessage
{
public:
Message(SourceMediaStream* stream,
TrackID track_id)
: ControlMessage(stream),
source_(stream),
track_id_(track_id)
explicit Message(dom::MediaStreamTrack* track)
: ControlMessage(track->GetInputStream()),
track_id_(track->GetInputTrackId())
{}
void Run() override {
source_->EndTrack(track_id_);
mStream->AsSourceStream()->EndTrack(track_id_);
}
RefPtr<SourceMediaStream> source_;
const TrackID track_id_;
};
source_->GraphImpl()->AppendMessage(MakeUnique<Message>(source_, track_id_));
// This breaks the cycle with source_
source_->RemoveListener(this);
track_->GraphImpl()->AppendMessage(MakeUnique<Message>(track_));
// This breaks the cycle with the SourceMediaStream
track_->GetInputStream()->RemoveListener(this);
}
// Must be called on the main thread
@ -1956,9 +1955,8 @@ class GenericReceiveListener : public MediaStreamListener
{
public:
Message(GenericReceiveListener* listener,
MediaStream* stream,
const PrincipalHandle& principal_handle)
: ControlMessage(stream),
: ControlMessage(nullptr),
listener_(listener),
principal_handle_(principal_handle)
{}
@ -1971,7 +1969,7 @@ class GenericReceiveListener : public MediaStreamListener
PrincipalHandle principal_handle_;
};
source_->GraphImpl()->AppendMessage(MakeUnique<Message>(this, source_, principal_handle));
track_->GraphImpl()->AppendMessage(MakeUnique<Message>(this, principal_handle));
}
// Must be called on the MediaStreamGraph thread
@ -1981,8 +1979,7 @@ class GenericReceiveListener : public MediaStreamListener
}
protected:
RefPtr<SourceMediaStream> source_;
const TrackID track_id_;
RefPtr<dom::MediaStreamTrack> track_;
TrackTicks played_ticks_;
TrackTicks last_log_; // played_ticks_ when we last logged
PrincipalHandle principal_handle_;
@ -2007,9 +2004,9 @@ class MediaPipelineReceiveAudio::PipelineListener
: public GenericReceiveListener
{
public:
PipelineListener(SourceMediaStream * source,
PipelineListener(dom::MediaStreamTrack* track,
const RefPtr<MediaSessionConduit>& conduit)
: GenericReceiveListener(source, kAudioTrack),
: GenericReceiveListener(track),
conduit_(conduit)
{
}
@ -2032,8 +2029,10 @@ public:
// Implement MediaStreamListener
void NotifyPull(MediaStreamGraph* graph, StreamTime desired_time) override
{
MOZ_ASSERT(source_);
if (!source_) {
RefPtr<SourceMediaStream> source =
track_->GetInputStream()->AsSourceStream();
MOZ_ASSERT(source);
if (!source) {
CSFLogError(LOGTAG, "NotifyPull() called from a non-SourceMediaStream");
return;
}
@ -2042,8 +2041,7 @@ public:
uint32_t samples_per_10ms = rate/100;
// This comparison is done in total time to avoid accumulated roundoff errors.
while (source_->TicksToTimeRoundDown(rate,
played_ticks_) < desired_time) {
while (source->TicksToTimeRoundDown(rate, played_ticks_) < desired_time) {
int16_t scratch_buffer[AUDIO_SAMPLE_BUFFER_MAX_BYTES / sizeof(int16_t)];
int samples_length;
@ -2060,7 +2058,7 @@ public:
// Insert silence on conduit/GIPS failure (extremely unlikely)
CSFLogError(LOGTAG, "Audio conduit failed (%d) to return data @ %" PRId64 " (desired %" PRId64 " -> %f)",
err, played_ticks_, desired_time,
source_->StreamTimeToSeconds(desired_time));
source->StreamTimeToSeconds(desired_time));
// if this is not enough we'll loop and provide more
samples_length = samples_per_10ms;
PodArrayZero(scratch_buffer);
@ -2101,13 +2099,14 @@ public:
principal_handle_);
// Handle track not actually added yet or removed/finished
if (source_->AppendToTrack(track_id_, &segment)) {
if (source->AppendToTrack(track_->GetInputTrackId(), &segment)) {
played_ticks_ += frames;
if (MOZ_LOG_TEST(AudioLogModule(), LogLevel::Debug)) {
if (played_ticks_ > last_log_ + rate) { // ~ 1 second
MOZ_LOG(AudioLogModule(), LogLevel::Debug,
("%p: Inserting %zu samples into track %d, total = %" PRIu64,
(void*) this, frames, track_id_, played_ticks_));
(void*) this, frames, track_->GetInputTrackId(),
played_ticks_));
last_log_ = played_ticks_;
}
}
@ -2129,9 +2128,9 @@ MediaPipelineReceiveAudio::MediaPipelineReceiveAudio(
nsCOMPtr<nsIEventTarget> main_thread,
nsCOMPtr<nsIEventTarget> sts_thread,
RefPtr<AudioSessionConduit> conduit,
SourceMediaStream* aStream) :
dom::MediaStreamTrack* aTrack) :
MediaPipelineReceive(pc, main_thread, sts_thread, conduit),
listener_(aStream ? new PipelineListener(aStream, conduit_) : nullptr)
listener_(aTrack ? new PipelineListener(aTrack, conduit_) : nullptr)
{
description_ = pc_ + "| Receive audio";
}
@ -2173,8 +2172,8 @@ MediaPipelineReceiveAudio::Stop()
class MediaPipelineReceiveVideo::PipelineListener
: public GenericReceiveListener {
public:
explicit PipelineListener(SourceMediaStream* source)
: GenericReceiveListener(source, kVideoTrack)
explicit PipelineListener(dom::MediaStreamTrack* track)
: GenericReceiveListener(track)
, image_container_()
, image_()
, mutex_("Video PipelineListener")
@ -2199,7 +2198,8 @@ public:
IntSize size = image ? image->GetSize() : IntSize(width_, height_);
segment.AppendFrame(image.forget(), delta, size, principal_handle_);
// Handle track not actually added yet or removed/finished
if (source_->AppendToTrack(track_id_, &segment)) {
if (track_->GetInputStream()->AsSourceStream()->AppendToTrack(
track_->GetInputTrackId(), &segment)) {
played_ticks_ = desired_time;
} else {
CSFLogError(LOGTAG, "AppendToTrack failed");
@ -2304,10 +2304,10 @@ MediaPipelineReceiveVideo::MediaPipelineReceiveVideo(
nsCOMPtr<nsIEventTarget> main_thread,
nsCOMPtr<nsIEventTarget> sts_thread,
RefPtr<VideoSessionConduit> conduit,
SourceMediaStream* aStream) :
dom::MediaStreamTrack* aTrack) :
MediaPipelineReceive(pc, main_thread, sts_thread, conduit),
renderer_(new PipelineRenderer(this)),
listener_(aStream ? new PipelineListener(aStream) : nullptr)
listener_(aTrack ? new PipelineListener(aTrack) : nullptr)
{
description_ = pc_ + "| Receive video";
conduit->AttachRenderer(renderer_);

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

@ -405,7 +405,7 @@ class MediaPipelineReceiveAudio : public MediaPipelineReceive {
nsCOMPtr<nsIEventTarget> main_thread,
nsCOMPtr<nsIEventTarget> sts_thread,
RefPtr<AudioSessionConduit> conduit,
SourceMediaStream* aStream);
dom::MediaStreamTrack* aTrack);
void DetachMedia() override;
@ -432,7 +432,7 @@ class MediaPipelineReceiveVideo : public MediaPipelineReceive {
nsCOMPtr<nsIEventTarget> main_thread,
nsCOMPtr<nsIEventTarget> sts_thread,
RefPtr<VideoSessionConduit> conduit,
SourceMediaStream* aStream);
dom::MediaStreamTrack* aTrack);
// Called on the main thread.
void DetachMedia() override;

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

@ -413,20 +413,6 @@ PeerConnectionImpl::~PeerConnectionImpl()
// to release off a timer (and XPCOM Shutdown) to avoid churn
}
OwningNonNull<DOMMediaStream>
PeerConnectionImpl::MakeMediaStream()
{
MediaStreamGraph* graph =
MediaStreamGraph::GetInstance(MediaStreamGraph::AUDIO_THREAD_DRIVER, GetWindow());
RefPtr<DOMMediaStream> stream =
DOMMediaStream::CreateSourceStreamAsInput(GetWindow(), graph);
CSFLogDebug(LOGTAG, "Created media stream %p, inner: %p", stream.get(), stream->GetInputStream());
return *stream;
}
/**
* In JS, an RTCConfiguration looks like this:
*
@ -1216,13 +1202,13 @@ PeerConnectionImpl::CreateTransceiverImpl(
aSendTrack->AddPrincipalChangeObserver(this);
}
OwningNonNull<DOMMediaStream> receiveStream =
CreateReceiveStreamWithTrack(aJsepTransceiver->GetMediaType());
OwningNonNull<dom::MediaStreamTrack> receiveTrack =
CreateReceiveTrack(aJsepTransceiver->GetMediaType());
RefPtr<TransceiverImpl> transceiverImpl;
aRv = mMedia->AddTransceiver(aJsepTransceiver,
*receiveStream,
*receiveTrack,
aSendTrack,
&transceiverImpl);
@ -2382,11 +2368,21 @@ static int GetDTMFToneCode(uint16_t c)
return i - DTMF_TONECODES;
}
OwningNonNull<DOMMediaStream>
PeerConnectionImpl::CreateReceiveStreamWithTrack(
SdpMediaSection::MediaType type) {
OwningNonNull<dom::MediaStreamTrack>
PeerConnectionImpl::CreateReceiveTrack(SdpMediaSection::MediaType type)
{
bool audio = (type == SdpMediaSection::MediaType::kAudio);
OwningNonNull<DOMMediaStream> stream = MakeMediaStream();
MediaStreamGraph* graph = MediaStreamGraph::GetInstance(
audio ?
MediaStreamGraph::AUDIO_THREAD_DRIVER :
MediaStreamGraph::SYSTEM_THREAD_DRIVER,
GetWindow());
RefPtr<DOMMediaStream> stream =
DOMMediaStream::CreateSourceStreamAsInput(GetWindow(), graph);
CSFLogDebug(LOGTAG, "Created media stream %p, inner: %p", stream.get(), stream->GetInputStream());
// Set the principal used for creating the tracks. This makes the stream
// data (audio/video samples) accessible to the receiving page. We're
@ -2403,27 +2399,23 @@ PeerConnectionImpl::CreateReceiveStreamWithTrack(
}
RefPtr<MediaStreamTrack> track;
switch (type) {
case SdpMediaSection::MediaType::kAudio:
track = stream->CreateDOMTrack(
kAudioTrack,
MediaSegment::AUDIO,
new RemoteTrackSource(principal,
NS_ConvertASCIItoUTF16("remote audio")));
break;
case SdpMediaSection::MediaType::kVideo:
track = stream->CreateDOMTrack(
kVideoTrack,
MediaSegment::VIDEO,
new RemoteTrackSource(principal,
NS_ConvertASCIItoUTF16("remote video")));
break;
default:
MOZ_ASSERT(false, "Bad media kind; our JS passed some garbage");
if (audio) {
track = stream->CreateDOMTrack(
kAudioTrack,
MediaSegment::AUDIO,
new RemoteTrackSource(principal,
NS_ConvertASCIItoUTF16("remote audio")));
} else {
track = stream->CreateDOMTrack(
kVideoTrack,
MediaSegment::VIDEO,
new RemoteTrackSource(principal,
NS_ConvertASCIItoUTF16("remote video")));
}
stream->AddTrackInternal(track);
return stream;
return OwningNonNull<dom::MediaStreamTrack>(*track);
}
NS_IMETHODIMP

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

@ -68,8 +68,6 @@ class NrIceTurnServer;
class MediaPipeline;
class TransceiverImpl;
class DOMMediaStream;
namespace dom {
class RTCCertificate;
struct RTCConfiguration;
@ -116,7 +114,6 @@ using mozilla::dom::PeerConnectionObserver;
using mozilla::dom::RTCConfiguration;
using mozilla::dom::RTCIceServer;
using mozilla::dom::RTCOfferOptions;
using mozilla::DOMMediaStream;
using mozilla::NrIceCtx;
using mozilla::NrIceMediaStream;
using mozilla::DtlsIdentity;
@ -258,7 +255,6 @@ public:
static already_AddRefed<PeerConnectionImpl>
Constructor(const mozilla::dom::GlobalObject& aGlobal, ErrorResult& rv);
static PeerConnectionImpl* CreatePeerConnection();
OwningNonNull<DOMMediaStream> MakeMediaStream();
nsresult CreateRemoteSourceStreamInfo(RefPtr<RemoteSourceStreamInfo>* aInfo,
const std::string& aId);
@ -410,7 +406,7 @@ public:
dom::MediaStreamTrack* aSendTrack,
ErrorResult& rv);
OwningNonNull<DOMMediaStream> CreateReceiveStreamWithTrack(
OwningNonNull<dom::MediaStreamTrack> CreateReceiveTrack(
SdpMediaSection::MediaType type);
bool CheckNegotiationNeeded(ErrorResult &rv);

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

@ -1131,7 +1131,7 @@ PeerConnectionMedia::ShutdownMediaTransport_s()
nsresult
PeerConnectionMedia::AddTransceiver(
JsepTransceiver* aJsepTransceiver,
DOMMediaStream& aReceiveStream,
dom::MediaStreamTrack& aReceiveTrack,
dom::MediaStreamTrack* aSendTrack,
RefPtr<TransceiverImpl>* aTransceiverImpl)
{
@ -1144,7 +1144,7 @@ PeerConnectionMedia::AddTransceiver(
aJsepTransceiver,
mMainThread.get(),
mSTSThread.get(),
aReceiveStream,
&aReceiveTrack,
aSendTrack,
mCall.get());

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

@ -117,7 +117,7 @@ class PeerConnectionMedia : public sigslot::has_slots<> {
// TODO: Let's move the TransceiverImpl stuff to PeerConnectionImpl.
nsresult AddTransceiver(
JsepTransceiver* aJsepTransceiver,
DOMMediaStream& aReceiveStream,
dom::MediaStreamTrack& aReceiveTrack,
dom::MediaStreamTrack* aSendTrack,
RefPtr<TransceiverImpl>* aTransceiverImpl);

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

@ -37,7 +37,7 @@ TransceiverImpl::TransceiverImpl(
JsepTransceiver* aJsepTransceiver,
nsIEventTarget* aMainThread,
nsIEventTarget* aStsThread,
DOMMediaStream& aReceiveStream,
dom::MediaStreamTrack* aReceiveTrack,
dom::MediaStreamTrack* aSendTrack,
WebRtcCallWrapper* aCallWrapper) :
mPCHandle(aPCHandle),
@ -46,7 +46,7 @@ TransceiverImpl::TransceiverImpl(
mHaveSetupTransport(false),
mMainThread(aMainThread),
mStsThread(aStsThread),
mReceiveStream(&aReceiveStream),
mReceiveTrack(aReceiveTrack),
mSendTrack(aSendTrack),
mCallWrapper(aCallWrapper)
{
@ -95,7 +95,7 @@ TransceiverImpl::InitAudio()
mMainThread.get(),
mStsThread.get(),
static_cast<AudioSessionConduit*>(mConduit.get()),
mReceiveStream->GetInputStream()->AsSourceStream());
mReceiveTrack);
}
void
@ -116,7 +116,7 @@ TransceiverImpl::InitVideo()
mMainThread.get(),
mStsThread.get(),
static_cast<VideoSessionConduit*>(mConduit.get()),
mReceiveStream->GetInputStream()->AsSourceStream());
mReceiveTrack);
}
nsresult
@ -252,7 +252,7 @@ TransceiverImpl::UpdateConduit()
}
if (mJsepTransceiver->mRecvTrack.GetActive()) {
MOZ_ASSERT(mReceiveStream);
MOZ_ASSERT(mReceiveTrack);
mReceivePipeline->Start();
mHaveStartedReceiving = true;
}
@ -275,22 +275,11 @@ TransceiverImpl::UpdatePrincipal(nsIPrincipal* aPrincipal)
return NS_OK;
}
nsTArray<RefPtr<dom::MediaStreamTrack>> receiveTracks;
mReceiveStream->GetTracks(receiveTracks);
if (receiveTracks.Length() != 1) {
MOZ_MTLOG(ML_ERROR, mPCHandle << "[" << mMid << "]: " << __FUNCTION__ <<
" mReceiveStream doesn't have exactly one track "
"(it has " << receiveTracks.Length() << ")");
MOZ_CRASH();
return NS_ERROR_FAILURE;
}
// This blasts away the existing principal.
// We only do this when we become certain that the all tracks are safe to make
// We only do this when we become certain that all tracks are safe to make
// accessible to the script principal.
RemoteTrackSource& source =
static_cast<RemoteTrackSource&>(receiveTracks[0]->GetSource());
source.SetPrincipal(aPrincipal);
static_cast<RemoteTrackSource&>(mReceiveTrack->GetSource()).SetPrincipal(
aPrincipal);
mReceivePipeline->SetPrincipalHandle_m(MakePrincipalHandle(aPrincipal));
return NS_OK;
@ -580,7 +569,7 @@ TransceiverImpl::HasReceiveTrack(const dom::MediaStreamTrack* aRecvTrack) const
return true;
}
return mReceiveStream->HasTrack(*aRecvTrack);
return mReceiveTrack == aRecvTrack;
}
bool
@ -593,13 +582,7 @@ TransceiverImpl::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
already_AddRefed<dom::MediaStreamTrack>
TransceiverImpl::GetReceiveTrack()
{
nsTArray<RefPtr<dom::MediaStreamTrack>> receiveTracks;
mReceiveStream->GetTracks(receiveTracks);
if (receiveTracks.Length() != 1) {
return nullptr;
}
return receiveTracks[0].forget();
return do_AddRef(mReceiveTrack);
}
RefPtr<MediaPipeline>
@ -1075,10 +1058,7 @@ void
TransceiverImpl::StartReceiveStream()
{
MOZ_MTLOG(ML_DEBUG, mPCHandle << "[" << mMid << "]: " << __FUNCTION__);
// TODO: Can this be simplified? There's an awful lot of moving pieces here.
SourceMediaStream* source(mReceiveStream->GetInputStream()->AsSourceStream());
mReceiveStream->SetLogicalStreamStartTime(
mReceiveStream->GetPlaybackStream()->GetCurrentTime());
SourceMediaStream* source(mReceiveTrack->GetInputStream()->AsSourceStream());
nsAutoPtr<MediaSegment> segment;
if (IsVideo()) {

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

@ -9,7 +9,6 @@
#include "nsCOMPtr.h"
#include "nsIEventTarget.h"
#include "nsTArray.h"
#include "DOMMediaStream.h"
#include "mozilla/OwningNonNull.h"
#include "mozilla/dom/MediaStreamTrack.h"
#include "ErrorList.h"
@ -39,7 +38,7 @@ struct RTCRtpSourceEntry;
/**
* This is what ties all the various pieces that make up a transceiver
* together. This includes:
* DOMMediaStream, MediaStreamTrack, SourceMediaStream for rendering and capture
* MediaStreamTrack for rendering and capture
* TransportFlow for RTP transmission/reception
* Audio/VideoConduit for feeding RTP/RTCP into webrtc.org for decoding, and
* feeding audio/video frames into webrtc.org for encoding into RTP/RTCP.
@ -55,7 +54,7 @@ public:
JsepTransceiver* aJsepTransceiver,
nsIEventTarget* aMainThread,
nsIEventTarget* aStsThread,
DOMMediaStream& aReceiveStream,
dom::MediaStreamTrack* aReceiveTrack,
dom::MediaStreamTrack* aSendTrack,
WebRtcCallWrapper* aCallWrapper);
@ -146,7 +145,7 @@ private:
bool mHaveSetupTransport;
nsCOMPtr<nsIEventTarget> mMainThread;
nsCOMPtr<nsIEventTarget> mStsThread;
RefPtr<DOMMediaStream> mReceiveStream;
RefPtr<dom::MediaStreamTrack> mReceiveTrack;
RefPtr<dom::MediaStreamTrack> mSendTrack;
// state for webrtc.org that is shared between all transceivers
RefPtr<WebRtcCallWrapper> mCallWrapper;