Propagate MediaStreamSource state to video tracks the same way as audio.

Also removes unused track states kLive and kFailed.
Since this also required a Video source to exist in all unit tests that create a track, a FakeVideoTrackSource is added and used in tests.

BUG=webrtc:5426

Review URL: https://codereview.webrtc.org/1790633002

Cr-Commit-Position: refs/heads/master@{#12098}
This commit is contained in:
perkj
2016-03-23 00:33:56 -07:00
committed by Commit bot
parent 8549ed7638
commit c8f952deaa
13 changed files with 43 additions and 75 deletions

View File

@ -111,28 +111,20 @@
+ (webrtc::MediaStreamTrackInterface::TrackState) + (webrtc::MediaStreamTrackInterface::TrackState)
convertTrackStateToNative:(RTCTrackState)state { convertTrackStateToNative:(RTCTrackState)state {
switch (state) { switch (state) {
case RTCTrackStateInitializing:
return webrtc::MediaStreamTrackInterface::kInitializing;
case RTCTrackStateLive: case RTCTrackStateLive:
return webrtc::MediaStreamTrackInterface::kLive; return webrtc::MediaStreamTrackInterface::kLive;
case RTCTrackStateEnded: case RTCTrackStateEnded:
return webrtc::MediaStreamTrackInterface::kEnded; return webrtc::MediaStreamTrackInterface::kEnded;
case RTCTrackStateFailed:
return webrtc::MediaStreamTrackInterface::kFailed;
} }
} }
+ (RTCTrackState)convertTrackStateToObjC: + (RTCTrackState)convertTrackStateToObjC:
(webrtc::MediaStreamTrackInterface::TrackState)nativeState { (webrtc::MediaStreamTrackInterface::TrackState)nativeState {
switch (nativeState) { switch (nativeState) {
case webrtc::MediaStreamTrackInterface::kInitializing:
return RTCTrackStateInitializing;
case webrtc::MediaStreamTrackInterface::kLive: case webrtc::MediaStreamTrackInterface::kLive:
return RTCTrackStateLive; return RTCTrackStateLive;
case webrtc::MediaStreamTrackInterface::kEnded: case webrtc::MediaStreamTrackInterface::kEnded:
return RTCTrackStateEnded; return RTCTrackStateEnded;
case webrtc::MediaStreamTrackInterface::kFailed:
return RTCTrackStateFailed;
} }
} }

View File

@ -72,8 +72,6 @@ typedef enum {
// RTCTrackState corresponds to the states in webrtc::TrackState. // RTCTrackState corresponds to the states in webrtc::TrackState.
typedef enum { typedef enum {
RTCTrackStateInitializing,
RTCTrackStateLive, RTCTrackStateLive,
RTCTrackStateEnded, RTCTrackStateEnded,
RTCTrackStateFailed,
} RTCTrackState; } RTCTrackState;

View File

@ -65,27 +65,11 @@ void AudioTrack::RemoveSink(AudioTrackSinkInterface* sink) {
void AudioTrack::OnChanged() { void AudioTrack::OnChanged() {
RTC_DCHECK(thread_checker_.CalledOnValidThread()); RTC_DCHECK(thread_checker_.CalledOnValidThread());
if (state() == kFailed) if (audio_source_->state() == MediaSourceInterface::kEnded) {
return; // We can't recover from this state (do we ever set it?). set_state(kEnded);
} else {
TrackState new_state = kInitializing; set_state(kLive);
// |audio_source_| must be non-null if we ever get here.
switch (audio_source_->state()) {
case MediaSourceInterface::kLive:
case MediaSourceInterface::kMuted:
new_state = kLive;
break;
case MediaSourceInterface::kEnded:
new_state = kEnded;
break;
case MediaSourceInterface::kInitializing:
default:
// use kInitializing.
break;
} }
set_state(new_state);
} }
} // namespace webrtc } // namespace webrtc

View File

@ -13,9 +13,7 @@ package org.webrtc;
/** Java wrapper for a C++ MediaStreamTrackInterface. */ /** Java wrapper for a C++ MediaStreamTrackInterface. */
public class MediaStreamTrack { public class MediaStreamTrack {
/** Tracks MediaStreamTrackInterface.TrackState */ /** Tracks MediaStreamTrackInterface.TrackState */
public enum State { public enum State { LIVE, ENDED }
INITIALIZING, LIVE, ENDED, FAILED
}
final long nativeTrack; final long nativeTrack;

View File

@ -60,12 +60,12 @@ class MediaStreamTest: public testing::Test {
video_track_ = video_track_ =
VideoTrack::Create(kVideoTrackId, FakeVideoTrackSource::Create()); VideoTrack::Create(kVideoTrackId, FakeVideoTrackSource::Create());
ASSERT_TRUE(video_track_.get() != NULL); ASSERT_TRUE(video_track_.get() != NULL);
EXPECT_EQ(MediaStreamTrackInterface::kInitializing, video_track_->state()); EXPECT_EQ(MediaStreamTrackInterface::kLive, video_track_->state());
audio_track_ = AudioTrack::Create(kAudioTrackId, NULL); audio_track_ = AudioTrack::Create(kAudioTrackId, NULL);
ASSERT_TRUE(audio_track_.get() != NULL); ASSERT_TRUE(audio_track_.get() != NULL);
EXPECT_EQ(MediaStreamTrackInterface::kInitializing, audio_track_->state()); EXPECT_EQ(MediaStreamTrackInterface::kLive, audio_track_->state());
EXPECT_TRUE(stream_->AddTrack(video_track_)); EXPECT_TRUE(stream_->AddTrack(video_track_));
EXPECT_FALSE(stream_->AddTrack(video_track_)); EXPECT_FALSE(stream_->AddTrack(video_track_));
@ -83,8 +83,8 @@ class MediaStreamTest: public testing::Test {
EXPECT_CALL(observer, OnChanged()) EXPECT_CALL(observer, OnChanged())
.Times(Exactly(1)); .Times(Exactly(1));
track->set_state(MediaStreamTrackInterface::kLive); track->set_state(MediaStreamTrackInterface::kEnded);
EXPECT_EQ(MediaStreamTrackInterface::kLive, track->state()); EXPECT_EQ(MediaStreamTrackInterface::kEnded, track->state());
} }
scoped_refptr<MediaStreamInterface> stream_; scoped_refptr<MediaStreamInterface> stream_;

View File

@ -80,10 +80,8 @@ class MediaStreamTrackInterface : public rtc::RefCountInterface,
public NotifierInterface { public NotifierInterface {
public: public:
enum TrackState { enum TrackState {
kInitializing, // Track is beeing negotiated. kLive,
kLive = 1, // Track alive kEnded,
kEnded = 2, // Track have ended
kFailed = 3, // Track negotiation failed.
}; };
static const char kAudioKind[]; static const char kAudioKind[];

View File

@ -48,10 +48,7 @@ class MediaStreamTrack : public Notifier<T> {
protected: protected:
explicit MediaStreamTrack(const std::string& id) explicit MediaStreamTrack(const std::string& id)
: enabled_(true), : enabled_(true), id_(id), state_(MediaStreamTrackInterface::kLive) {}
id_(id),
state_(MediaStreamTrackInterface::kInitializing) {
}
private: private:
bool enabled_; bool enabled_;

View File

@ -11,14 +11,11 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
/** /**
* Represents the state of the track. This exposes the same states in C++, * Represents the state of the track. This exposes the same states in C++.
* which include two more states than are in the W3C spec.
*/ */
typedef NS_ENUM(NSInteger, RTCMediaStreamTrackState) { typedef NS_ENUM(NSInteger, RTCMediaStreamTrackState) {
RTCMediaStreamTrackStateInitializing,
RTCMediaStreamTrackStateLive, RTCMediaStreamTrackStateLive,
RTCMediaStreamTrackStateEnded, RTCMediaStreamTrackStateEnded
RTCMediaStreamTrackStateFailed,
}; };
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN

View File

@ -67,41 +67,29 @@
+ (webrtc::MediaStreamTrackInterface::TrackState)nativeTrackStateForState: + (webrtc::MediaStreamTrackInterface::TrackState)nativeTrackStateForState:
(RTCMediaStreamTrackState)state { (RTCMediaStreamTrackState)state {
switch (state) { switch (state) {
case RTCMediaStreamTrackStateInitializing:
return webrtc::MediaStreamTrackInterface::kInitializing;
case RTCMediaStreamTrackStateLive: case RTCMediaStreamTrackStateLive:
return webrtc::MediaStreamTrackInterface::kLive; return webrtc::MediaStreamTrackInterface::kLive;
case RTCMediaStreamTrackStateEnded: case RTCMediaStreamTrackStateEnded:
return webrtc::MediaStreamTrackInterface::kEnded; return webrtc::MediaStreamTrackInterface::kEnded;
case RTCMediaStreamTrackStateFailed:
return webrtc::MediaStreamTrackInterface::kFailed;
} }
} }
+ (RTCMediaStreamTrackState)trackStateForNativeState: + (RTCMediaStreamTrackState)trackStateForNativeState:
(webrtc::MediaStreamTrackInterface::TrackState)nativeState { (webrtc::MediaStreamTrackInterface::TrackState)nativeState {
switch (nativeState) { switch (nativeState) {
case webrtc::MediaStreamTrackInterface::kInitializing:
return RTCMediaStreamTrackStateInitializing;
case webrtc::MediaStreamTrackInterface::kLive: case webrtc::MediaStreamTrackInterface::kLive:
return RTCMediaStreamTrackStateLive; return RTCMediaStreamTrackStateLive;
case webrtc::MediaStreamTrackInterface::kEnded: case webrtc::MediaStreamTrackInterface::kEnded:
return RTCMediaStreamTrackStateEnded; return RTCMediaStreamTrackStateEnded;
case webrtc::MediaStreamTrackInterface::kFailed:
return RTCMediaStreamTrackStateFailed;
} }
} }
+ (NSString *)stringForState:(RTCMediaStreamTrackState)state { + (NSString *)stringForState:(RTCMediaStreamTrackState)state {
switch (state) { switch (state) {
case RTCMediaStreamTrackStateInitializing:
return @"Initializing";
case RTCMediaStreamTrackStateLive: case RTCMediaStreamTrackStateLive:
return @"Live"; return @"Live";
case RTCMediaStreamTrackStateEnded: case RTCMediaStreamTrackStateEnded:
return @"Ended"; return @"Ended";
case RTCMediaStreamTrackStateFailed:
return @"Failed";
} }
} }

View File

@ -81,10 +81,6 @@ VideoRtpReceiver::VideoRtpReceiver(MediaStreamInterface* stream,
rtc::Thread::Current(), rtc::Thread::Current(),
VideoTrack::Create(track_id, source_.get()))) { VideoTrack::Create(track_id, source_.get()))) {
source_->SetState(MediaSourceInterface::kLive); source_->SetState(MediaSourceInterface::kLive);
// TODO(perkj): It should be enough to set the source state. All tracks
// belonging to the same source should get its state from the source.
// I.e. if a track has been cloned from a remote source.
track_->set_state(webrtc::MediaStreamTrackInterface::kLive);
provider_->SetVideoPlayout(ssrc_, true, &broadcaster_); provider_->SetVideoPlayout(ssrc_, true, &broadcaster_);
stream->AddTrack(track_); stream->AddTrack(track_);
} }
@ -102,9 +98,6 @@ void VideoRtpReceiver::Stop() {
} }
source_->SetState(MediaSourceInterface::kEnded); source_->SetState(MediaSourceInterface::kEnded);
source_->OnSourceDestroyed(); source_->OnSourceDestroyed();
// TODO(perkj): It should be enough to set the source state. All tracks
// belonging to the same source should get its state from the source.
track_->set_state(MediaStreamTrackInterface::kEnded);
provider_->SetVideoPlayout(ssrc_, false, nullptr); provider_->SetVideoPlayout(ssrc_, false, nullptr);
provider_ = nullptr; provider_ = nullptr;
} }

View File

@ -20,9 +20,11 @@ VideoTrack::VideoTrack(const std::string& label,
VideoTrackSourceInterface* video_source) VideoTrackSourceInterface* video_source)
: MediaStreamTrack<VideoTrackInterface>(label), : MediaStreamTrack<VideoTrackInterface>(label),
video_source_(video_source) { video_source_(video_source) {
video_source_->RegisterObserver(this);
} }
VideoTrack::~VideoTrack() { VideoTrack::~VideoTrack() {
video_source_->UnregisterObserver(this);
} }
std::string VideoTrack::kind() const { std::string VideoTrack::kind() const {
@ -56,6 +58,15 @@ bool VideoTrack::set_enabled(bool enable) {
return MediaStreamTrack<VideoTrackInterface>::set_enabled(enable); return MediaStreamTrack<VideoTrackInterface>::set_enabled(enable);
} }
void VideoTrack::OnChanged() {
RTC_DCHECK(thread_checker_.CalledOnValidThread());
if (video_source_->state() == MediaSourceInterface::kEnded) {
set_state(kEnded);
} else {
set_state(kLive);
}
}
rtc::scoped_refptr<VideoTrack> VideoTrack::Create( rtc::scoped_refptr<VideoTrack> VideoTrack::Create(
const std::string& id, const std::string& id,
VideoTrackSourceInterface* source) { VideoTrackSourceInterface* source) {

View File

@ -22,7 +22,8 @@
namespace webrtc { namespace webrtc {
class VideoTrack : public MediaStreamTrack<VideoTrackInterface>, class VideoTrack : public MediaStreamTrack<VideoTrackInterface>,
public rtc::VideoSourceBase { public rtc::VideoSourceBase,
public ObserverInterface {
public: public:
static rtc::scoped_refptr<VideoTrack> Create( static rtc::scoped_refptr<VideoTrack> Create(
const std::string& label, const std::string& label,
@ -43,6 +44,9 @@ class VideoTrack : public MediaStreamTrack<VideoTrackInterface>,
~VideoTrack(); ~VideoTrack();
private: private:
// Implements ObserverInterface. Observes |video_source_| state.
void OnChanged() override;
rtc::ThreadChecker thread_checker_; rtc::ThreadChecker thread_checker_;
rtc::scoped_refptr<VideoTrackSourceInterface> video_source_; rtc::scoped_refptr<VideoTrackSourceInterface> video_source_;
}; };

View File

@ -21,19 +21,19 @@
using webrtc::FakeVideoTrackRenderer; using webrtc::FakeVideoTrackRenderer;
using webrtc::FakeVideoTrackRendererOld; using webrtc::FakeVideoTrackRendererOld;
using webrtc::MediaSourceInterface;
using webrtc::MediaStreamTrackInterface;
using webrtc::VideoTrackSource; using webrtc::VideoTrackSource;
using webrtc::VideoTrack; using webrtc::VideoTrack;
using webrtc::VideoTrackInterface; using webrtc::VideoTrackInterface;
class VideoTrackTest : public testing::Test { class VideoTrackTest : public testing::Test {
public: public:
VideoTrackTest() { VideoTrackTest() {
static const char kVideoTrackId[] = "track_id"; static const char kVideoTrackId[] = "track_id";
video_track_ = VideoTrack::Create( video_track_source_ = new rtc::RefCountedObject<VideoTrackSource>(
kVideoTrackId, &capturer_, rtc::Thread::Current(), true /* remote */);
new rtc::RefCountedObject<VideoTrackSource>( video_track_ = VideoTrack::Create(kVideoTrackId, video_track_source_);
&capturer_, rtc::Thread::Current(), true /* remote */));
capturer_.Start( capturer_.Start(
cricket::VideoFormat(640, 480, cricket::VideoFormat::FpsToInterval(30), cricket::VideoFormat(640, 480, cricket::VideoFormat::FpsToInterval(30),
cricket::FOURCC_I420)); cricket::FOURCC_I420));
@ -41,9 +41,17 @@ class VideoTrackTest : public testing::Test {
protected: protected:
cricket::FakeVideoCapturer capturer_; cricket::FakeVideoCapturer capturer_;
rtc::scoped_refptr<VideoTrackSource> video_track_source_;
rtc::scoped_refptr<VideoTrackInterface> video_track_; rtc::scoped_refptr<VideoTrackInterface> video_track_;
}; };
// Test changing the source state also changes the track state.
TEST_F(VideoTrackTest, SourceStateChangeTrackState) {
EXPECT_EQ(MediaStreamTrackInterface::kLive, video_track_->state());
video_track_source_->SetState(MediaSourceInterface::kEnded);
EXPECT_EQ(MediaStreamTrackInterface::kEnded, video_track_->state());
}
// Test adding renderers to a video track and render to them by providing // Test adding renderers to a video track and render to them by providing
// frames to the source. // frames to the source.
TEST_F(VideoTrackTest, RenderVideo) { TEST_F(VideoTrackTest, RenderVideo) {