Implement RTP extension support in WebRtcVideoEngine2.
BUG=1788 R=pthatcher@webrtc.org Review URL: https://webrtc-codereview.appspot.com/20679004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@6453 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
d054bff3b9
commit
587ef60056
@ -278,6 +278,13 @@ void WebRtcVideoEngine2::Construct(WebRtcVideoChannelFactory* channel_factory,
|
||||
|
||||
video_codecs_ = DefaultVideoCodecs();
|
||||
default_codec_format_ = VideoFormat(kDefaultVideoFormat);
|
||||
|
||||
rtp_header_extensions_.push_back(
|
||||
RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension,
|
||||
kRtpTimestampOffsetHeaderExtensionDefaultId));
|
||||
rtp_header_extensions_.push_back(
|
||||
RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension,
|
||||
kRtpAbsoluteSenderTimeHeaderExtensionDefaultId));
|
||||
}
|
||||
|
||||
WebRtcVideoEngine2::~WebRtcVideoEngine2() {
|
||||
@ -774,6 +781,20 @@ static bool ValidateCodecFormats(const std::vector<VideoCodec>& codecs) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static std::string RtpExtensionsToString(
|
||||
const std::vector<RtpHeaderExtension>& extensions) {
|
||||
std::stringstream out;
|
||||
out << '{';
|
||||
for (size_t i = 0; i < extensions.size(); ++i) {
|
||||
out << "{" << extensions[i].uri << ": " << extensions[i].id << "}";
|
||||
if (i != extensions.size() - 1) {
|
||||
out << ", ";
|
||||
}
|
||||
}
|
||||
out << '}';
|
||||
return out.str();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool WebRtcVideoChannel2::SetRecvCodecs(const std::vector<VideoCodec>& codecs) {
|
||||
@ -967,6 +988,8 @@ bool WebRtcVideoChannel2::AddSendStream(const StreamParams& sp) {
|
||||
config.rtp.rtx.payload_type = codec_settings.rtx_payload_type;
|
||||
}
|
||||
|
||||
config.rtp.extensions = send_rtp_extensions_;
|
||||
|
||||
if (IsNackEnabled(codec_settings.codec)) {
|
||||
config.rtp.nack.rtp_history_ms = kNackHistoryMs;
|
||||
}
|
||||
@ -1047,6 +1070,7 @@ bool WebRtcVideoChannel2::AddRecvStream(const StreamParams& sp) {
|
||||
config.rtp.nack.rtp_history_ms = kNackHistoryMs;
|
||||
}
|
||||
config.rtp.remb = true;
|
||||
config.rtp.extensions = recv_rtp_extensions_;
|
||||
// TODO(pbos): This protection is against setting the same local ssrc as
|
||||
// remote which is not permitted by the lower-level API. RTCP requires a
|
||||
// corresponding sender SSRC. Figure out what to do when we don't have
|
||||
@ -1280,15 +1304,31 @@ bool WebRtcVideoChannel2::MuteStream(uint32 ssrc, bool mute) {
|
||||
|
||||
bool WebRtcVideoChannel2::SetRecvRtpHeaderExtensions(
|
||||
const std::vector<RtpHeaderExtension>& extensions) {
|
||||
// TODO(pbos): Implement.
|
||||
LOG(LS_VERBOSE) << "SetRecvRtpHeaderExtensions()";
|
||||
LOG(LS_INFO) << "SetRecvRtpHeaderExtensions: "
|
||||
<< RtpExtensionsToString(extensions);
|
||||
std::vector<webrtc::RtpExtension> webrtc_extensions;
|
||||
for (size_t i = 0; i < extensions.size(); ++i) {
|
||||
// TODO(pbos): Make sure we don't pass unsupported extensions!
|
||||
webrtc::RtpExtension webrtc_extension(extensions[i].uri.c_str(),
|
||||
extensions[i].id);
|
||||
webrtc_extensions.push_back(webrtc_extension);
|
||||
}
|
||||
recv_rtp_extensions_ = webrtc_extensions;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebRtcVideoChannel2::SetSendRtpHeaderExtensions(
|
||||
const std::vector<RtpHeaderExtension>& extensions) {
|
||||
// TODO(pbos): Implement.
|
||||
LOG(LS_VERBOSE) << "SetSendRtpHeaderExtensions()";
|
||||
LOG(LS_INFO) << "SetSendRtpHeaderExtensions: "
|
||||
<< RtpExtensionsToString(extensions);
|
||||
std::vector<webrtc::RtpExtension> webrtc_extensions;
|
||||
for (size_t i = 0; i < extensions.size(); ++i) {
|
||||
// TODO(pbos): Make sure we don't pass unsupported extensions!
|
||||
webrtc::RtpExtension webrtc_extension(extensions[i].uri.c_str(),
|
||||
extensions[i].id);
|
||||
webrtc_extensions.push_back(webrtc_extension);
|
||||
}
|
||||
send_rtp_extensions_ = webrtc_extensions;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -236,6 +236,9 @@ class WebRtcVideoChannel2 : public talk_base::MessageHandler,
|
||||
OVERRIDE;
|
||||
virtual void OnReadyToSend(bool ready) OVERRIDE;
|
||||
virtual bool MuteStream(uint32 ssrc, bool mute) OVERRIDE;
|
||||
|
||||
// Set send/receive RTP header extensions. This must be done before creating
|
||||
// streams as it only has effect on future streams.
|
||||
virtual bool SetRecvRtpHeaderExtensions(
|
||||
const std::vector<RtpHeaderExtension>& extensions) OVERRIDE;
|
||||
virtual bool SetSendRtpHeaderExtensions(
|
||||
@ -351,8 +354,11 @@ class WebRtcVideoChannel2 : public talk_base::MessageHandler,
|
||||
std::map<uint32, webrtc::VideoReceiveStream*> receive_streams_;
|
||||
|
||||
Settable<VideoCodecSettings> send_codec_;
|
||||
std::vector<webrtc::RtpExtension> send_rtp_extensions_;
|
||||
|
||||
WebRtcVideoEncoderFactory2* const encoder_factory_;
|
||||
std::vector<VideoCodecSettings> recv_codecs_;
|
||||
std::vector<webrtc::RtpExtension> recv_rtp_extensions_;
|
||||
VideoOptions options_;
|
||||
};
|
||||
|
||||
|
@ -396,6 +396,31 @@ TEST_F(WebRtcVideoEngine2Test, DefaultRtxCodecHasAssociatedPayloadTypeSet) {
|
||||
FAIL() << "No RTX codec found among default codecs.";
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoEngine2Test, SupportsTimestampOffsetHeaderExtension) {
|
||||
std::vector<RtpHeaderExtension> extensions = engine_.rtp_header_extensions();
|
||||
ASSERT_FALSE(extensions.empty());
|
||||
for (size_t i = 0; i < extensions.size(); ++i) {
|
||||
if (extensions[i].uri == kRtpTimestampOffsetHeaderExtension) {
|
||||
EXPECT_EQ(kRtpTimestampOffsetHeaderExtensionDefaultId, extensions[i].id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
FAIL() << "Timestamp offset extension not in header-extension list.";
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoEngine2Test, SupportsAbsoluteSenderTimeHeaderExtension) {
|
||||
std::vector<RtpHeaderExtension> extensions = engine_.rtp_header_extensions();
|
||||
ASSERT_FALSE(extensions.empty());
|
||||
for (size_t i = 0; i < extensions.size(); ++i) {
|
||||
if (extensions[i].uri == kRtpAbsoluteSenderTimeHeaderExtension) {
|
||||
EXPECT_EQ(kRtpAbsoluteSenderTimeHeaderExtensionDefaultId,
|
||||
extensions[i].id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
FAIL() << "Absolute Sender Time extension not in header-extension list.";
|
||||
}
|
||||
|
||||
class WebRtcVideoChannel2BaseTest
|
||||
: public VideoMediaChannelTest<WebRtcVideoEngine2, WebRtcVideoChannel2> {
|
||||
protected:
|
||||
@ -598,6 +623,67 @@ class WebRtcVideoChannel2Test : public WebRtcVideoEngine2Test {
|
||||
EXPECT_EQ(video_codec.height, webrtc_codec.height);
|
||||
EXPECT_EQ(video_codec.framerate, webrtc_codec.maxFramerate);
|
||||
}
|
||||
|
||||
void TestSetSendRtpHeaderExtensions(const std::string& cricket_ext,
|
||||
const std::string& webrtc_ext) {
|
||||
// Enable extension.
|
||||
const int id = 1;
|
||||
std::vector<cricket::RtpHeaderExtension> extensions;
|
||||
extensions.push_back(cricket::RtpHeaderExtension(cricket_ext, id));
|
||||
EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(extensions));
|
||||
|
||||
FakeVideoSendStream* send_stream =
|
||||
AddSendStream(cricket::StreamParams::CreateLegacy(123));
|
||||
|
||||
// Verify the send extension id.
|
||||
ASSERT_EQ(1u, send_stream->GetConfig().rtp.extensions.size());
|
||||
EXPECT_EQ(id, send_stream->GetConfig().rtp.extensions[0].id);
|
||||
EXPECT_EQ(webrtc_ext, send_stream->GetConfig().rtp.extensions[0].name);
|
||||
// Verify call with same set of extensions returns true.
|
||||
EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(extensions));
|
||||
// Verify that SetSendRtpHeaderExtensions doesn't implicitly add them for
|
||||
// receivers.
|
||||
EXPECT_TRUE(AddRecvStream(cricket::StreamParams::CreateLegacy(123))
|
||||
->GetConfig()
|
||||
.rtp.extensions.empty());
|
||||
|
||||
// Remove the extension id, verify that this doesn't reset extensions as
|
||||
// they should be set before creating channels.
|
||||
std::vector<cricket::RtpHeaderExtension> empty_extensions;
|
||||
EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(empty_extensions));
|
||||
EXPECT_FALSE(send_stream->GetConfig().rtp.extensions.empty());
|
||||
}
|
||||
|
||||
void TestSetRecvRtpHeaderExtensions(const std::string& cricket_ext,
|
||||
const std::string& webrtc_ext) {
|
||||
// Enable extension.
|
||||
const int id = 1;
|
||||
std::vector<cricket::RtpHeaderExtension> extensions;
|
||||
extensions.push_back(cricket::RtpHeaderExtension(cricket_ext, id));
|
||||
EXPECT_TRUE(channel_->SetRecvRtpHeaderExtensions(extensions));
|
||||
|
||||
FakeVideoReceiveStream* recv_stream =
|
||||
AddRecvStream(cricket::StreamParams::CreateLegacy(123));
|
||||
|
||||
// Verify the recv extension id.
|
||||
ASSERT_EQ(1u, recv_stream->GetConfig().rtp.extensions.size());
|
||||
EXPECT_EQ(id, recv_stream->GetConfig().rtp.extensions[0].id);
|
||||
EXPECT_EQ(webrtc_ext, recv_stream->GetConfig().rtp.extensions[0].name);
|
||||
// Verify call with same set of extensions returns true.
|
||||
EXPECT_TRUE(channel_->SetRecvRtpHeaderExtensions(extensions));
|
||||
// Verify that SetRecvRtpHeaderExtensions doesn't implicitly add them for
|
||||
// senders.
|
||||
EXPECT_TRUE(AddSendStream(cricket::StreamParams::CreateLegacy(123))
|
||||
->GetConfig()
|
||||
.rtp.extensions.empty());
|
||||
|
||||
// Remove the extension id, verify that this doesn't reset extensions as
|
||||
// they should be set before creating channels.
|
||||
std::vector<cricket::RtpHeaderExtension> empty_extensions;
|
||||
EXPECT_TRUE(channel_->SetSendRtpHeaderExtensions(empty_extensions));
|
||||
EXPECT_FALSE(recv_stream->GetConfig().rtp.extensions.empty());
|
||||
}
|
||||
|
||||
talk_base::scoped_ptr<VideoMediaChannel> channel_;
|
||||
FakeWebRtcVideoChannel2* fake_channel_;
|
||||
uint32 last_ssrc_;
|
||||
@ -723,12 +809,34 @@ TEST_F(WebRtcVideoChannel2Test, RecvStreamNoRtx) {
|
||||
ASSERT_TRUE(recv_stream->GetConfig().rtp.rtx.empty());
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoChannel2Test, DISABLED_RtpTimestampOffsetHeaderExtensions) {
|
||||
FAIL() << "Not implemented."; // TODO(pbos): Implement.
|
||||
TEST_F(WebRtcVideoChannel2Test, NoHeaderExtesionsByDefault) {
|
||||
FakeVideoSendStream* send_stream =
|
||||
AddSendStream(cricket::StreamParams::CreateLegacy(kSsrcs1[0]));
|
||||
ASSERT_TRUE(send_stream->GetConfig().rtp.extensions.empty());
|
||||
|
||||
FakeVideoReceiveStream* recv_stream =
|
||||
AddRecvStream(cricket::StreamParams::CreateLegacy(kSsrcs1[0]));
|
||||
ASSERT_TRUE(recv_stream->GetConfig().rtp.extensions.empty());
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoChannel2Test, DISABLED_AbsoluteSendTimeHeaderExtensions) {
|
||||
FAIL() << "Not implemented."; // TODO(pbos): Implement.
|
||||
// Test support for RTP timestamp offset header extension.
|
||||
TEST_F(WebRtcVideoChannel2Test, SendRtpTimestampOffsetHeaderExtensions) {
|
||||
TestSetSendRtpHeaderExtensions(kRtpTimestampOffsetHeaderExtension,
|
||||
webrtc::RtpExtension::kTOffset);
|
||||
}
|
||||
TEST_F(WebRtcVideoChannel2Test, RecvRtpTimestampOffsetHeaderExtensions) {
|
||||
TestSetRecvRtpHeaderExtensions(kRtpTimestampOffsetHeaderExtension,
|
||||
webrtc::RtpExtension::kTOffset);
|
||||
}
|
||||
|
||||
// Test support for absolute send time header extension.
|
||||
TEST_F(WebRtcVideoChannel2Test, SendAbsoluteSendTimeHeaderExtensions) {
|
||||
TestSetSendRtpHeaderExtensions(kRtpAbsoluteSenderTimeHeaderExtension,
|
||||
webrtc::RtpExtension::kAbsSendTime);
|
||||
}
|
||||
TEST_F(WebRtcVideoChannel2Test, RecvAbsoluteSendTimeHeaderExtensions) {
|
||||
TestSetRecvRtpHeaderExtensions(kRtpAbsoluteSenderTimeHeaderExtension,
|
||||
webrtc::RtpExtension::kAbsSendTime);
|
||||
}
|
||||
|
||||
TEST_F(WebRtcVideoChannel2Test, DISABLED_LeakyBucketTest) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user