Dactyloidae/media/webrtc/signaling/test/jsep_track_unittest.cpp
Moonchild 8c395520d9 Issue #1656 - Part 1: Nuke most vim config lines in the tree.
Since these are just interpreted comments, there's 0 impact on actual code.
This removes all lines that match /* vim: set(.*)tw=80: */ with S&R -- there are
a few others scattered around which will be removed manually in a second part.
2020-09-25 22:04:12 +08:00

1268 lines
41 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#define GTEST_HAS_RTTI 0
#include "gtest/gtest.h"
#include "gtest_utils.h"
// Magic linker includes :(
#include "FakeMediaStreams.h"
#include "FakeMediaStreamsImpl.h"
#include "FakeLogging.h"
#include "signaling/src/jsep/JsepTrack.h"
#include "signaling/src/sdp/SipccSdp.h"
#include "signaling/src/sdp/SdpHelper.h"
#include "mtransport_test_utils.h"
#include "FakeIPC.h"
#include "FakeIPC.cpp"
#include "TestHarness.h"
namespace mozilla {
class JsepTrackTest : public ::testing::Test
{
public:
JsepTrackTest() {}
std::vector<JsepCodecDescription*>
MakeCodecs(bool addFecCodecs = false,
bool preferRed = false,
bool addDtmfCodec = false) const
{
std::vector<JsepCodecDescription*> results;
results.push_back(
new JsepAudioCodecDescription("1", "opus", 48000, 2, 960, 40000));
results.push_back(
new JsepAudioCodecDescription("9", "G722", 8000, 1, 320, 64000));
if (addDtmfCodec) {
results.push_back(
new JsepAudioCodecDescription("101", "telephone-event",
8000, 1, 0, 0));
}
JsepVideoCodecDescription* red = nullptr;
if (addFecCodecs && preferRed) {
red = new JsepVideoCodecDescription(
"122",
"red",
90000
);
results.push_back(red);
}
JsepVideoCodecDescription* vp8 =
new JsepVideoCodecDescription("120", "VP8", 90000);
vp8->mConstraints.maxFs = 12288;
vp8->mConstraints.maxFps = 60;
results.push_back(vp8);
JsepVideoCodecDescription* h264 =
new JsepVideoCodecDescription("126", "H264", 90000);
h264->mPacketizationMode = 1;
h264->mProfileLevelId = 0x42E00D;
results.push_back(h264);
if (addFecCodecs) {
if (!preferRed) {
red = new JsepVideoCodecDescription(
"122",
"red",
90000
);
results.push_back(red);
}
JsepVideoCodecDescription* ulpfec = new JsepVideoCodecDescription(
"123",
"ulpfec",
90000
);
results.push_back(ulpfec);
}
results.push_back(
new JsepApplicationCodecDescription(
"5000",
"webrtc-datachannel",
16
));
// if we're doing something with red, it needs
// to update the redundant encodings list
if (red) {
red->UpdateRedundantEncodings(results);
}
return results;
}
void Init(SdpMediaSection::MediaType type) {
InitCodecs();
InitTracks(type);
InitSdp(type);
}
void InitCodecs() {
mOffCodecs.values = MakeCodecs();
mAnsCodecs.values = MakeCodecs();
}
void InitTracks(SdpMediaSection::MediaType type)
{
mSendOff = new JsepTrack(type, "stream_id", "track_id", sdp::kSend);
mRecvOff = new JsepTrack(type, "stream_id", "track_id", sdp::kRecv);
mSendOff->PopulateCodecs(mOffCodecs.values);
mRecvOff->PopulateCodecs(mOffCodecs.values);
mSendAns = new JsepTrack(type, "stream_id", "track_id", sdp::kSend);
mRecvAns = new JsepTrack(type, "stream_id", "track_id", sdp::kRecv);
mSendAns->PopulateCodecs(mAnsCodecs.values);
mRecvAns->PopulateCodecs(mAnsCodecs.values);
}
void InitSdp(SdpMediaSection::MediaType type)
{
mOffer.reset(new SipccSdp(SdpOrigin("", 0, 0, sdp::kIPv4, "")));
mOffer->AddMediaSection(
type,
SdpDirectionAttribute::kInactive,
0,
SdpHelper::GetProtocolForMediaType(type),
sdp::kIPv4,
"0.0.0.0");
mAnswer.reset(new SipccSdp(SdpOrigin("", 0, 0, sdp::kIPv4, "")));
mAnswer->AddMediaSection(
type,
SdpDirectionAttribute::kInactive,
0,
SdpHelper::GetProtocolForMediaType(type),
sdp::kIPv4,
"0.0.0.0");
}
SdpMediaSection& GetOffer()
{
return mOffer->GetMediaSection(0);
}
SdpMediaSection& GetAnswer()
{
return mAnswer->GetMediaSection(0);
}
void CreateOffer()
{
if (mSendOff) {
mSendOff->AddToOffer(&GetOffer());
}
if (mRecvOff) {
mRecvOff->AddToOffer(&GetOffer());
}
}
void CreateAnswer()
{
if (mSendAns && GetOffer().IsReceiving()) {
mSendAns->AddToAnswer(GetOffer(), &GetAnswer());
}
if (mRecvAns && GetOffer().IsSending()) {
mRecvAns->AddToAnswer(GetOffer(), &GetAnswer());
}
}
void Negotiate()
{
std::cerr << "Offer SDP: " << std::endl;
mOffer->Serialize(std::cerr);
std::cerr << "Answer SDP: " << std::endl;
mAnswer->Serialize(std::cerr);
if (mSendAns && GetAnswer().IsSending()) {
mSendAns->Negotiate(GetAnswer(), GetOffer());
}
if (mRecvAns && GetAnswer().IsReceiving()) {
mRecvAns->Negotiate(GetAnswer(), GetOffer());
}
if (mSendOff && GetAnswer().IsReceiving()) {
mSendOff->Negotiate(GetAnswer(), GetAnswer());
}
if (mRecvOff && GetAnswer().IsSending()) {
mRecvOff->Negotiate(GetAnswer(), GetAnswer());
}
}
void OfferAnswer()
{
CreateOffer();
CreateAnswer();
Negotiate();
SanityCheck();
}
static size_t EncodingCount(const RefPtr<JsepTrack>& track)
{
return track->GetNegotiatedDetails()->GetEncodingCount();
}
// TODO: Look into writing a macro that wraps an ASSERT_ and returns false
// if it fails (probably requires writing a bool-returning function that
// takes a void-returning lambda with a bool outparam, which will in turn
// invokes the ASSERT_)
static void CheckEncodingCount(size_t expected,
const RefPtr<JsepTrack>& send,
const RefPtr<JsepTrack>& recv)
{
if (expected) {
ASSERT_TRUE(!!send);
ASSERT_TRUE(send->GetNegotiatedDetails());
ASSERT_TRUE(!!recv);
ASSERT_TRUE(recv->GetNegotiatedDetails());
}
if (send && send->GetNegotiatedDetails()) {
ASSERT_EQ(expected, send->GetNegotiatedDetails()->GetEncodingCount());
}
if (recv && recv->GetNegotiatedDetails()) {
ASSERT_EQ(expected, recv->GetNegotiatedDetails()->GetEncodingCount());
}
}
void CheckOffEncodingCount(size_t expected) const
{
CheckEncodingCount(expected, mSendOff, mRecvAns);
}
void CheckAnsEncodingCount(size_t expected) const
{
CheckEncodingCount(expected, mSendAns, mRecvOff);
}
const JsepCodecDescription*
GetCodec(const JsepTrack& track,
SdpMediaSection::MediaType type,
size_t expectedSize,
size_t codecIndex) const
{
if (!track.GetNegotiatedDetails() ||
track.GetNegotiatedDetails()->GetEncodingCount() != 1U ||
track.GetMediaType() != type) {
return nullptr;
}
const std::vector<JsepCodecDescription*>& codecs =
track.GetNegotiatedDetails()->GetEncoding(0).GetCodecs();
// it should not be possible for codecs to have a different type
// than the track, but we'll check the codec here just in case.
if (codecs.size() != expectedSize || codecIndex >= expectedSize ||
codecs[codecIndex]->mType != type) {
return nullptr;
}
return codecs[codecIndex];
}
const JsepVideoCodecDescription*
GetVideoCodec(const JsepTrack& track,
size_t expectedSize = 1,
size_t codecIndex = 0) const
{
return static_cast<const JsepVideoCodecDescription*>
(GetCodec(track, SdpMediaSection::kVideo, expectedSize, codecIndex));
}
const JsepAudioCodecDescription*
GetAudioCodec(const JsepTrack& track,
size_t expectedSize = 1,
size_t codecIndex = 0) const
{
return static_cast<const JsepAudioCodecDescription*>
(GetCodec(track, SdpMediaSection::kAudio, expectedSize, codecIndex));
}
void CheckOtherFbsSize(const JsepTrack& track, size_t expected) const
{
const JsepVideoCodecDescription* videoCodec = GetVideoCodec(track);
ASSERT_NE(videoCodec, nullptr);
ASSERT_EQ(videoCodec->mOtherFbTypes.size(), expected);
}
void CheckOtherFbExists(const JsepTrack& track,
SdpRtcpFbAttributeList::Type type) const
{
const JsepVideoCodecDescription* videoCodec = GetVideoCodec(track);
ASSERT_NE(videoCodec, nullptr);
for (const auto& fb : videoCodec->mOtherFbTypes) {
if (fb.type == type) {
return; // found the RtcpFb type, so stop looking
}
}
FAIL(); // RtcpFb type not found
}
void SanityCheckRtcpFbs(const JsepVideoCodecDescription& a,
const JsepVideoCodecDescription& b) const
{
ASSERT_EQ(a.mNackFbTypes.size(), b.mNackFbTypes.size());
ASSERT_EQ(a.mAckFbTypes.size(), b.mAckFbTypes.size());
ASSERT_EQ(a.mCcmFbTypes.size(), b.mCcmFbTypes.size());
ASSERT_EQ(a.mOtherFbTypes.size(), b.mOtherFbTypes.size());
}
void SanityCheckCodecs(const JsepCodecDescription& a,
const JsepCodecDescription& b) const
{
ASSERT_EQ(a.mType, b.mType);
ASSERT_EQ(a.mDefaultPt, b.mDefaultPt);
ASSERT_EQ(a.mName, b.mName);
ASSERT_EQ(a.mClock, b.mClock);
ASSERT_EQ(a.mChannels, b.mChannels);
ASSERT_NE(a.mDirection, b.mDirection);
// These constraints are for fmtp and rid, which _are_ signaled
ASSERT_EQ(a.mConstraints, b.mConstraints);
if (a.mType == SdpMediaSection::kVideo) {
SanityCheckRtcpFbs(static_cast<const JsepVideoCodecDescription&>(a),
static_cast<const JsepVideoCodecDescription&>(b));
}
}
void SanityCheckEncodings(const JsepTrackEncoding& a,
const JsepTrackEncoding& b) const
{
ASSERT_EQ(a.GetCodecs().size(), b.GetCodecs().size());
for (size_t i = 0; i < a.GetCodecs().size(); ++i) {
SanityCheckCodecs(*a.GetCodecs()[i], *b.GetCodecs()[i]);
}
ASSERT_EQ(a.mRid, b.mRid);
// mConstraints will probably differ, since they are not signaled to the
// other side.
}
void SanityCheckNegotiatedDetails(const JsepTrackNegotiatedDetails& a,
const JsepTrackNegotiatedDetails& b) const
{
ASSERT_EQ(a.GetEncodingCount(), b.GetEncodingCount());
for (size_t i = 0; i < a.GetEncodingCount(); ++i) {
SanityCheckEncodings(a.GetEncoding(i), b.GetEncoding(i));
}
ASSERT_EQ(a.GetUniquePayloadTypes().size(),
b.GetUniquePayloadTypes().size());
for (size_t i = 0; i < a.GetUniquePayloadTypes().size(); ++i) {
ASSERT_EQ(a.GetUniquePayloadTypes()[i], b.GetUniquePayloadTypes()[i]);
}
}
void SanityCheckTracks(const JsepTrack& a, const JsepTrack& b) const
{
if (!a.GetNegotiatedDetails()) {
ASSERT_FALSE(!!b.GetNegotiatedDetails());
return;
}
ASSERT_TRUE(!!a.GetNegotiatedDetails());
ASSERT_TRUE(!!b.GetNegotiatedDetails());
ASSERT_EQ(a.GetMediaType(), b.GetMediaType());
ASSERT_EQ(a.GetStreamId(), b.GetStreamId());
ASSERT_EQ(a.GetTrackId(), b.GetTrackId());
ASSERT_EQ(a.GetCNAME(), b.GetCNAME());
ASSERT_NE(a.GetDirection(), b.GetDirection());
ASSERT_EQ(a.GetSsrcs().size(), b.GetSsrcs().size());
for (size_t i = 0; i < a.GetSsrcs().size(); ++i) {
ASSERT_EQ(a.GetSsrcs()[i], b.GetSsrcs()[i]);
}
SanityCheckNegotiatedDetails(*a.GetNegotiatedDetails(),
*b.GetNegotiatedDetails());
}
void SanityCheck() const
{
if (mSendOff && mRecvAns) {
SanityCheckTracks(*mSendOff, *mRecvAns);
}
if (mRecvOff && mSendAns) {
SanityCheckTracks(*mRecvOff, *mSendAns);
}
}
protected:
RefPtr<JsepTrack> mSendOff;
RefPtr<JsepTrack> mRecvOff;
RefPtr<JsepTrack> mSendAns;
RefPtr<JsepTrack> mRecvAns;
PtrVector<JsepCodecDescription> mOffCodecs;
PtrVector<JsepCodecDescription> mAnsCodecs;
UniquePtr<Sdp> mOffer;
UniquePtr<Sdp> mAnswer;
};
TEST_F(JsepTrackTest, CreateDestroy)
{
Init(SdpMediaSection::kAudio);
}
TEST_F(JsepTrackTest, AudioNegotiation)
{
Init(SdpMediaSection::kAudio);
OfferAnswer();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(1);
}
TEST_F(JsepTrackTest, VideoNegotiation)
{
Init(SdpMediaSection::kVideo);
OfferAnswer();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(1);
}
class CheckForCodecType
{
public:
explicit CheckForCodecType(SdpMediaSection::MediaType type,
bool *result) :
mResult(result),
mType(type) {}
void operator()(JsepCodecDescription* codec) {
if (codec->mType == mType) {
*mResult = true;
}
}
private:
bool *mResult;
SdpMediaSection::MediaType mType;
};
TEST_F(JsepTrackTest, CheckForMismatchedAudioCodecAndVideoTrack)
{
PtrVector<JsepCodecDescription> offerCodecs;
// make codecs including telephone-event (an audio codec)
offerCodecs.values = MakeCodecs(false, false, true);
RefPtr<JsepTrack> videoTrack = new JsepTrack(SdpMediaSection::kVideo,
"stream_id",
"track_id",
sdp::kSend);
// populate codecs and then make sure we don't have any audio codecs
// in the video track
videoTrack->PopulateCodecs(offerCodecs.values);
bool found = false;
videoTrack->ForEachCodec(CheckForCodecType(SdpMediaSection::kAudio, &found));
ASSERT_FALSE(found);
found = false;
videoTrack->ForEachCodec(CheckForCodecType(SdpMediaSection::kVideo, &found));
ASSERT_TRUE(found); // for sanity, make sure we did find video codecs
}
TEST_F(JsepTrackTest, CheckVideoTrackWithHackedDtmfSdp)
{
Init(SdpMediaSection::kVideo);
CreateOffer();
// make sure we don't find sdp containing telephone-event in video track
ASSERT_EQ(mOffer->ToString().find("a=rtpmap:101 telephone-event"),
std::string::npos);
// force audio codec telephone-event into video m= section of offer
GetOffer().AddCodec("101", "telephone-event", 8000, 1);
// make sure we _do_ find sdp containing telephone-event in video track
ASSERT_NE(mOffer->ToString().find("a=rtpmap:101 telephone-event"),
std::string::npos);
CreateAnswer();
// make sure we don't find sdp containing telephone-event in video track
ASSERT_EQ(mAnswer->ToString().find("a=rtpmap:101 telephone-event"),
std::string::npos);
// force audio codec telephone-event into video m= section of answer
GetAnswer().AddCodec("101", "telephone-event", 8000, 1);
// make sure we _do_ find sdp containing telephone-event in video track
ASSERT_NE(mAnswer->ToString().find("a=rtpmap:101 telephone-event"),
std::string::npos);
Negotiate();
SanityCheck();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(1);
ASSERT_TRUE(mSendOff.get());
ASSERT_TRUE(mRecvOff.get());
ASSERT_TRUE(mSendAns.get());
ASSERT_TRUE(mRecvAns.get());
// make sure we still don't find any audio codecs in the video track after
// hacking the sdp
bool found = false;
mSendOff->ForEachCodec(CheckForCodecType(SdpMediaSection::kAudio, &found));
ASSERT_FALSE(found);
mRecvOff->ForEachCodec(CheckForCodecType(SdpMediaSection::kAudio, &found));
ASSERT_FALSE(found);
mSendAns->ForEachCodec(CheckForCodecType(SdpMediaSection::kAudio, &found));
ASSERT_FALSE(found);
mRecvAns->ForEachCodec(CheckForCodecType(SdpMediaSection::kAudio, &found));
ASSERT_FALSE(found);
}
TEST_F(JsepTrackTest, AudioNegotiationOffererDtmf)
{
mOffCodecs.values = MakeCodecs(false, false, true);
mAnsCodecs.values = MakeCodecs(false, false, false);
InitTracks(SdpMediaSection::kAudio);
InitSdp(SdpMediaSection::kAudio);
OfferAnswer();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(1);
ASSERT_NE(mOffer->ToString().find("a=rtpmap:101 telephone-event"),
std::string::npos);
ASSERT_EQ(mAnswer->ToString().find("a=rtpmap:101 telephone-event"),
std::string::npos);
ASSERT_NE(mOffer->ToString().find("a=fmtp:101 0-15"), std::string::npos);
ASSERT_EQ(mAnswer->ToString().find("a=fmtp:101"), std::string::npos);
const JsepAudioCodecDescription* track = nullptr;
ASSERT_TRUE((track = GetAudioCodec(*mSendOff)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvOff)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendAns)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvAns)));
ASSERT_EQ("1", track->mDefaultPt);
}
TEST_F(JsepTrackTest, AudioNegotiationAnswererDtmf)
{
mOffCodecs.values = MakeCodecs(false, false, false);
mAnsCodecs.values = MakeCodecs(false, false, true);
InitTracks(SdpMediaSection::kAudio);
InitSdp(SdpMediaSection::kAudio);
OfferAnswer();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(1);
ASSERT_EQ(mOffer->ToString().find("a=rtpmap:101 telephone-event"),
std::string::npos);
ASSERT_EQ(mAnswer->ToString().find("a=rtpmap:101 telephone-event"),
std::string::npos);
ASSERT_EQ(mOffer->ToString().find("a=fmtp:101 0-15"), std::string::npos);
ASSERT_EQ(mAnswer->ToString().find("a=fmtp:101"), std::string::npos);
const JsepAudioCodecDescription* track = nullptr;
ASSERT_TRUE((track = GetAudioCodec(*mSendOff)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvOff)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendAns)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvAns)));
ASSERT_EQ("1", track->mDefaultPt);
}
TEST_F(JsepTrackTest, AudioNegotiationOffererAnswererDtmf)
{
mOffCodecs.values = MakeCodecs(false, false, true);
mAnsCodecs.values = MakeCodecs(false, false, true);
InitTracks(SdpMediaSection::kAudio);
InitSdp(SdpMediaSection::kAudio);
OfferAnswer();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(1);
ASSERT_NE(mOffer->ToString().find("a=rtpmap:101 telephone-event"),
std::string::npos);
ASSERT_NE(mAnswer->ToString().find("a=rtpmap:101 telephone-event"),
std::string::npos);
ASSERT_NE(mOffer->ToString().find("a=fmtp:101 0-15"), std::string::npos);
ASSERT_NE(mAnswer->ToString().find("a=fmtp:101 0-15"), std::string::npos);
const JsepAudioCodecDescription* track = nullptr;
ASSERT_TRUE((track = GetAudioCodec(*mSendOff, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvOff, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendAns, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvAns, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendOff, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvOff, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendAns, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvAns, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
}
TEST_F(JsepTrackTest, AudioNegotiationDtmfOffererNoFmtpAnswererFmtp)
{
mOffCodecs.values = MakeCodecs(false, false, true);
mAnsCodecs.values = MakeCodecs(false, false, true);
InitTracks(SdpMediaSection::kAudio);
InitSdp(SdpMediaSection::kAudio);
CreateOffer();
GetOffer().RemoveFmtp("101");
CreateAnswer();
Negotiate();
SanityCheck();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(1);
ASSERT_NE(mOffer->ToString().find("a=rtpmap:101 telephone-event"),
std::string::npos);
ASSERT_NE(mAnswer->ToString().find("a=rtpmap:101 telephone-event"),
std::string::npos);
ASSERT_EQ(mOffer->ToString().find("a=fmtp:101"), std::string::npos);
ASSERT_NE(mAnswer->ToString().find("a=fmtp:101 0-15"), std::string::npos);
const JsepAudioCodecDescription* track = nullptr;
ASSERT_TRUE((track = GetAudioCodec(*mSendOff, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvOff, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendAns, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvAns, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendOff, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvOff, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendAns, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvAns, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
}
TEST_F(JsepTrackTest, AudioNegotiationDtmfOffererFmtpAnswererNoFmtp)
{
mOffCodecs.values = MakeCodecs(false, false, true);
mAnsCodecs.values = MakeCodecs(false, false, true);
InitTracks(SdpMediaSection::kAudio);
InitSdp(SdpMediaSection::kAudio);
CreateOffer();
CreateAnswer();
GetAnswer().RemoveFmtp("101");
Negotiate();
SanityCheck();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(1);
ASSERT_NE(mOffer->ToString().find("a=rtpmap:101 telephone-event"),
std::string::npos);
ASSERT_NE(mAnswer->ToString().find("a=rtpmap:101 telephone-event"),
std::string::npos);
ASSERT_NE(mOffer->ToString().find("a=fmtp:101 0-15"), std::string::npos);
ASSERT_EQ(mAnswer->ToString().find("a=fmtp:101"), std::string::npos);
const JsepAudioCodecDescription* track = nullptr;
ASSERT_TRUE((track = GetAudioCodec(*mSendOff, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvOff, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendAns, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvAns, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendOff, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvOff, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendAns, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvAns, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
}
TEST_F(JsepTrackTest, AudioNegotiationDtmfOffererNoFmtpAnswererNoFmtp)
{
mOffCodecs.values = MakeCodecs(false, false, true);
mAnsCodecs.values = MakeCodecs(false, false, true);
InitTracks(SdpMediaSection::kAudio);
InitSdp(SdpMediaSection::kAudio);
CreateOffer();
GetOffer().RemoveFmtp("101");
CreateAnswer();
GetAnswer().RemoveFmtp("101");
Negotiate();
SanityCheck();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(1);
ASSERT_NE(mOffer->ToString().find("a=rtpmap:101 telephone-event"),
std::string::npos);
ASSERT_NE(mAnswer->ToString().find("a=rtpmap:101 telephone-event"),
std::string::npos);
ASSERT_EQ(mOffer->ToString().find("a=fmtp:101"), std::string::npos);
ASSERT_EQ(mAnswer->ToString().find("a=fmtp:101"), std::string::npos);
const JsepAudioCodecDescription* track = nullptr;
ASSERT_TRUE((track = GetAudioCodec(*mSendOff, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvOff, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendAns, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvAns, 2)));
ASSERT_EQ("1", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendOff, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvOff, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mSendAns, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
ASSERT_TRUE((track = GetAudioCodec(*mRecvAns, 2, 1)));
ASSERT_EQ("101", track->mDefaultPt);
}
TEST_F(JsepTrackTest, VideoNegotationOffererFEC)
{
mOffCodecs.values = MakeCodecs(true);
mAnsCodecs.values = MakeCodecs(false);
InitTracks(SdpMediaSection::kVideo);
InitSdp(SdpMediaSection::kVideo);
OfferAnswer();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(1);
ASSERT_NE(mOffer->ToString().find("a=rtpmap:122 red"), std::string::npos);
ASSERT_NE(mOffer->ToString().find("a=rtpmap:123 ulpfec"), std::string::npos);
ASSERT_EQ(mAnswer->ToString().find("a=rtpmap:122 red"), std::string::npos);
ASSERT_EQ(mAnswer->ToString().find("a=rtpmap:123 ulpfec"), std::string::npos);
ASSERT_NE(mOffer->ToString().find("a=fmtp:122 120/126/123"), std::string::npos);
ASSERT_EQ(mAnswer->ToString().find("a=fmtp:122"), std::string::npos);
const JsepVideoCodecDescription* track = nullptr;
ASSERT_TRUE((track = GetVideoCodec(*mSendOff)));
ASSERT_EQ("120", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mRecvOff)));
ASSERT_EQ("120", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mSendAns)));
ASSERT_EQ("120", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mRecvAns)));
ASSERT_EQ("120", track->mDefaultPt);
}
TEST_F(JsepTrackTest, VideoNegotationAnswererFEC)
{
mOffCodecs.values = MakeCodecs(false);
mAnsCodecs.values = MakeCodecs(true);
InitTracks(SdpMediaSection::kVideo);
InitSdp(SdpMediaSection::kVideo);
OfferAnswer();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(1);
ASSERT_EQ(mOffer->ToString().find("a=rtpmap:122 red"), std::string::npos);
ASSERT_EQ(mOffer->ToString().find("a=rtpmap:123 ulpfec"), std::string::npos);
ASSERT_EQ(mAnswer->ToString().find("a=rtpmap:122 red"), std::string::npos);
ASSERT_EQ(mAnswer->ToString().find("a=rtpmap:123 ulpfec"), std::string::npos);
ASSERT_EQ(mOffer->ToString().find("a=fmtp:122"), std::string::npos);
ASSERT_EQ(mAnswer->ToString().find("a=fmtp:122"), std::string::npos);
const JsepVideoCodecDescription* track = nullptr;
ASSERT_TRUE((track = GetVideoCodec(*mSendOff)));
ASSERT_EQ("120", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mRecvOff)));
ASSERT_EQ("120", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mSendAns)));
ASSERT_EQ("120", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mRecvAns)));
ASSERT_EQ("120", track->mDefaultPt);
}
TEST_F(JsepTrackTest, VideoNegotationOffererAnswererFEC)
{
mOffCodecs.values = MakeCodecs(true);
mAnsCodecs.values = MakeCodecs(true);
InitTracks(SdpMediaSection::kVideo);
InitSdp(SdpMediaSection::kVideo);
OfferAnswer();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(1);
ASSERT_NE(mOffer->ToString().find("a=rtpmap:122 red"), std::string::npos);
ASSERT_NE(mOffer->ToString().find("a=rtpmap:123 ulpfec"), std::string::npos);
ASSERT_NE(mAnswer->ToString().find("a=rtpmap:122 red"), std::string::npos);
ASSERT_NE(mAnswer->ToString().find("a=rtpmap:123 ulpfec"), std::string::npos);
ASSERT_NE(mOffer->ToString().find("a=fmtp:122 120/126/123"), std::string::npos);
ASSERT_NE(mAnswer->ToString().find("a=fmtp:122 120/126/123"), std::string::npos);
const JsepVideoCodecDescription* track = nullptr;
ASSERT_TRUE((track = GetVideoCodec(*mSendOff, 4)));
ASSERT_EQ("120", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mRecvOff, 4)));
ASSERT_EQ("120", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mSendAns, 4)));
ASSERT_EQ("120", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mRecvAns, 4)));
ASSERT_EQ("120", track->mDefaultPt);
}
TEST_F(JsepTrackTest, VideoNegotationOffererAnswererFECPreferred)
{
mOffCodecs.values = MakeCodecs(true, true);
mAnsCodecs.values = MakeCodecs(true);
InitTracks(SdpMediaSection::kVideo);
InitSdp(SdpMediaSection::kVideo);
OfferAnswer();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(1);
ASSERT_NE(mOffer->ToString().find("a=rtpmap:122 red"), std::string::npos);
ASSERT_NE(mOffer->ToString().find("a=rtpmap:123 ulpfec"), std::string::npos);
ASSERT_NE(mAnswer->ToString().find("a=rtpmap:122 red"), std::string::npos);
ASSERT_NE(mAnswer->ToString().find("a=rtpmap:123 ulpfec"), std::string::npos);
ASSERT_NE(mOffer->ToString().find("a=fmtp:122 120/126/123"), std::string::npos);
ASSERT_NE(mAnswer->ToString().find("a=fmtp:122 120/126/123"), std::string::npos);
const JsepVideoCodecDescription* track = nullptr;
ASSERT_TRUE((track = GetVideoCodec(*mSendOff, 4)));
ASSERT_EQ("122", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mRecvOff, 4)));
ASSERT_EQ("122", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mSendAns, 4)));
ASSERT_EQ("122", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mRecvAns, 4)));
ASSERT_EQ("122", track->mDefaultPt);
}
// Make sure we only put the right things in the fmtp:122 120/.... line
TEST_F(JsepTrackTest, VideoNegotationOffererAnswererFECMismatch)
{
mOffCodecs.values = MakeCodecs(true, true);
mAnsCodecs.values = MakeCodecs(true);
// remove h264 from answer codecs
ASSERT_EQ("H264", mAnsCodecs.values[3]->mName);
mAnsCodecs.values.erase(mAnsCodecs.values.begin()+3);
InitTracks(SdpMediaSection::kVideo);
InitSdp(SdpMediaSection::kVideo);
OfferAnswer();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(1);
ASSERT_NE(mOffer->ToString().find("a=rtpmap:122 red"), std::string::npos);
ASSERT_NE(mOffer->ToString().find("a=rtpmap:123 ulpfec"), std::string::npos);
ASSERT_NE(mAnswer->ToString().find("a=rtpmap:122 red"), std::string::npos);
ASSERT_NE(mAnswer->ToString().find("a=rtpmap:123 ulpfec"), std::string::npos);
ASSERT_NE(mOffer->ToString().find("a=fmtp:122 120/126/123"), std::string::npos);
ASSERT_NE(mAnswer->ToString().find("a=fmtp:122 120/123"), std::string::npos);
const JsepVideoCodecDescription* track = nullptr;
ASSERT_TRUE((track = GetVideoCodec(*mSendOff, 3)));
ASSERT_EQ("122", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mRecvOff, 3)));
ASSERT_EQ("122", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mSendAns, 3)));
ASSERT_EQ("122", track->mDefaultPt);
ASSERT_TRUE((track = GetVideoCodec(*mRecvAns, 3)));
ASSERT_EQ("122", track->mDefaultPt);
}
TEST_F(JsepTrackTest, VideoNegotationOffererAnswererFECZeroVP9Codec)
{
mOffCodecs.values = MakeCodecs(true);
JsepVideoCodecDescription* vp9 =
new JsepVideoCodecDescription("0", "VP9", 90000);
vp9->mConstraints.maxFs = 12288;
vp9->mConstraints.maxFps = 60;
mOffCodecs.values.push_back(vp9);
ASSERT_EQ(8U, mOffCodecs.values.size());
JsepVideoCodecDescription* red =
static_cast<JsepVideoCodecDescription*>(mOffCodecs.values[4]);
ASSERT_EQ("red", red->mName);
// rebuild the redundant encodings with our newly added "wacky" VP9
red->mRedundantEncodings.clear();
red->UpdateRedundantEncodings(mOffCodecs.values);
mAnsCodecs.values = MakeCodecs(true);
InitTracks(SdpMediaSection::kVideo);
InitSdp(SdpMediaSection::kVideo);
OfferAnswer();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(1);
ASSERT_NE(mOffer->ToString().find("a=rtpmap:122 red"), std::string::npos);
ASSERT_NE(mOffer->ToString().find("a=rtpmap:123 ulpfec"), std::string::npos);
ASSERT_NE(mAnswer->ToString().find("a=rtpmap:122 red"), std::string::npos);
ASSERT_NE(mAnswer->ToString().find("a=rtpmap:123 ulpfec"), std::string::npos);
ASSERT_NE(mOffer->ToString().find("a=fmtp:122 120/126/123/0"), std::string::npos);
ASSERT_NE(mAnswer->ToString().find("a=fmtp:122 120/126/123\r\n"), std::string::npos);
}
TEST_F(JsepTrackTest, VideoNegotiationOfferRemb)
{
InitCodecs();
// enable remb on the offer codecs
((JsepVideoCodecDescription*)mOffCodecs.values[2])->EnableRemb();
InitTracks(SdpMediaSection::kVideo);
InitSdp(SdpMediaSection::kVideo);
OfferAnswer();
// make sure REMB is on offer and not on answer
ASSERT_NE(mOffer->ToString().find("a=rtcp-fb:120 goog-remb"),
std::string::npos);
ASSERT_EQ(mAnswer->ToString().find("a=rtcp-fb:120 goog-remb"),
std::string::npos);
CheckOffEncodingCount(1);
CheckAnsEncodingCount(1);
CheckOtherFbsSize(*mSendOff, 0);
CheckOtherFbsSize(*mRecvAns, 0);
CheckOtherFbsSize(*mSendAns, 0);
CheckOtherFbsSize(*mRecvOff, 0);
}
TEST_F(JsepTrackTest, VideoNegotiationAnswerRemb)
{
InitCodecs();
// enable remb on the answer codecs
((JsepVideoCodecDescription*)mAnsCodecs.values[2])->EnableRemb();
InitTracks(SdpMediaSection::kVideo);
InitSdp(SdpMediaSection::kVideo);
OfferAnswer();
// make sure REMB is not on offer and not on answer
ASSERT_EQ(mOffer->ToString().find("a=rtcp-fb:120 goog-remb"),
std::string::npos);
ASSERT_EQ(mAnswer->ToString().find("a=rtcp-fb:120 goog-remb"),
std::string::npos);
CheckOffEncodingCount(1);
CheckAnsEncodingCount(1);
CheckOtherFbsSize(*mSendOff, 0);
CheckOtherFbsSize(*mRecvAns, 0);
CheckOtherFbsSize(*mSendAns, 0);
CheckOtherFbsSize(*mRecvOff, 0);
}
TEST_F(JsepTrackTest, VideoNegotiationOfferAnswerRemb)
{
InitCodecs();
// enable remb on the offer and answer codecs
((JsepVideoCodecDescription*)mOffCodecs.values[2])->EnableRemb();
((JsepVideoCodecDescription*)mAnsCodecs.values[2])->EnableRemb();
InitTracks(SdpMediaSection::kVideo);
InitSdp(SdpMediaSection::kVideo);
OfferAnswer();
// make sure REMB is on offer and on answer
ASSERT_NE(mOffer->ToString().find("a=rtcp-fb:120 goog-remb"),
std::string::npos);
ASSERT_NE(mAnswer->ToString().find("a=rtcp-fb:120 goog-remb"),
std::string::npos);
CheckOffEncodingCount(1);
CheckAnsEncodingCount(1);
CheckOtherFbsSize(*mSendOff, 1);
CheckOtherFbsSize(*mRecvAns, 1);
CheckOtherFbExists(*mSendOff, SdpRtcpFbAttributeList::kRemb);
CheckOtherFbExists(*mRecvAns, SdpRtcpFbAttributeList::kRemb);
CheckOtherFbsSize(*mSendAns, 1);
CheckOtherFbsSize(*mRecvOff, 1);
CheckOtherFbExists(*mSendAns, SdpRtcpFbAttributeList::kRemb);
CheckOtherFbExists(*mRecvOff, SdpRtcpFbAttributeList::kRemb);
}
TEST_F(JsepTrackTest, AudioOffSendonlyAnsRecvonly)
{
Init(SdpMediaSection::kAudio);
mRecvOff = nullptr;
mSendAns = nullptr;
OfferAnswer();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(0);
}
TEST_F(JsepTrackTest, VideoOffSendonlyAnsRecvonly)
{
Init(SdpMediaSection::kVideo);
mRecvOff = nullptr;
mSendAns = nullptr;
OfferAnswer();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(0);
}
TEST_F(JsepTrackTest, AudioOffSendrecvAnsRecvonly)
{
Init(SdpMediaSection::kAudio);
mSendAns = nullptr;
OfferAnswer();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(0);
}
TEST_F(JsepTrackTest, VideoOffSendrecvAnsRecvonly)
{
Init(SdpMediaSection::kVideo);
mSendAns = nullptr;
OfferAnswer();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(0);
}
TEST_F(JsepTrackTest, AudioOffRecvonlyAnsSendrecv)
{
Init(SdpMediaSection::kAudio);
mSendOff = nullptr;
OfferAnswer();
CheckOffEncodingCount(0);
CheckAnsEncodingCount(1);
}
TEST_F(JsepTrackTest, VideoOffRecvonlyAnsSendrecv)
{
Init(SdpMediaSection::kVideo);
mSendOff = nullptr;
OfferAnswer();
CheckOffEncodingCount(0);
CheckAnsEncodingCount(1);
}
TEST_F(JsepTrackTest, AudioOffSendrecvAnsSendonly)
{
Init(SdpMediaSection::kAudio);
mRecvAns = nullptr;
OfferAnswer();
CheckOffEncodingCount(0);
CheckAnsEncodingCount(1);
}
TEST_F(JsepTrackTest, VideoOffSendrecvAnsSendonly)
{
Init(SdpMediaSection::kVideo);
mRecvAns = nullptr;
OfferAnswer();
CheckOffEncodingCount(0);
CheckAnsEncodingCount(1);
}
static JsepTrack::JsConstraints
MakeConstraints(const std::string& rid, uint32_t maxBitrate)
{
JsepTrack::JsConstraints constraints;
constraints.rid = rid;
constraints.constraints.maxBr = maxBitrate;
return constraints;
}
TEST_F(JsepTrackTest, SimulcastRejected)
{
Init(SdpMediaSection::kVideo);
std::vector<JsepTrack::JsConstraints> constraints;
constraints.push_back(MakeConstraints("foo", 40000));
constraints.push_back(MakeConstraints("bar", 10000));
mSendOff->SetJsConstraints(constraints);
OfferAnswer();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(1);
}
TEST_F(JsepTrackTest, SimulcastPrevented)
{
Init(SdpMediaSection::kVideo);
std::vector<JsepTrack::JsConstraints> constraints;
constraints.push_back(MakeConstraints("foo", 40000));
constraints.push_back(MakeConstraints("bar", 10000));
mSendAns->SetJsConstraints(constraints);
OfferAnswer();
CheckOffEncodingCount(1);
CheckAnsEncodingCount(1);
}
TEST_F(JsepTrackTest, SimulcastOfferer)
{
Init(SdpMediaSection::kVideo);
std::vector<JsepTrack::JsConstraints> constraints;
constraints.push_back(MakeConstraints("foo", 40000));
constraints.push_back(MakeConstraints("bar", 10000));
mSendOff->SetJsConstraints(constraints);
CreateOffer();
CreateAnswer();
// Add simulcast/rid to answer
JsepTrack::AddToMsection(constraints, sdp::kRecv, &GetAnswer());
Negotiate();
ASSERT_TRUE(mSendOff->GetNegotiatedDetails());
ASSERT_EQ(2U, mSendOff->GetNegotiatedDetails()->GetEncodingCount());
ASSERT_EQ("foo", mSendOff->GetNegotiatedDetails()->GetEncoding(0).mRid);
ASSERT_EQ(40000U,
mSendOff->GetNegotiatedDetails()->GetEncoding(0).mConstraints.maxBr);
ASSERT_EQ("bar", mSendOff->GetNegotiatedDetails()->GetEncoding(1).mRid);
ASSERT_EQ(10000U,
mSendOff->GetNegotiatedDetails()->GetEncoding(1).mConstraints.maxBr);
}
TEST_F(JsepTrackTest, SimulcastAnswerer)
{
Init(SdpMediaSection::kVideo);
std::vector<JsepTrack::JsConstraints> constraints;
constraints.push_back(MakeConstraints("foo", 40000));
constraints.push_back(MakeConstraints("bar", 10000));
mSendAns->SetJsConstraints(constraints);
CreateOffer();
// Add simulcast/rid to offer
JsepTrack::AddToMsection(constraints, sdp::kRecv, &GetOffer());
CreateAnswer();
Negotiate();
ASSERT_TRUE(mSendAns->GetNegotiatedDetails());
ASSERT_EQ(2U, mSendAns->GetNegotiatedDetails()->GetEncodingCount());
ASSERT_EQ("foo", mSendAns->GetNegotiatedDetails()->GetEncoding(0).mRid);
ASSERT_EQ(40000U,
mSendAns->GetNegotiatedDetails()->GetEncoding(0).mConstraints.maxBr);
ASSERT_EQ("bar", mSendAns->GetNegotiatedDetails()->GetEncoding(1).mRid);
ASSERT_EQ(10000U,
mSendAns->GetNegotiatedDetails()->GetEncoding(1).mConstraints.maxBr);
}
#define VERIFY_OPUS_MAX_PLAYBACK_RATE(track, expectedRate) \
{ \
JsepTrack& copy(track); \
ASSERT_TRUE(copy.GetNegotiatedDetails()); \
ASSERT_TRUE(copy.GetNegotiatedDetails()->GetEncodingCount()); \
for (auto codec : copy.GetNegotiatedDetails()->GetEncoding(0).GetCodecs()) {\
if (codec->mName == "opus") { \
JsepAudioCodecDescription* audioCodec = \
static_cast<JsepAudioCodecDescription*>(codec); \
ASSERT_EQ((expectedRate), audioCodec->mMaxPlaybackRate); \
} \
}; \
}
#define VERIFY_OPUS_FORCE_MONO(track, expected) \
{ \
JsepTrack& copy(track); \
ASSERT_TRUE(copy.GetNegotiatedDetails()); \
ASSERT_TRUE(copy.GetNegotiatedDetails()->GetEncodingCount()); \
for (auto codec : copy.GetNegotiatedDetails()->GetEncoding(0).GetCodecs()) {\
if (codec->mName == "opus") { \
JsepAudioCodecDescription* audioCodec = \
static_cast<JsepAudioCodecDescription*>(codec); \
/* gtest has some compiler warnings when using ASSERT_EQ with booleans. */ \
ASSERT_EQ((int)(expected), (int)audioCodec->mForceMono); \
} \
}; \
}
TEST_F(JsepTrackTest, DefaultOpusParameters)
{
Init(SdpMediaSection::kAudio);
OfferAnswer();
VERIFY_OPUS_MAX_PLAYBACK_RATE(*mSendOff,
SdpFmtpAttributeList::OpusParameters::kDefaultMaxPlaybackRate);
VERIFY_OPUS_MAX_PLAYBACK_RATE(*mSendAns,
SdpFmtpAttributeList::OpusParameters::kDefaultMaxPlaybackRate);
VERIFY_OPUS_MAX_PLAYBACK_RATE(*mRecvOff, 0U);
VERIFY_OPUS_FORCE_MONO(*mRecvOff, false);
VERIFY_OPUS_MAX_PLAYBACK_RATE(*mRecvAns, 0U);
VERIFY_OPUS_FORCE_MONO(*mRecvAns, false);
}
TEST_F(JsepTrackTest, NonDefaultOpusParameters)
{
InitCodecs();
for (auto& codec : mAnsCodecs.values) {
if (codec->mName == "opus") {
JsepAudioCodecDescription* audioCodec =
static_cast<JsepAudioCodecDescription*>(codec);
audioCodec->mMaxPlaybackRate = 16000;
audioCodec->mForceMono = true;
}
}
InitTracks(SdpMediaSection::kAudio);
InitSdp(SdpMediaSection::kAudio);
OfferAnswer();
VERIFY_OPUS_MAX_PLAYBACK_RATE(*mSendOff, 16000U);
VERIFY_OPUS_FORCE_MONO(*mSendOff, true);
VERIFY_OPUS_MAX_PLAYBACK_RATE(*mSendAns,
SdpFmtpAttributeList::OpusParameters::kDefaultMaxPlaybackRate);
VERIFY_OPUS_FORCE_MONO(*mSendAns, false);
VERIFY_OPUS_MAX_PLAYBACK_RATE(*mRecvOff, 0U);
VERIFY_OPUS_FORCE_MONO(*mRecvOff, false);
VERIFY_OPUS_MAX_PLAYBACK_RATE(*mRecvAns, 16000U);
VERIFY_OPUS_FORCE_MONO(*mRecvAns, true);
}
} // namespace mozilla
int
main(int argc, char** argv)
{
// Prevents some log spew
ScopedXPCOM xpcom("jsep_track_unittest");
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}