/* * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include #include #include #include #include "rtp_rtcp.h" #include "common_types.h" #include "rtcp_utility.h" #include "tmmbr_help.h" #define TEST_STR "Test TMMBR." #define TEST_PASSED() std::cerr << TEST_STR << " : [OK]" << std::endl #define PRINT_LINE std::cout << "------------------------------------------" << std::endl; const int maxFileLen = 200; WebRtc_UWord8* dataFile[maxFileLen]; struct InputSet { WebRtc_UWord32 TMMBR; WebRtc_UWord32 packetOH; WebRtc_UWord32 SSRC; }; const InputSet set0 = {220, 80, 11111}; // bitRate, packetOH, ssrc const InputSet set1 = {180, 90, 22222}; const InputSet set2 = {100, 210, 33333}; const InputSet set3 = { 35, 40, 44444}; const InputSet set4 = { 40, 60, 55555}; const InputSet set4_1 = {100, 60, 55555}; const InputSet set4_2 = { 10, 60, 55555}; const InputSet set5 = {200, 40, 66666}; const InputSet set00 = { 0, 40, 66666}; const int maxBitrate = 230; // if this is lower than max in the list above test should fail void Verify(TMMBRSet* boundingSet, int index, InputSet set) { assert(boundingSet->ptrTmmbrSet[index] == set.TMMBR); assert(boundingSet->ptrPacketOHSet[index] == set.packetOH); assert(boundingSet->ptrSsrcSet[index] == set.SSRC); }; int ParseRTCPPacket(const void *data, int len, TMMBRSet*& boundingSet) { int numItems = -1; RTCPUtility::RTCPParserV2 rtcpParser((const WebRtc_UWord8*)data, len, true); RTCPUtility::RTCPPacketTypes pktType = rtcpParser.Begin(); while (pktType != RTCPUtility::kRtcpNotValidCode) { const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet(); if (pktType == RTCPUtility::kRtcpRtpfbTmmbnCode) { assert(0 == rtcpPacket.TMMBN.SenderSSRC); assert(0 == rtcpPacket.TMMBN.MediaSSRC); numItems = 0; } if (pktType == RTCPUtility::kRtcpRtpfbTmmbnItemCode) { boundingSet->ptrTmmbrSet[numItems] = rtcpPacket.TMMBNItem.MaxTotalMediaBitRate; boundingSet->ptrPacketOHSet[numItems] = rtcpPacket.TMMBNItem.MeasuredOverhead; boundingSet->ptrSsrcSet[numItems] = rtcpPacket.TMMBNItem.SSRC; ++numItems; } pktType = rtcpParser.Iterate(); } return numItems; }; WebRtc_Word32 GetFile(char* fileName) { if (!fileName[0]) { return 0; } FILE* openFile = fopen(fileName, "rb"); assert(openFile != NULL); fseek(openFile, 0, SEEK_END); int len = (WebRtc_Word16)(ftell(openFile)); rewind(openFile); assert(len > 0 && len < maxFileLen); fread(dataFile, 1, len, openFile); fclose(openFile); return len; }; class LoopBackTransport2 : public webrtc::Transport, private TMMBRHelp { public: LoopBackTransport2(RtpRtcp* rtpRtcpModule) : TMMBRHelp(false), _rtpRtcpModule(rtpRtcpModule), _cnt(0) { } virtual int SendPacket(int channel, const void *data, int len) { if( 0 == _rtpRtcpModule->IncomingPacket((const WebRtc_UWord8*)data, len)) { return len; } return -1; } virtual int SendRTCPPacket(int channel, const void *data, int len) { char fileName[256] = {0}; TMMBRSet* boundingSet = BoundingSet(); boundingSet->VerifyAndAllocateSet(3); if (_cnt == 0) { // TMMBN {} // TMMBN {} // TMMBN {} // TMMBN {2,4,0} -> {4,2} assert(2 == ParseRTCPPacket(data, len, boundingSet)); Verify(boundingSet, 0, set4); Verify(boundingSet, 1, set2); strcpy(fileName, "RTCPPacketTMMBR3.bin"); } ++_cnt; // Get stored rtcp packet w/ TMMBR len = GetFile(fileName); if (len == 0) { return 1; } // Send in bitrate request if(_rtpRtcpModule->IncomingPacket((const WebRtc_UWord8*)dataFile, len) == 0) { return len; } return -1; } RtpRtcp* _rtpRtcpModule; WebRtc_UWord32 _cnt; }; class LoopBackTransportVideo : public webrtc::Transport, private TMMBRHelp { public: LoopBackTransportVideo(RtpRtcp* rtpRtcpModule) : TMMBRHelp(false), _rtpRtcpModule(rtpRtcpModule), _cnt(0) { } virtual int SendPacket(int channel, const void *data, int len) { if(_rtpRtcpModule->IncomingPacket((const WebRtc_UWord8*)data, len)== 0) { return len; } return -1; } virtual int SendRTCPPacket(int channel, const void *data, int len) { char fileName[256] = {0}; TMMBRSet* boundingSet = BoundingSet(); boundingSet->VerifyAndAllocateSet(3); if (_cnt == 0) { strcpy(fileName, "RTCPPacketTMMBR0.bin"); } else if (_cnt == 1) { // TMMBN {0} -> {0} assert(1 == ParseRTCPPacket(data, len, boundingSet)); Verify(boundingSet, 0, set0); strcpy(fileName, "RTCPPacketTMMBR1.bin"); } else if (_cnt == 2) { // TMMBN {0,1} -> {1} assert(1 == ParseRTCPPacket(data, len, boundingSet)); Verify(boundingSet, 0, set1); strcpy(fileName, "RTCPPacketTMMBR2.bin"); } else if (_cnt == 3) { // TMMBN {0,1,2} -> {2} assert(1 == ParseRTCPPacket(data, len, boundingSet)); Verify(boundingSet, 0, set2); strcpy(fileName, "RTCPPacketTMMBR3.bin"); } else if (_cnt == 4) { // TMMBN {0,1,2,3} -> {3,2} assert(2 == ParseRTCPPacket(data, len, boundingSet)); Verify(boundingSet, 0, set3); Verify(boundingSet, 1, set2); strcpy(fileName, "RTCPPacketTMMBR4.bin"); } else if (_cnt == 5) { // TMMBN {0,1,2,3,4} -> {3,4,2} assert(3 == ParseRTCPPacket(data, len, boundingSet)); Verify(boundingSet, 0, set3); Verify(boundingSet, 1, set4); Verify(boundingSet, 2, set2); strcpy(fileName, "RTCPPacketTMMBR5.bin"); } else if (_cnt == 6) { // TMMBN {0,1,2,3,4,5} -> {3,4,2} assert(3 == ParseRTCPPacket(data, len, boundingSet)); Verify(boundingSet, 0, set3); Verify(boundingSet, 1, set4); Verify(boundingSet, 2, set2); strcpy(fileName, "RTCPPacketTMMBR4_2.bin"); } else if (_cnt == 7) { // TMMBN {0,1,2,3,4_2,5} -> {4_2} assert(1 == ParseRTCPPacket(data, len, boundingSet)); Verify(boundingSet, 0, set4_2); ++_cnt; ::Sleep(5*RTCP_INTERVAL_AUDIO_MS + 1000); // time out receiver _rtpRtcpModule->Process(); // SendRTCP() (_cnt == 8) // a receiver has timed out -> UpdateTMMBR() } else if (_cnt == 8) { // No TMMBN in this packet assert(-1 == ParseRTCPPacket(data, len, boundingSet)); } else if (_cnt == 10) { // TMMBN {} -> {}, empty set assert(0 == ParseRTCPPacket(data, len, boundingSet)); strcpy(fileName, "RTCPPacketTMMBR2.bin"); } else if (_cnt == 11) { // TMMBN {2} -> {2} assert(1 == ParseRTCPPacket(data, len, boundingSet)); Verify(boundingSet, 0, set2); } else if (_cnt == 12) // ----- multi module ------------- { // No TMMBN in this packet assert(-1 == ParseRTCPPacket(data, len, boundingSet)); strcpy(fileName, "RTCPPacketTMMBR4.bin"); } else if (_cnt == 13) { // TMMBN {} // TMMBN {} // TMMBN {} // TMMBN {2,4} -> {4,2} assert(2 == ParseRTCPPacket(data, len, boundingSet)); Verify(boundingSet, 0, set4); Verify(boundingSet, 1, set2); strcpy(fileName, "RTCPPacketTMMBR0.bin"); } else if (_cnt == 14) { // TMMBN {} // TMMBN {3} // TMMBN {} // TMMBN {2,4,0} -> {3,4,2} assert(3 == ParseRTCPPacket(data, len, boundingSet)); Verify(boundingSet, 0, set3); Verify(boundingSet, 1, set4); Verify(boundingSet, 2, set2); strcpy(fileName, "RTCPPacketTMMBR1.bin"); } //else if (_cnt == 15) //{ // // TMMBN {} // // TMMBN {} // // TMMBN {} // // TMMBN {2,4,0,1} -> {4,2} // //assert(2 == ParseRTCPPacket(data, len, boundingSet)); // //Verify(boundingSet, 0, set4); // //Verify(boundingSet, 1, set2); //} //else if (_cnt == 15) //{ // // No TMMBN in this packet // assert(-1 == ParseRTCPPacket(data, len, boundingSet)); //} else if (_cnt == 15) { // TMMBN {} // TMMBN {} // TMMBN {} // TMMBN {} -> {}, empty set assert(0 == ParseRTCPPacket(data, len, boundingSet)); } ++_cnt; // Get stored rtcp packet w/ TMMBR len = GetFile(fileName); if (len == 0) { return 1; } // Send in bitrate request if( 0 == _rtpRtcpModule->IncomingPacket((const WebRtc_UWord8*)dataFile, len)) { return len; } return -1; } RtpRtcp* _rtpRtcpModule; WebRtc_UWord32 _cnt; }; class TestTMMBR : private TMMBRHelp { public: TestTMMBR() : TMMBRHelp(false) {}; void Add(TMMBRSet* candidateSet, int index, InputSet set) { candidateSet->ptrTmmbrSet[index] = set.TMMBR; candidateSet->ptrPacketOHSet[index] = set.packetOH; candidateSet->ptrSsrcSet[index] = set.SSRC; }; void Start() { // Get sets TMMBRSet* candidateSet = CandidateSet(); assert(0 == candidateSet->sizeOfSet); TMMBRSet* boundingSet = BoundingSet(); assert(0 == boundingSet->sizeOfSet); TMMBRSet* boundingSetToSend = BoundingSetToSend(); assert(0 == boundingSetToSend->sizeOfSet); WebRtc_Word32 numBoundingSet = FindTMMBRBoundingSet(boundingSet); assert(0 == numBoundingSet); // should be empty assert( 0 == SetTMMBRBoundingSetToSend(NULL,0)); // ok to send empty set assert( 0 == SetTMMBRBoundingSetToSend(boundingSet,0)); // ok to send empty set WebRtc_UWord32 minBitrateKbit = 0; WebRtc_UWord32 maxBitrateKbit = 0; assert(-1 == CalcMinMaxBitRate(0, 0, 1, false, minBitrateKbit, maxBitrateKbit)); // no bounding set // --------------------------------- // Test candidate set {0} -> {0} // --------------------------------- candidateSet = VerifyAndAllocateCandidateSet(1); assert(1 == candidateSet->sizeOfSet); Add(candidateSet, 0, set0); // Find bounding set numBoundingSet = FindTMMBRBoundingSet(boundingSet); assert(1 == numBoundingSet); Verify(boundingSet, 0, set0); // Is owner of set assert(!IsOwner(set0.SSRC, 0)); // incorrect length assert(!IsOwner(set1.SSRC, 100)); // incorrect length assert( IsOwner(set0.SSRC, numBoundingSet)); assert(!IsOwner(set1.SSRC, numBoundingSet)); assert(!IsOwner(set2.SSRC, numBoundingSet)); // Set boundingSet to send assert(0 == SetTMMBRBoundingSetToSend(boundingSet, maxBitrate)); // Get boundingSet to send boundingSetToSend = BoundingSetToSend(); assert(boundingSetToSend->sizeOfSet == numBoundingSet); Verify(boundingSetToSend, 0, set0); // Get net bitrate depending on packet rate assert( 0 == CalcMinMaxBitRate(0, numBoundingSet, false,0, minBitrateKbit, maxBitrateKbit)); assert(set0.TMMBR == minBitrateKbit); assert(set0.TMMBR == maxBitrateKbit); assert(0 == CalcMinMaxBitRate(0, 100, false,0, minBitrateKbit, maxBitrateKbit)); // incorrect length assert(set0.TMMBR == minBitrateKbit); assert(set0.TMMBR == maxBitrateKbit); // --------------------------------- // Test candidate set {0,1} -> {1} // --------------------------------- candidateSet = VerifyAndAllocateCandidateSet(2); assert(2 == candidateSet->sizeOfSet); Add(candidateSet, 0, set0); Add(candidateSet, 1, set1); // Find bounding set numBoundingSet = FindTMMBRBoundingSet(boundingSet); assert(1 == numBoundingSet); Verify(boundingSet, 0, set1); // Is owner of set assert(!IsOwner(set0.SSRC, numBoundingSet)); assert( IsOwner(set1.SSRC, numBoundingSet)); assert(!IsOwner(set2.SSRC, numBoundingSet)); // Set boundingSet to send assert(0 == SetTMMBRBoundingSetToSend(boundingSet, maxBitrate)); // Get boundingSet to send boundingSetToSend = BoundingSetToSend(); assert(boundingSetToSend->sizeOfSet == numBoundingSet); Verify(boundingSetToSend, 0, set1); // Get net bitrate depending on packet rate assert(0 == CalcMinMaxBitRate(0, numBoundingSet, true,0, minBitrateKbit, maxBitrateKbit)); assert(set1.TMMBR == minBitrateKbit); assert(set0.TMMBR == maxBitrateKbit); // --------------------------------- // Test candidate set {0,1,2} -> {2} // --------------------------------- candidateSet = VerifyAndAllocateCandidateSet(3); assert(3 == candidateSet->sizeOfSet); Add(candidateSet, 0, set0); Add(candidateSet, 1, set1); Add(candidateSet, 2, set2); // Find bounding set numBoundingSet = FindTMMBRBoundingSet(boundingSet); assert(1 == numBoundingSet); Verify(boundingSet, 0, set2); // Is owner of set assert(!IsOwner(set0.SSRC, numBoundingSet)); assert(!IsOwner(set1.SSRC, numBoundingSet)); assert( IsOwner(set2.SSRC, numBoundingSet)); // Set boundingSet to send assert(0 == SetTMMBRBoundingSetToSend(boundingSet, maxBitrate)); // Get boundingSet to send boundingSetToSend = BoundingSetToSend(); assert(boundingSetToSend->sizeOfSet == numBoundingSet); Verify(boundingSetToSend, 0, set2); // Get net bitrate depending on packet rate assert(0 == CalcMinMaxBitRate(0, numBoundingSet, true,0, minBitrateKbit, maxBitrateKbit)); assert(set2.TMMBR == minBitrateKbit); assert(set0.TMMBR == maxBitrateKbit); // --------------------------------- // Test candidate set {0,1,2,3} -> {3,2} // --------------------------------- candidateSet = VerifyAndAllocateCandidateSet(4); assert(4 == candidateSet->sizeOfSet); Add(candidateSet, 0, set0); Add(candidateSet, 1, set1); Add(candidateSet, 2, set2); Add(candidateSet, 3, set3); // Find bounding set numBoundingSet = FindTMMBRBoundingSet(boundingSet); assert(2 == numBoundingSet); Verify(boundingSet, 0, set3); Verify(boundingSet, 1, set2); // Is owner of set assert(!IsOwner(set0.SSRC, numBoundingSet)); assert(!IsOwner(set1.SSRC, numBoundingSet)); assert( IsOwner(set2.SSRC, numBoundingSet)); assert( IsOwner(set3.SSRC, numBoundingSet)); // Set boundingSet to send assert(0 == SetTMMBRBoundingSetToSend(boundingSet, maxBitrate)); // Get boundingSet to send boundingSetToSend = BoundingSetToSend(); assert(boundingSetToSend->sizeOfSet == numBoundingSet); Verify(boundingSetToSend, 0, set3); Verify(boundingSetToSend, 1, set2); // Get net bitrate depending on packet rate assert(0 == CalcMinMaxBitRate(0, numBoundingSet, true,0, minBitrateKbit, maxBitrateKbit)); assert(set3.TMMBR == minBitrateKbit); assert(set0.TMMBR == maxBitrateKbit); // --------------------------------- // Test candidate set {0,1,2,3,4} -> {3,4,2} // --------------------------------- candidateSet = VerifyAndAllocateCandidateSet(5); assert(5 == candidateSet->sizeOfSet); Add(candidateSet, 0, set0); Add(candidateSet, 1, set1); Add(candidateSet, 2, set2); Add(candidateSet, 3, set3); Add(candidateSet, 4, set4); // Find bounding set numBoundingSet = FindTMMBRBoundingSet(boundingSet); assert(3 == numBoundingSet); Verify(boundingSet, 0, set3); Verify(boundingSet, 1, set4); Verify(boundingSet, 2, set2); // Is owner of set assert(!IsOwner(set0.SSRC, numBoundingSet)); assert(!IsOwner(set1.SSRC, numBoundingSet)); assert( IsOwner(set2.SSRC, numBoundingSet)); assert( IsOwner(set3.SSRC, numBoundingSet)); assert( IsOwner(set4.SSRC, numBoundingSet)); // Set boundingSet to send assert(0 == SetTMMBRBoundingSetToSend(boundingSet, maxBitrate)); // Get boundingSet to send boundingSetToSend = BoundingSetToSend(); assert(boundingSetToSend->sizeOfSet == numBoundingSet); Verify(boundingSetToSend, 0, set3); Verify(boundingSetToSend, 1, set4); Verify(boundingSetToSend, 2, set2); // Get net bitrate depending on packet rate assert(0 == CalcMinMaxBitRate(0,numBoundingSet, true,0, minBitrateKbit, maxBitrateKbit)); assert(set3.TMMBR == minBitrateKbit); assert(set0.TMMBR == maxBitrateKbit); // --------------------------------- // Test candidate set {0,1,2,3,4,5} -> {3,4,2} // --------------------------------- candidateSet = VerifyAndAllocateCandidateSet(6); assert(6 == candidateSet->sizeOfSet); Add(candidateSet, 0, set0); Add(candidateSet, 1, set1); Add(candidateSet, 2, set2); Add(candidateSet, 3, set3); Add(candidateSet, 4, set4); Add(candidateSet, 5, set5); // Find bounding set numBoundingSet = FindTMMBRBoundingSet(boundingSet); assert(3 == numBoundingSet); Verify(boundingSet, 0, set3); Verify(boundingSet, 1, set4); Verify(boundingSet, 2, set2); // Is owner of set assert(!IsOwner(set0.SSRC, numBoundingSet)); assert(!IsOwner(set1.SSRC, numBoundingSet)); assert( IsOwner(set2.SSRC, numBoundingSet)); assert( IsOwner(set3.SSRC, numBoundingSet)); assert( IsOwner(set4.SSRC, numBoundingSet)); assert(!IsOwner(set5.SSRC, numBoundingSet)); // Set boundingSet to send assert(0 == SetTMMBRBoundingSetToSend(boundingSet, maxBitrate)); // Get boundingSet to send boundingSetToSend = BoundingSetToSend(); assert(boundingSetToSend->sizeOfSet == numBoundingSet); Verify(boundingSetToSend, 0, set3); Verify(boundingSetToSend, 1, set4); Verify(boundingSetToSend, 2, set2); // Get net bitrate depending on packet rate assert(0 == CalcMinMaxBitRate(0,numBoundingSet, true,0, minBitrateKbit, maxBitrateKbit)); assert(set3.TMMBR == minBitrateKbit); assert(set0.TMMBR == maxBitrateKbit); // --------------------------------- // Test candidate set {1,2,3,4,5} -> {3,4,2} // --------------------------------- candidateSet = VerifyAndAllocateCandidateSet(5); assert(6 == candidateSet->sizeOfSet); Add(candidateSet, 0, set1); Add(candidateSet, 1, set2); Add(candidateSet, 2, set3); Add(candidateSet, 3, set4); Add(candidateSet, 4, set5); // Find bounding set numBoundingSet = FindTMMBRBoundingSet(boundingSet); assert(3 == numBoundingSet); Verify(boundingSet, 0, set3); Verify(boundingSet, 1, set4); Verify(boundingSet, 2, set2); // Is owner of set assert(!IsOwner(set0.SSRC, numBoundingSet)); assert(!IsOwner(set1.SSRC, numBoundingSet)); assert( IsOwner(set2.SSRC, numBoundingSet)); assert( IsOwner(set3.SSRC, numBoundingSet)); assert( IsOwner(set4.SSRC, numBoundingSet)); assert(!IsOwner(set5.SSRC, numBoundingSet)); // Set boundingSet to send assert(0 == SetTMMBRBoundingSetToSend(boundingSet, maxBitrate)); // Get boundingSet to send boundingSetToSend = BoundingSetToSend(); assert(boundingSetToSend->sizeOfSet == numBoundingSet); Verify(boundingSetToSend, 0, set3); Verify(boundingSetToSend, 1, set4); Verify(boundingSetToSend, 2, set2); // Get net bitrate depending on packet rate assert(0 == CalcMinMaxBitRate(0,numBoundingSet, true,0, minBitrateKbit, maxBitrateKbit)); assert(set3.TMMBR == minBitrateKbit); assert(set5.TMMBR == maxBitrateKbit); // --------------------------------- // Test candidate set {1,3,4,5} -> {3,4} // --------------------------------- candidateSet = VerifyAndAllocateCandidateSet(4); assert(6 == candidateSet->sizeOfSet); Add(candidateSet, 0, set1); Add(candidateSet, 1, set3); Add(candidateSet, 2, set4); Add(candidateSet, 3, set5); // Find bounding set numBoundingSet = FindTMMBRBoundingSet(boundingSet); assert(2 == numBoundingSet); Verify(boundingSet, 0, set3); Verify(boundingSet, 1, set4); // Is owner of set assert(!IsOwner(set0.SSRC, numBoundingSet)); assert(!IsOwner(set1.SSRC, numBoundingSet)); assert(!IsOwner(set2.SSRC, numBoundingSet)); assert( IsOwner(set3.SSRC, numBoundingSet)); assert( IsOwner(set4.SSRC, numBoundingSet)); assert(!IsOwner(set5.SSRC, numBoundingSet)); // Set boundingSet to send assert(0 == SetTMMBRBoundingSetToSend(boundingSet, maxBitrate)); // Get boundingSet to send boundingSetToSend = BoundingSetToSend(); Verify(boundingSetToSend, 0, set3); Verify(boundingSetToSend, 1, set4); // Get net bitrate depending on packet rate assert(0 == CalcMinMaxBitRate(0, numBoundingSet,true,0, minBitrateKbit, maxBitrateKbit)); assert(set3.TMMBR == minBitrateKbit); assert(set5.TMMBR == maxBitrateKbit); // --------------------------------- // Test candidate set {1,2,4,5} -> {4,2} // --------------------------------- candidateSet = VerifyAndAllocateCandidateSet(4); assert(6 == candidateSet->sizeOfSet); Add(candidateSet, 0, set1); Add(candidateSet, 1, set2); Add(candidateSet, 2, set4); Add(candidateSet, 3, set5); // Find bounding set numBoundingSet = FindTMMBRBoundingSet(boundingSet); assert(2 == numBoundingSet); Verify(boundingSet, 0, set4); Verify(boundingSet, 1, set2); // Is owner of set assert(!IsOwner(set0.SSRC, numBoundingSet)); assert(!IsOwner(set1.SSRC, numBoundingSet)); assert( IsOwner(set2.SSRC, numBoundingSet)); assert(!IsOwner(set3.SSRC, numBoundingSet)); assert( IsOwner(set4.SSRC, numBoundingSet)); assert(!IsOwner(set5.SSRC, numBoundingSet)); // Set boundingSet to send assert(0 == SetTMMBRBoundingSetToSend(boundingSet, maxBitrate)); // Get boundingSet to send boundingSetToSend = BoundingSetToSend(); Verify(boundingSetToSend, 0, set4); Verify(boundingSetToSend, 1, set2); // Get net bitrate depending on packet rate assert(0 == CalcMinMaxBitRate(0, numBoundingSet, true,0, minBitrateKbit, maxBitrateKbit)); assert(set4.TMMBR == minBitrateKbit); assert(set5.TMMBR == maxBitrateKbit); // --------------------------------- // Test candidate set {1,2,3,5} -> {3,2} // --------------------------------- candidateSet = VerifyAndAllocateCandidateSet(4); assert(6 == candidateSet->sizeOfSet); Add(candidateSet, 0, set1); Add(candidateSet, 1, set2); Add(candidateSet, 2, set3); Add(candidateSet, 3, set5); // Find bounding set numBoundingSet = FindTMMBRBoundingSet(boundingSet); assert(2 == numBoundingSet); Verify(boundingSet, 0, set3); Verify(boundingSet, 1, set2); // Is owner of set assert(!IsOwner(set0.SSRC, numBoundingSet)); assert(!IsOwner(set1.SSRC, numBoundingSet)); assert( IsOwner(set2.SSRC, numBoundingSet)); assert( IsOwner(set3.SSRC, numBoundingSet)); assert(!IsOwner(set4.SSRC, numBoundingSet)); assert(!IsOwner(set5.SSRC, numBoundingSet)); // Set boundingSet to send assert(0 == SetTMMBRBoundingSetToSend(boundingSet, maxBitrate)); // Get boundingSet to send boundingSetToSend = BoundingSetToSend(); Verify(boundingSetToSend, 0, set3); Verify(boundingSetToSend, 1, set2); // Get net bitrate depending on packet rate assert(0 == CalcMinMaxBitRate(0, numBoundingSet, true,0, minBitrateKbit, maxBitrateKbit)); assert(set3.TMMBR == minBitrateKbit); assert(set5.TMMBR == maxBitrateKbit); // --------------------------------- // Test candidate set {1,2,3,4_1,5} -> {3,2} // --------------------------------- candidateSet = VerifyAndAllocateCandidateSet(5); assert(6 == candidateSet->sizeOfSet); Add(candidateSet, 0, set1); Add(candidateSet, 1, set2); Add(candidateSet, 2, set3); Add(candidateSet, 3, set4_1); Add(candidateSet, 4, set5); // Find bounding set numBoundingSet = FindTMMBRBoundingSet(boundingSet); assert(2 == numBoundingSet); Verify(boundingSet, 0, set3); Verify(boundingSet, 1, set2); // Is owner of set assert(!IsOwner(set0.SSRC, numBoundingSet)); assert(!IsOwner(set1.SSRC, numBoundingSet)); assert( IsOwner(set2.SSRC, numBoundingSet)); assert( IsOwner(set3.SSRC, numBoundingSet)); assert(!IsOwner(set4.SSRC, numBoundingSet)); assert(!IsOwner(set5.SSRC, numBoundingSet)); // Set boundingSet to send assert(0 == SetTMMBRBoundingSetToSend(boundingSet, maxBitrate)); // Get boundingSet to send boundingSetToSend = BoundingSetToSend(); Verify(boundingSetToSend, 0, set3); Verify(boundingSetToSend, 1, set2); // Get net bitrate depending on packet rate assert(0 == CalcMinMaxBitRate(0, numBoundingSet, true,0, minBitrateKbit, maxBitrateKbit)); assert(set3.TMMBR == minBitrateKbit); assert(set5.TMMBR == maxBitrateKbit); // --------------------------------- // Test candidate set {1,2,3,4_2,5} -> {4_2} // --------------------------------- candidateSet = VerifyAndAllocateCandidateSet(5); assert(6 == candidateSet->sizeOfSet); Add(candidateSet, 0, set1); Add(candidateSet, 1, set2); Add(candidateSet, 2, set3); Add(candidateSet, 3, set4_2); Add(candidateSet, 4, set5); // Find bounding set numBoundingSet = FindTMMBRBoundingSet(boundingSet); assert(1 == numBoundingSet); Verify(boundingSet, 0, set4_2); // Is owner of set assert(!IsOwner(set0.SSRC, numBoundingSet)); assert(!IsOwner(set1.SSRC, numBoundingSet)); assert(!IsOwner(set2.SSRC, numBoundingSet)); assert(!IsOwner(set3.SSRC, numBoundingSet)); assert( IsOwner(set4.SSRC, numBoundingSet)); assert(!IsOwner(set5.SSRC, numBoundingSet)); // Set boundingSet to send assert(0 == SetTMMBRBoundingSetToSend(boundingSet, maxBitrate)); // Get boundingSet to send boundingSetToSend = BoundingSetToSend(); Verify(boundingSetToSend, 0, set4_2); // Get net bitrate depending on packet rate assert(0 == CalcMinMaxBitRate(0, numBoundingSet, true,0, minBitrateKbit, maxBitrateKbit)); assert(MIN_VIDEO_BW_MANAGEMENT_BITRATE == minBitrateKbit); assert(set5.TMMBR == maxBitrateKbit); // --------------------------------- // Test candidate set {} -> {} // --------------------------------- candidateSet = VerifyAndAllocateCandidateSet(0); assert(6 == candidateSet->sizeOfSet); // Find bounding set numBoundingSet = FindTMMBRBoundingSet(boundingSet); assert(0 == numBoundingSet); // Is owner of set assert(!IsOwner(set0.SSRC, numBoundingSet)); assert(!IsOwner(set1.SSRC, numBoundingSet)); assert(!IsOwner(set2.SSRC, numBoundingSet)); assert(!IsOwner(set3.SSRC, numBoundingSet)); assert(!IsOwner(set4.SSRC, numBoundingSet)); assert(!IsOwner(set5.SSRC, numBoundingSet)); // Set boundingSet to send assert(0 == SetTMMBRBoundingSetToSend(boundingSet, maxBitrate)); // Get boundingSet to send boundingSetToSend = BoundingSetToSend(); // Get net bitrate depending on packet rate assert(-1 == CalcMinMaxBitRate(0,numBoundingSet, true,0, minBitrateKbit, maxBitrateKbit)); // --------------------------------- // Test candidate set {x0,5} -> {5} // --------------------------------- candidateSet = VerifyAndAllocateCandidateSet(2); assert(6 == candidateSet->sizeOfSet); Add(candidateSet, 0, set00); Add(candidateSet, 1, set5); // Find bounding set numBoundingSet = FindTMMBRBoundingSet(boundingSet); assert(1 == numBoundingSet); Verify(boundingSet, 0, set5); // Is owner of set assert(!IsOwner(set0.SSRC, numBoundingSet)); assert(!IsOwner(set1.SSRC, numBoundingSet)); assert(!IsOwner(set2.SSRC, numBoundingSet)); assert(!IsOwner(set3.SSRC, numBoundingSet)); assert(!IsOwner(set4.SSRC, numBoundingSet)); assert( IsOwner(set5.SSRC, numBoundingSet)); // Set boundingSet to send assert(0 == SetTMMBRBoundingSetToSend(boundingSet, maxBitrate)); // Get boundingSet to send boundingSetToSend = BoundingSetToSend(); Verify(boundingSetToSend, 0, set5); // Get net bitrate depending on packet rate assert(0 == CalcMinMaxBitRate(0,numBoundingSet, true,0, minBitrateKbit, maxBitrateKbit)); assert(set5.TMMBR == minBitrateKbit); assert(set5.TMMBR == maxBitrateKbit); // --------------------------------- // Test candidate set {x0,4,2} -> {4,2} // --------------------------------- candidateSet = VerifyAndAllocateCandidateSet(3); assert(6 == candidateSet->sizeOfSet); Add(candidateSet, 0, set00); Add(candidateSet, 1, set4); Add(candidateSet, 2, set2); // Find bounding set numBoundingSet = FindTMMBRBoundingSet(boundingSet); assert(2 == numBoundingSet); Verify(boundingSet, 0, set4); Verify(boundingSet, 1, set2); // Is owner of set assert(!IsOwner(set0.SSRC, numBoundingSet)); assert(!IsOwner(set1.SSRC, numBoundingSet)); assert( IsOwner(set2.SSRC, numBoundingSet)); assert(!IsOwner(set3.SSRC, numBoundingSet)); assert( IsOwner(set4.SSRC, numBoundingSet)); assert(!IsOwner(set5.SSRC, numBoundingSet)); // Set boundingSet to send assert(0 == SetTMMBRBoundingSetToSend(boundingSet, maxBitrate)); // Get boundingSet to send boundingSetToSend = BoundingSetToSend(); Verify(boundingSetToSend, 0, set4); Verify(boundingSetToSend, 1, set2); // Get net bitrate depending on packet rate assert(0 == CalcMinMaxBitRate(0,numBoundingSet, true,0, minBitrateKbit, maxBitrateKbit)); assert(set4.TMMBR == minBitrateKbit); assert(set2.TMMBR == maxBitrateKbit); }; }; class NULLDataZink: public RtpData { virtual WebRtc_Word32 OnReceivedPayloadData(const WebRtc_UWord8* payloadData, const WebRtc_UWord16 payloadSize, const webrtc::WebRtcRTPHeader* rtpHeader, const WebRtc_UWord8* incomingRtpPacket, const WebRtc_UWord16 incomingRtpPacketLengt) { return 0; }; }; int _tmain(int argc, _TCHAR* argv[]) { std::string str; std::cout << "------------------------" << std::endl; std::cout << "------ Test TMMBR ------" << std::endl; std::cout << "------------------------" << std::endl; std::cout << " " << std::endl; // -------------------- // Test TMMBRHelp class // -------------------- TestTMMBR test; test.Start(); printf("TMMBRHelp-class test done.\n"); // ------------------------ // Test TMMBR single module // ------------------------ RtpRtcp* rtpRtcpModuleVideo = RtpRtcp::CreateRtpRtcp(0, false); LoopBackTransportVideo* myLoopBackTransportVideo = new LoopBackTransportVideo(rtpRtcpModuleVideo); assert(0 == rtpRtcpModuleVideo->RegisterSendTransport(myLoopBackTransportVideo)); assert(false == rtpRtcpModuleVideo->TMMBR()); rtpRtcpModuleVideo->SetTMMBRStatus(true); assert(true == rtpRtcpModuleVideo->TMMBR()); assert(0 == rtpRtcpModuleVideo->RegisterSendPayload( "I420", 96)); assert(0 == rtpRtcpModuleVideo->RegisterReceivePayload( "I420", 96)); // send a RTP packet with SSRC 11111 to get 11111 as the received SSRC assert(0 == rtpRtcpModuleVideo->SetSSRC(11111)); const WebRtc_UWord8 testStream[9] = "testtest"; assert(0 == rtpRtcpModuleVideo->RegisterIncomingDataCallback(new NULLDataZink())); // needed to avoid error from parsing the incoming stream assert(0 == rtpRtcpModuleVideo->SendOutgoingData(webrtc::kVideoFrameKey,96, 0, testStream, 8)); // set the SSRC to 0 assert(0 == rtpRtcpModuleVideo->SetSSRC(0)); // assert(0 == rtpRtcpModuleVideo->SetRTCPStatus(kRtcpCompound)); assert(0 == rtpRtcpModuleVideo->SendRTCP()); // -> incoming TMMBR {0} // should this make us remember a TMMBR? assert(0 == rtpRtcpModuleVideo->SendRTCP()); // -> incoming TMMBR {1}, verify TMMBN {0} assert(0 == rtpRtcpModuleVideo->SendRTCP()); // -> incoming TMMBR {2}, verify TMMBN {1} assert(0 == rtpRtcpModuleVideo->SendRTCP()); // -> incoming TMMBR {3}, verify TMMBN {2} assert(0 == rtpRtcpModuleVideo->SendRTCP()); // -> incoming TMMBR {4}, verify TMMBN {3,2} assert(0 == rtpRtcpModuleVideo->SendRTCP()); // -> incoming TMMBR {5}, verify TMMBN {3,4,2} assert(0 == rtpRtcpModuleVideo->SendRTCP()); // -> incoming TMMBR {4_2}, verify TMMBN {3,4,2} assert(0 == rtpRtcpModuleVideo->SendRTCP()); // -> time out receivers, verify TMMBN {4_2} assert(0 == rtpRtcpModuleVideo->SendRTCP()); // -> incoming TMMBR {2} assert(0 == rtpRtcpModuleVideo->SendRTCP()); // -> verify TMMBN {2} printf("Single module test done.\n"); // ------------------------ // Test TMMBR multi module // ------------------------ RtpRtcp* rtpRtcpModuleVideoDef = RtpRtcp::CreateRtpRtcp(10, false); assert(0 == rtpRtcpModuleVideo->RegisterDefaultModule(rtpRtcpModuleVideoDef)); RtpRtcp* rtpRtcpModuleVideo1 = RtpRtcp::CreateRtpRtcp(1, false); assert(0 == rtpRtcpModuleVideo1->RegisterDefaultModule(rtpRtcpModuleVideoDef)); RtpRtcp* rtpRtcpModuleVideo2 = RtpRtcp::CreateRtpRtcp(2, false); assert(0 == rtpRtcpModuleVideo2->RegisterDefaultModule(rtpRtcpModuleVideoDef)); RtpRtcp* rtpRtcpModuleVideo3 = RtpRtcp::CreateRtpRtcp(3, false); assert(0 == rtpRtcpModuleVideo3->RegisterDefaultModule(rtpRtcpModuleVideoDef)); LoopBackTransport2* myLoopBackTransport2 = new LoopBackTransport2(rtpRtcpModuleVideo2); assert(0 == rtpRtcpModuleVideo2->RegisterSendTransport(myLoopBackTransport2)); assert(0 == rtpRtcpModuleVideo2->SetRTCPStatus(kRtcpCompound)); // set the SSRC to 0 assert(0 == rtpRtcpModuleVideo2->SetSSRC(0)); assert(0 == rtpRtcpModuleVideo->SendRTCP()); // -> incoming TMMBR {4}, verify no TMMBN in this packet assert(0 == rtpRtcpModuleVideo->SendRTCP()); // -> incoming TMMBR {0}, verify TMMBN {4,2} assert(0 == rtpRtcpModuleVideo2->SendRTCP()); // -> incoming TMMBR {3}, verify TMMBN {4,2} assert(0 == rtpRtcpModuleVideo->SendRTCP()); // -> incoming TMMBR {1}, verify TMMBN {3,4,2} ::Sleep(5*RTCP_INTERVAL_AUDIO_MS + 1000); rtpRtcpModuleVideo2->Process(); // time out receiver2 -> UpdateTMMBR() assert(0 == rtpRtcpModuleVideo->SendRTCP()); // verify TMMBN {} printf("Multi module test done.\n"); RtpRtcp::DestroyRtpRtcp(rtpRtcpModuleVideo); RtpRtcp::DestroyRtpRtcp(rtpRtcpModuleVideo1); RtpRtcp::DestroyRtpRtcp(rtpRtcpModuleVideo2); RtpRtcp::DestroyRtpRtcp(rtpRtcpModuleVideo3); RtpRtcp::DestroyRtpRtcp(rtpRtcpModuleVideoDef); TEST_PASSED(); ::Sleep(5000); return 0; }