diff --git a/webrtc/modules/video_coding/frame_buffer2.cc b/webrtc/modules/video_coding/frame_buffer2.cc index e02e5b6071..bf1760ec27 100644 --- a/webrtc/modules/video_coding/frame_buffer2.cc +++ b/webrtc/modules/video_coding/frame_buffer2.cc @@ -19,6 +19,7 @@ #include "webrtc/modules/video_coding/jitter_estimator.h" #include "webrtc/modules/video_coding/timing.h" #include "webrtc/system_wrappers/include/clock.h" +#include "webrtc/system_wrappers/include/metrics.h" namespace webrtc { namespace video_coding { @@ -44,7 +45,13 @@ FrameBuffer::FrameBuffer(Clock* clock, num_frames_history_(0), num_frames_buffered_(0), stopped_(false), - protection_mode_(kProtectionNack) {} + protection_mode_(kProtectionNack), + num_total_frames_(0), + num_key_frames_(0) {} + +FrameBuffer::~FrameBuffer() { + UpdateHistograms(); +} FrameBuffer::ReturnReason FrameBuffer::NextFrame( int64_t max_wait_time_ms, @@ -155,6 +162,10 @@ int FrameBuffer::InsertFrame(std::unique_ptr frame) { rtc::CritScope lock(&crit_); RTC_DCHECK(frame); + ++num_total_frames_; + if (frame->num_references == 0) + ++num_key_frames_; + FrameKey key(frame->picture_id, frame->spatial_layer); int last_continuous_picture_id = last_continuous_frame_it_ == frames_.end() @@ -353,5 +364,16 @@ bool FrameBuffer::UpdateFrameInfoWithIncomingFrame(const FrameObject& frame, return true; } +void FrameBuffer::UpdateHistograms() const { + rtc::CritScope lock(&crit_); + if (num_total_frames_ > 0) { + int key_frames_permille = (static_cast(num_key_frames_) * 1000.0f / + static_cast(num_total_frames_) + + 0.5f); + RTC_HISTOGRAM_COUNTS_1000("WebRTC.Video.KeyFramesReceivedInPermille", + key_frames_permille); + } +} + } // namespace video_coding } // namespace webrtc diff --git a/webrtc/modules/video_coding/frame_buffer2.h b/webrtc/modules/video_coding/frame_buffer2.h index 8f726d0d86..7a5326b1fa 100644 --- a/webrtc/modules/video_coding/frame_buffer2.h +++ b/webrtc/modules/video_coding/frame_buffer2.h @@ -41,6 +41,8 @@ class FrameBuffer { VCMJitterEstimator* jitter_estimator, VCMTiming* timing); + virtual ~FrameBuffer(); + // Insert a frame into the frame buffer. Returns the picture id // of the last continuous frame or -1 if there is no continuous frame. int InsertFrame(std::unique_ptr frame); @@ -137,6 +139,8 @@ class FrameBuffer { FrameMap::iterator info) EXCLUSIVE_LOCKS_REQUIRED(crit_); + void UpdateHistograms() const; + FrameMap frames_ GUARDED_BY(crit_); rtc::CriticalSection crit_; @@ -151,6 +155,8 @@ class FrameBuffer { int num_frames_buffered_ GUARDED_BY(crit_); bool stopped_ GUARDED_BY(crit_); VCMVideoProtection protection_mode_ GUARDED_BY(crit_); + int num_total_frames_ GUARDED_BY(crit_); + int num_key_frames_ GUARDED_BY(crit_); RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(FrameBuffer); }; diff --git a/webrtc/modules/video_coding/frame_object.cc b/webrtc/modules/video_coding/frame_object.cc index 4eb8aeea53..0dd06abf2e 100644 --- a/webrtc/modules/video_coding/frame_object.cc +++ b/webrtc/modules/video_coding/frame_object.cc @@ -8,6 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ +#include "webrtc/base/checks.h" #include "webrtc/modules/video_coding/frame_object.h" #include "webrtc/modules/video_coding/packet_buffer.h" @@ -32,39 +33,50 @@ RtpFrameObject::RtpFrameObject(PacketBuffer* packet_buffer, last_seq_num_(last_seq_num), received_time_(received_time), times_nacked_(times_nacked) { - VCMPacket* packet = packet_buffer_->GetPacket(first_seq_num); - if (packet) { - // RtpFrameObject members - frame_type_ = packet->frameType; - codec_type_ = packet->codec; + VCMPacket* first_packet = packet_buffer_->GetPacket(first_seq_num); + RTC_DCHECK(first_packet); - // TODO(philipel): Remove when encoded image is replaced by FrameObject. - // VCMEncodedFrame members - CopyCodecSpecific(&packet->video_header); - _completeFrame = true; - _payloadType = packet->payloadType; - _timeStamp = packet->timestamp; - ntp_time_ms_ = packet->ntp_time_ms_; + // RtpFrameObject members + frame_type_ = first_packet->frameType; + codec_type_ = first_packet->codec; - // Since FFmpeg use an optimized bitstream reader that reads in chunks of - // 32/64 bits we have to add at least that much padding to the buffer - // to make sure the decoder doesn't read out of bounds. - // NOTE! EncodedImage::_size is the size of the buffer (think capacity of - // an std::vector) and EncodedImage::_length is the actual size of - // the bitstream (think size of an std::vector). - if (codec_type_ == kVideoCodecH264) - _size = frame_size + EncodedImage::kBufferPaddingBytesH264; - else - _size = frame_size; + // TODO(philipel): Remove when encoded image is replaced by FrameObject. + // VCMEncodedFrame members + CopyCodecSpecific(&first_packet->video_header); + _completeFrame = true; + _payloadType = first_packet->payloadType; + _timeStamp = first_packet->timestamp; + ntp_time_ms_ = first_packet->ntp_time_ms_; - _buffer = new uint8_t[_size]; - _length = frame_size; - _frameType = packet->frameType; - GetBitstream(_buffer); + // Since FFmpeg use an optimized bitstream reader that reads in chunks of + // 32/64 bits we have to add at least that much padding to the buffer + // to make sure the decoder doesn't read out of bounds. + // NOTE! EncodedImage::_size is the size of the buffer (think capacity of + // an std::vector) and EncodedImage::_length is the actual size of + // the bitstream (think size of an std::vector). + if (codec_type_ == kVideoCodecH264) + _size = frame_size + EncodedImage::kBufferPaddingBytesH264; + else + _size = frame_size; - // FrameObject members - timestamp = packet->timestamp; - } + _buffer = new uint8_t[_size]; + _length = frame_size; + _frameType = first_packet->frameType; + GetBitstream(_buffer); + + // FrameObject members + timestamp = first_packet->timestamp; + + VCMPacket* last_packet = packet_buffer_->GetPacket(last_seq_num); + RTC_DCHECK(last_packet && last_packet->markerBit); + // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/ + // ts_126114v120700p.pdf Section 7.4.5. + // The MTSI client shall add the payload bytes as defined in this clause + // onto the last RTP packet in each group of packets which make up a key + // frame (I-frame or IDR frame in H.264 (AVC), or an IRAP picture in H.265 + // (HEVC)). + rotation_ = last_packet->video_header.rotation; + _rotation_set = true; } RtpFrameObject::~RtpFrameObject() { diff --git a/webrtc/modules/video_coding/rtp_frame_reference_finder.cc b/webrtc/modules/video_coding/rtp_frame_reference_finder.cc index 5a9420a847..3d5283378f 100644 --- a/webrtc/modules/video_coding/rtp_frame_reference_finder.cc +++ b/webrtc/modules/video_coding/rtp_frame_reference_finder.cc @@ -43,7 +43,6 @@ void RtpFrameReferenceFinder::ManageFrame( case kVideoCodecFlexfec: case kVideoCodecULPFEC: case kVideoCodecRED: - case kVideoCodecUnknown: RTC_NOTREACHED(); break; case kVideoCodecVP8: @@ -52,6 +51,11 @@ void RtpFrameReferenceFinder::ManageFrame( case kVideoCodecVP9: ManageFrameVp9(std::move(frame)); break; + // Since the EndToEndTests use kVicdeoCodecUnknow we treat it the same as + // kVideoCodecGeneric. + // TODO(philipel): Take a look at the EndToEndTests and see if maybe they + // should be changed to use kVideoCodecGeneric instead. + case kVideoCodecUnknown: case kVideoCodecH264: case kVideoCodecI420: case kVideoCodecGeneric: diff --git a/webrtc/modules/video_coding/rtp_frame_reference_finder_unittest.cc b/webrtc/modules/video_coding/rtp_frame_reference_finder_unittest.cc index 928785c107..551b06b265 100644 --- a/webrtc/modules/video_coding/rtp_frame_reference_finder_unittest.cc +++ b/webrtc/modules/video_coding/rtp_frame_reference_finder_unittest.cc @@ -83,8 +83,12 @@ class TestRtpFrameReferenceFinder : public ::testing::Test, packet.codec = kVideoCodecGeneric; packet.seqNum = seq_num_start; packet.frameType = keyframe ? kVideoFrameKey : kVideoFrameDelta; - ref_packet_buffer_->InsertPacket(packet); + + packet.seqNum = seq_num_end; + packet.markerBit = true; + ref_packet_buffer_->InsertPacket(packet); + std::unique_ptr frame(new RtpFrameObject( ref_packet_buffer_, seq_num_start, seq_num_end, 0, 0, 0)); reference_finder_->ManageFrame(std::move(frame)); @@ -100,13 +104,20 @@ class TestRtpFrameReferenceFinder : public ::testing::Test, VCMPacket packet; packet.codec = kVideoCodecVP8; packet.seqNum = seq_num_start; + packet.markerBit = (seq_num_start == seq_num_end); packet.frameType = keyframe ? kVideoFrameKey : kVideoFrameDelta; packet.video_header.codecHeader.VP8.pictureId = pid % (1 << 15); packet.video_header.codecHeader.VP8.temporalIdx = tid; packet.video_header.codecHeader.VP8.tl0PicIdx = tl0; packet.video_header.codecHeader.VP8.layerSync = sync; - ref_packet_buffer_->InsertPacket(packet); + + if (seq_num_start != seq_num_end) { + packet.seqNum = seq_num_end; + packet.markerBit = true; + ref_packet_buffer_->InsertPacket(packet); + } + std::unique_ptr frame(new RtpFrameObject( ref_packet_buffer_, seq_num_start, seq_num_end, 0, 0, 0)); reference_finder_->ManageFrame(std::move(frame)); @@ -125,6 +136,7 @@ class TestRtpFrameReferenceFinder : public ::testing::Test, packet.timestamp = pid; packet.codec = kVideoCodecVP9; packet.seqNum = seq_num_start; + packet.markerBit = (seq_num_start == seq_num_end); packet.frameType = keyframe ? kVideoFrameKey : kVideoFrameDelta; packet.video_header.codecHeader.VP9.flexible_mode = false; packet.video_header.codecHeader.VP9.picture_id = pid % (1 << 15); @@ -136,8 +148,15 @@ class TestRtpFrameReferenceFinder : public ::testing::Test, packet.video_header.codecHeader.VP9.ss_data_available = true; packet.video_header.codecHeader.VP9.gof = *ss; } - ref_packet_buffer_->InsertPacket(packet); + + if (seq_num_start != seq_num_end) { + packet.markerBit = true; + packet.video_header.codecHeader.VP9.ss_data_available = false; + packet.seqNum = seq_num_end; + ref_packet_buffer_->InsertPacket(packet); + } + std::unique_ptr frame(new RtpFrameObject( ref_packet_buffer_, seq_num_start, seq_num_end, 0, 0, 0)); reference_finder_->ManageFrame(std::move(frame)); @@ -156,6 +175,7 @@ class TestRtpFrameReferenceFinder : public ::testing::Test, packet.timestamp = pid; packet.codec = kVideoCodecVP9; packet.seqNum = seq_num_start; + packet.markerBit = (seq_num_start == seq_num_end); packet.frameType = keyframe ? kVideoFrameKey : kVideoFrameDelta; packet.video_header.codecHeader.VP9.inter_layer_predicted = inter; packet.video_header.codecHeader.VP9.flexible_mode = true; @@ -166,8 +186,14 @@ class TestRtpFrameReferenceFinder : public ::testing::Test, packet.video_header.codecHeader.VP9.num_ref_pics = refs.size(); for (size_t i = 0; i < refs.size(); ++i) packet.video_header.codecHeader.VP9.pid_diff[i] = refs[i]; - ref_packet_buffer_->InsertPacket(packet); + + if (seq_num_start != seq_num_end) { + packet.seqNum = seq_num_end; + packet.markerBit = true; + ref_packet_buffer_->InsertPacket(packet); + } + std::unique_ptr frame(new RtpFrameObject( ref_packet_buffer_, seq_num_start, seq_num_end, 0, 0, 0)); reference_finder_->ManageFrame(std::move(frame)); @@ -1233,6 +1259,7 @@ TEST_F(TestRtpFrameReferenceFinder, Vp9PidFix_PidJumpsBackwardThenForward) { packet.timestamp = 0; packet.codec = kVideoCodecVP9; packet.frameType = kVideoFrameKey; + packet.markerBit = true; packet.video_header.codecHeader.VP9.flexible_mode = false; packet.video_header.codecHeader.VP9.picture_id = 1; packet.video_header.codecHeader.VP9.temporal_idx = 0; @@ -1286,6 +1313,7 @@ TEST_F(TestRtpFrameReferenceFinder, Vp9PidFix_Tl0JumpsBackwardThenForward) { packet.timestamp = 0; packet.codec = kVideoCodecVP9; packet.frameType = kVideoFrameKey; + packet.markerBit = true; packet.video_header.codecHeader.VP9.flexible_mode = false; packet.video_header.codecHeader.VP9.picture_id = 0; packet.video_header.codecHeader.VP9.temporal_idx = 0; @@ -1351,6 +1379,7 @@ TEST_F(TestRtpFrameReferenceFinder, Vp9PidFix_PidSmallJumpForward) { packet.timestamp = 0; packet.codec = kVideoCodecVP9; packet.frameType = kVideoFrameKey; + packet.markerBit = true; packet.video_header.codecHeader.VP9.flexible_mode = false; packet.video_header.codecHeader.VP9.picture_id = 1; packet.video_header.codecHeader.VP9.temporal_idx = 0; @@ -1413,6 +1442,7 @@ TEST_F(TestRtpFrameReferenceFinder, Vp9PidFix_DropOldFrame) { packet.timestamp = 0; packet.codec = kVideoCodecVP9; packet.frameType = kVideoFrameKey; + packet.markerBit = true; packet.video_header.codecHeader.VP9.flexible_mode = false; packet.video_header.codecHeader.VP9.picture_id = 1; packet.video_header.codecHeader.VP9.temporal_idx = 0; diff --git a/webrtc/modules/video_coding/video_receiver.cc b/webrtc/modules/video_coding/video_receiver.cc index 46373ef6cb..7395840feb 100644 --- a/webrtc/modules/video_coding/video_receiver.cc +++ b/webrtc/modules/video_coding/video_receiver.cc @@ -295,6 +295,15 @@ int32_t VideoReceiver::Decode(uint16_t maxWaitTimeMs) { // VCMEncodedFrame with FrameObject. int32_t VideoReceiver::Decode(const webrtc::VCMEncodedFrame* frame) { rtc::CritScope lock(&receive_crit_); + if (pre_decode_image_callback_) { + EncodedImage encoded_image(frame->EncodedImage()); + int qp = -1; + if (qp_parser_.GetQp(*frame, &qp)) { + encoded_image.qp_ = qp; + } + pre_decode_image_callback_->OnEncodedImage(encoded_image, + frame->CodecSpecific(), nullptr); + } return Decode(*frame); } diff --git a/webrtc/video/end_to_end_tests.cc b/webrtc/video/end_to_end_tests.cc index e88977abdd..cf8d5d099f 100644 --- a/webrtc/video/end_to_end_tests.cc +++ b/webrtc/video/end_to_end_tests.cc @@ -42,9 +42,11 @@ #include "webrtc/test/encoder_settings.h" #include "webrtc/test/fake_decoder.h" #include "webrtc/test/fake_encoder.h" +#include "webrtc/test/field_trial.h" #include "webrtc/test/frame_generator.h" #include "webrtc/test/frame_generator_capturer.h" #include "webrtc/test/gtest.h" +#include "webrtc/test/gmock.h" #include "webrtc/test/null_transport.h" #include "webrtc/test/rtcp_packet_parser.h" #include "webrtc/test/rtp_rtcp_observer.h" @@ -55,11 +57,17 @@ namespace webrtc { +namespace { +const char new_jb_enabled[] = "WebRTC-NewVideoJitterBuffer/Enabled/"; +const char new_jb_disabled[] = "WebRTC-NewVideoJitterBuffer/Disabled/"; +} // anonymous namespace + static const int kSilenceTimeoutMs = 2000; -class EndToEndTest : public test::CallTest { +class EndToEndTest : public test::CallTest, + public ::testing::WithParamInterface { public: - EndToEndTest() {} + EndToEndTest() : scoped_field_trial_(GetParam()) {} virtual ~EndToEndTest() { EXPECT_EQ(nullptr, video_send_stream_); @@ -128,9 +136,14 @@ class EndToEndTest : public test::CallTest { void VerifyNewVideoReceiveStreamsRespectNetworkState( MediaType network_to_bring_up, Transport* transport); + test::ScopedFieldTrials scoped_field_trial_; }; -TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) { +INSTANTIATE_TEST_CASE_P(TestWithNewVideoJitterBuffer, + EndToEndTest, + ::testing::Values(new_jb_enabled, new_jb_disabled)); + +TEST_P(EndToEndTest, ReceiverCanBeStartedTwice) { CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_)); test::NullTransport transport; @@ -145,7 +158,7 @@ TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) { DestroyStreams(); } -TEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) { +TEST_P(EndToEndTest, ReceiverCanBeStoppedTwice) { CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_)); test::NullTransport transport; @@ -160,7 +173,7 @@ TEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) { DestroyStreams(); } -TEST_F(EndToEndTest, ReceiverCanBeStoppedAndRestarted) { +TEST_P(EndToEndTest, ReceiverCanBeStoppedAndRestarted) { CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_)); test::NullTransport transport; @@ -176,7 +189,7 @@ TEST_F(EndToEndTest, ReceiverCanBeStoppedAndRestarted) { DestroyStreams(); } -TEST_F(EndToEndTest, RendersSingleDelayedFrame) { +TEST_P(EndToEndTest, RendersSingleDelayedFrame) { static const int kWidth = 320; static const int kHeight = 240; // This constant is chosen to be higher than the timeout in the video_render @@ -249,7 +262,7 @@ TEST_F(EndToEndTest, RendersSingleDelayedFrame) { DestroyStreams(); } -TEST_F(EndToEndTest, TransmitsFirstFrame) { +TEST_P(EndToEndTest, TransmitsFirstFrame) { class Renderer : public rtc::VideoSinkInterface { public: Renderer() : event_(false, false) {} @@ -352,20 +365,26 @@ class CodecObserver : public test::EndToEndTest, int frame_counter_; }; -TEST_F(EndToEndTest, SendsAndReceivesVP8Rotation90) { +TEST_P(EndToEndTest, SendsAndReceivesVP8) { + CodecObserver test(5, kVideoRotation_0, "VP8", VP8Encoder::Create(), + VP8Decoder::Create()); + RunBaseTest(&test); +} + +TEST_P(EndToEndTest, SendsAndReceivesVP8Rotation90) { CodecObserver test(5, kVideoRotation_90, "VP8", VP8Encoder::Create(), VP8Decoder::Create()); RunBaseTest(&test); } #if !defined(RTC_DISABLE_VP9) -TEST_F(EndToEndTest, SendsAndReceivesVP9) { +TEST_P(EndToEndTest, SendsAndReceivesVP9) { CodecObserver test(500, kVideoRotation_0, "VP9", VP9Encoder::Create(), VP9Decoder::Create()); RunBaseTest(&test); } -TEST_F(EndToEndTest, SendsAndReceivesVP9VideoRotation90) { +TEST_P(EndToEndTest, SendsAndReceivesVP9VideoRotation90) { CodecObserver test(5, kVideoRotation_90, "VP9", VP9Encoder::Create(), VP9Decoder::Create()); RunBaseTest(&test); @@ -373,14 +392,14 @@ TEST_F(EndToEndTest, SendsAndReceivesVP9VideoRotation90) { #endif // !defined(RTC_DISABLE_VP9) #if defined(WEBRTC_USE_H264) -TEST_F(EndToEndTest, SendsAndReceivesH264) { +TEST_P(EndToEndTest, SendsAndReceivesH264) { CodecObserver test(500, kVideoRotation_0, "H264", H264Encoder::Create(cricket::VideoCodec("H264")), H264Decoder::Create()); RunBaseTest(&test); } -TEST_F(EndToEndTest, SendsAndReceivesH264VideoRotation90) { +TEST_P(EndToEndTest, SendsAndReceivesH264VideoRotation90) { CodecObserver test(5, kVideoRotation_90, "H264", H264Encoder::Create(cricket::VideoCodec("H264")), H264Decoder::Create()); @@ -388,7 +407,7 @@ TEST_F(EndToEndTest, SendsAndReceivesH264VideoRotation90) { } #endif // defined(WEBRTC_USE_H264) -TEST_F(EndToEndTest, ReceiverUsesLocalSsrc) { +TEST_P(EndToEndTest, ReceiverUsesLocalSsrc) { class SyncRtcpObserver : public test::EndToEndTest { public: SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {} @@ -411,7 +430,7 @@ TEST_F(EndToEndTest, ReceiverUsesLocalSsrc) { RunBaseTest(&test); } -TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) { +TEST_P(EndToEndTest, ReceivesAndRetransmitsNack) { static const int kNumberOfNacksToObserve = 2; static const int kLossBurstSize = 2; static const int kPacketsBetweenLossBursts = 9; @@ -493,7 +512,7 @@ TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) { RunBaseTest(&test); } -TEST_F(EndToEndTest, ReceivesNackAndRetransmitsAudio) { +TEST_P(EndToEndTest, ReceivesNackAndRetransmitsAudio) { class NackObserver : public test::EndToEndTest { public: NackObserver() @@ -564,7 +583,7 @@ TEST_F(EndToEndTest, ReceivesNackAndRetransmitsAudio) { RunBaseTest(&test); } -TEST_F(EndToEndTest, CanReceiveUlpfec) { +TEST_P(EndToEndTest, CanReceiveUlpfec) { class UlpfecRenderObserver : public test::EndToEndTest, public rtc::VideoSinkInterface { public: @@ -590,8 +609,9 @@ TEST_F(EndToEndTest, CanReceiveUlpfec) { if (protected_sequence_numbers_.count(header.sequenceNumber) != 0) { // Retransmitted packet, should not count. protected_sequence_numbers_.erase(header.sequenceNumber); - EXPECT_GT(protected_timestamps_.count(header.timestamp), 0u); - protected_timestamps_.erase(header.timestamp); + auto ts_it = protected_timestamps_.find(header.timestamp); + EXPECT_NE(ts_it, protected_timestamps_.end()); + protected_timestamps_.erase(ts_it); return SEND_PACKET; } @@ -657,13 +677,15 @@ TEST_F(EndToEndTest, CanReceiveUlpfec) { rtc::CriticalSection crit_; std::set protected_sequence_numbers_ GUARDED_BY(crit_); - std::set protected_timestamps_ GUARDED_BY(crit_); + // Since several packets can have the same timestamp a multiset is used + // instead of a set. + std::multiset protected_timestamps_ GUARDED_BY(crit_); } test; RunBaseTest(&test); } -TEST_F(EndToEndTest, CanReceiveFlexfec) { +TEST_P(EndToEndTest, CanReceiveFlexfec) { class FlexfecRenderObserver : public test::EndToEndTest, public rtc::VideoSinkInterface { public: @@ -747,13 +769,15 @@ TEST_F(EndToEndTest, CanReceiveFlexfec) { rtc::CriticalSection crit_; std::set protected_sequence_numbers_ GUARDED_BY(crit_); - std::set protected_timestamps_ GUARDED_BY(crit_); + // Since several packets can have the same timestamp a multiset is used + // instead of a set. + std::multiset protected_timestamps_ GUARDED_BY(crit_); } test; RunBaseTest(&test); } -TEST_F(EndToEndTest, ReceivedUlpfecPacketsNotNacked) { +TEST_P(EndToEndTest, ReceivedUlpfecPacketsNotNacked) { class UlpfecNackObserver : public test::EndToEndTest { public: UlpfecNackObserver() @@ -1051,19 +1075,19 @@ void EndToEndTest::DecodesRetransmittedFrame(bool enable_rtx, bool enable_red) { RunBaseTest(&test); } -TEST_F(EndToEndTest, DecodesRetransmittedFrame) { +TEST_P(EndToEndTest, DecodesRetransmittedFrame) { DecodesRetransmittedFrame(false, false); } -TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) { +TEST_P(EndToEndTest, DecodesRetransmittedFrameOverRtx) { DecodesRetransmittedFrame(true, false); } -TEST_F(EndToEndTest, DecodesRetransmittedFrameByRed) { +TEST_P(EndToEndTest, DecodesRetransmittedFrameByRed) { DecodesRetransmittedFrame(false, true); } -TEST_F(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) { +TEST_P(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) { DecodesRetransmittedFrame(true, true); } @@ -1147,15 +1171,18 @@ void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) { RunBaseTest(&test); } -TEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) { +TEST_P(EndToEndTest, ReceivesPliAndRecoversWithNack) { ReceivesPliAndRecovers(1000); } -TEST_F(EndToEndTest, ReceivesPliAndRecoversWithoutNack) { +TEST_P(EndToEndTest, ReceivesPliAndRecoversWithoutNack) { + // This test makes no sense for the new video jitter buffer. + if (GetParam() == new_jb_enabled) + return; ReceivesPliAndRecovers(0); } -TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) { +TEST_P(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) { class PacketInputObserver : public PacketReceiver { public: explicit PacketInputObserver(PacketReceiver* receiver) @@ -1287,11 +1314,11 @@ void EndToEndTest::RespectsRtcpMode(RtcpMode rtcp_mode) { RunBaseTest(&test); } -TEST_F(EndToEndTest, UsesRtcpCompoundMode) { +TEST_P(EndToEndTest, UsesRtcpCompoundMode) { RespectsRtcpMode(RtcpMode::kCompound); } -TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) { +TEST_P(EndToEndTest, UsesRtcpReducedSizeMode) { RespectsRtcpMode(RtcpMode::kReducedSize); } @@ -1415,7 +1442,7 @@ class MultiStreamTest { // Each renderer verifies that it receives the expected resolution, and as soon // as every renderer has received a frame, the test finishes. -TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) { +TEST_P(EndToEndTest, SendsAndReceivesMultipleStreams) { class VideoOutputObserver : public rtc::VideoSinkInterface { public: VideoOutputObserver(const MultiStreamTest::CodecSettings& settings, @@ -1480,7 +1507,7 @@ TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) { tester.RunTest(); } -TEST_F(EndToEndTest, AssignsTransportSequenceNumbers) { +TEST_P(EndToEndTest, AssignsTransportSequenceNumbers) { static const int kExtensionId = 5; class RtpExtensionHeaderObserver : public test::DirectTransport { @@ -1747,32 +1774,32 @@ class TransportFeedbackTester : public test::EndToEndTest { Call* receiver_call_; }; -TEST_F(EndToEndTest, VideoReceivesTransportFeedback) { +TEST_P(EndToEndTest, VideoReceivesTransportFeedback) { TransportFeedbackTester test(true, 1, 0); RunBaseTest(&test); } -TEST_F(EndToEndTest, VideoTransportFeedbackNotConfigured) { +TEST_P(EndToEndTest, VideoTransportFeedbackNotConfigured) { TransportFeedbackTester test(false, 1, 0); RunBaseTest(&test); } -TEST_F(EndToEndTest, AudioReceivesTransportFeedback) { +TEST_P(EndToEndTest, AudioReceivesTransportFeedback) { TransportFeedbackTester test(true, 0, 1); RunBaseTest(&test); } -TEST_F(EndToEndTest, AudioTransportFeedbackNotConfigured) { +TEST_P(EndToEndTest, AudioTransportFeedbackNotConfigured) { TransportFeedbackTester test(false, 0, 1); RunBaseTest(&test); } -TEST_F(EndToEndTest, AudioVideoReceivesTransportFeedback) { +TEST_P(EndToEndTest, AudioVideoReceivesTransportFeedback) { TransportFeedbackTester test(true, 1, 1); RunBaseTest(&test); } -TEST_F(EndToEndTest, ObserversEncodedFrames) { +TEST_P(EndToEndTest, ObserversEncodedFrames) { class EncodedFrameTestObserver : public EncodedFrameObserver { public: EncodedFrameTestObserver() @@ -1847,7 +1874,7 @@ TEST_F(EndToEndTest, ObserversEncodedFrames) { DestroyStreams(); } -TEST_F(EndToEndTest, ReceiveStreamSendsRemb) { +TEST_P(EndToEndTest, ReceiveStreamSendsRemb) { class RembObserver : public test::EndToEndTest { public: RembObserver() : EndToEndTest(kDefaultTimeoutMs) {} @@ -1876,7 +1903,7 @@ TEST_F(EndToEndTest, ReceiveStreamSendsRemb) { RunBaseTest(&test); } -TEST_F(EndToEndTest, VerifyBandwidthStats) { +TEST_P(EndToEndTest, VerifyBandwidthStats) { class RtcpObserver : public test::EndToEndTest { public: RtcpObserver() @@ -1922,7 +1949,7 @@ TEST_F(EndToEndTest, VerifyBandwidthStats) { // then have the test generate a REMB of 500 kbps and verify that the send BWE // is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the // test verifies that the send BWE ramps back up to exactly 1000 kbps. -TEST_F(EndToEndTest, RembWithSendSideBwe) { +TEST_P(EndToEndTest, RembWithSendSideBwe) { class BweObserver : public test::EndToEndTest { public: BweObserver() @@ -2055,7 +2082,7 @@ TEST_F(EndToEndTest, RembWithSendSideBwe) { RunBaseTest(&test); } -TEST_F(EndToEndTest, VerifyNackStats) { +TEST_P(EndToEndTest, VerifyNackStats) { static const int kPacketNumberToDrop = 200; class NackObserver : public test::EndToEndTest { public: @@ -2387,21 +2414,21 @@ void EndToEndTest::VerifyHistogramStats(bool use_rtx, metrics::NumSamples("WebRTC.Video.ReceivedFecPacketsInPercent")); } -TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) { +TEST_P(EndToEndTest, VerifyHistogramStatsWithRtx) { const bool kEnabledRtx = true; const bool kEnabledRed = false; const bool kScreenshare = false; VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare); } -TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) { +TEST_P(EndToEndTest, VerifyHistogramStatsWithRed) { const bool kEnabledRtx = false; const bool kEnabledRed = true; const bool kScreenshare = false; VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare); } -TEST_F(EndToEndTest, VerifyHistogramStatsWithScreenshare) { +TEST_P(EndToEndTest, VerifyHistogramStatsWithScreenshare) { const bool kEnabledRtx = false; const bool kEnabledRed = false; const bool kScreenshare = true; @@ -2609,7 +2636,7 @@ void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs, RunBaseTest(&test); } -TEST_F(EndToEndTest, ReportsSetEncoderRates) { +TEST_P(EndToEndTest, ReportsSetEncoderRates) { class EncoderRateStatsTest : public test::EndToEndTest, public test::FakeEncoder { public: @@ -2689,7 +2716,7 @@ TEST_F(EndToEndTest, ReportsSetEncoderRates) { RunBaseTest(&test); } -TEST_F(EndToEndTest, GetStats) { +TEST_P(EndToEndTest, GetStats) { static const int kStartBitrateBps = 3000000; static const int kExpectedRenderDelayMs = 20; @@ -3030,18 +3057,22 @@ TEST_F(EndToEndTest, GetStats) { ReceiveStreamRenderer receive_stream_renderer_; } test; + // TODO(philipel): Implement statistics for the new video jitter buffer. + if (GetParam() == new_jb_enabled) + return; + RunBaseTest(&test); } -TEST_F(EndToEndTest, ReceiverReferenceTimeReportEnabled) { +TEST_P(EndToEndTest, ReceiverReferenceTimeReportEnabled) { TestXrReceiverReferenceTimeReport(true); } -TEST_F(EndToEndTest, ReceiverReferenceTimeReportDisabled) { +TEST_P(EndToEndTest, ReceiverReferenceTimeReportDisabled) { TestXrReceiverReferenceTimeReport(false); } -TEST_F(EndToEndTest, TestReceivedRtpPacketStats) { +TEST_P(EndToEndTest, TestReceivedRtpPacketStats) { static const size_t kNumRtpPacketsToSend = 5; class ReceivedRtpStatsObserver : public test::EndToEndTest { public: @@ -3081,17 +3112,19 @@ TEST_F(EndToEndTest, TestReceivedRtpPacketStats) { RunBaseTest(&test); } -TEST_F(EndToEndTest, SendsSetSsrc) { TestSendsSetSsrcs(1, false); } +TEST_P(EndToEndTest, SendsSetSsrc) { + TestSendsSetSsrcs(1, false); +} -TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) { +TEST_P(EndToEndTest, SendsSetSimulcastSsrcs) { TestSendsSetSsrcs(kNumSsrcs, false); } -TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) { +TEST_P(EndToEndTest, CanSwitchToUseAllSsrcs) { TestSendsSetSsrcs(kNumSsrcs, true); } -TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) { +TEST_P(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) { class ObserveRedundantPayloads: public test::EndToEndTest { public: ObserveRedundantPayloads() @@ -3425,19 +3458,19 @@ void EndToEndTest::TestRtpStatePreservation(bool use_rtx, DestroyStreams(); } -TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpState) { +TEST_P(EndToEndTest, RestartingSendStreamPreservesRtpState) { TestRtpStatePreservation(false, false); } -TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) { +TEST_P(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) { TestRtpStatePreservation(true, false); } -TEST_F(EndToEndTest, RestartingSendStreamKeepsRtpAndRtcpTimestampsSynced) { +TEST_P(EndToEndTest, RestartingSendStreamKeepsRtpAndRtcpTimestampsSynced) { TestRtpStatePreservation(true, true); } -TEST_F(EndToEndTest, RespectsNetworkState) { +TEST_P(EndToEndTest, RespectsNetworkState) { // TODO(pbos): Remove accepted downtime packets etc. when signaling network // down blocks until no more packets will be sent. @@ -3631,7 +3664,7 @@ TEST_F(EndToEndTest, RespectsNetworkState) { RunBaseTest(&test); } -TEST_F(EndToEndTest, CallReportsRttForSender) { +TEST_P(EndToEndTest, CallReportsRttForSender) { static const int kSendDelayMs = 30; static const int kReceiveDelayMs = 70; CreateCalls(Call::Config(&event_log_), Call::Config(&event_log_)); @@ -3668,8 +3701,11 @@ TEST_F(EndToEndTest, CallReportsRttForSender) { SleepMs(10); } + sender_transport.StopSending(); + receiver_transport.StopSending(); Stop(); DestroyStreams(); + DestroyCalls(); } void EndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState( @@ -3716,7 +3752,7 @@ void EndToEndTest::VerifyNewVideoReceiveStreamsRespectNetworkState( DestroyStreams(); } -TEST_F(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) { +TEST_P(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) { class UnusedEncoder : public test::FakeEncoder { public: UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {} @@ -3742,7 +3778,7 @@ TEST_F(EndToEndTest, NewVideoSendStreamsRespectVideoNetworkDown) { MediaType::AUDIO, &unused_encoder, &unused_transport); } -TEST_F(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) { +TEST_P(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) { class RequiredEncoder : public test::FakeEncoder { public: RequiredEncoder() @@ -3770,12 +3806,12 @@ TEST_F(EndToEndTest, NewVideoSendStreamsIgnoreAudioNetworkDown) { MediaType::VIDEO, &required_encoder, &required_transport); } -TEST_F(EndToEndTest, NewVideoReceiveStreamsRespectVideoNetworkDown) { +TEST_P(EndToEndTest, NewVideoReceiveStreamsRespectVideoNetworkDown) { UnusedTransport transport; VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::AUDIO, &transport); } -TEST_F(EndToEndTest, NewVideoReceiveStreamsIgnoreAudioNetworkDown) { +TEST_P(EndToEndTest, NewVideoReceiveStreamsIgnoreAudioNetworkDown) { RequiredTransport transport(false /*rtp*/, true /*rtcp*/); VerifyNewVideoReceiveStreamsRespectNetworkState(MediaType::VIDEO, &transport); } @@ -3801,7 +3837,7 @@ void VerifyEmptyFlexfecConfig(const FlexfecConfig& config) { << "Enabling FlexFEC requires ssrc-group: FEC-FR negotiation."; } -TEST_F(EndToEndTest, VerifyDefaultSendConfigParameters) { +TEST_P(EndToEndTest, VerifyDefaultSendConfigParameters) { VideoSendStream::Config default_send_config(nullptr); EXPECT_EQ(0, default_send_config.rtp.nack.rtp_history_ms) << "Enabling NACK require rtcp-fb: nack negotiation."; @@ -3815,7 +3851,7 @@ TEST_F(EndToEndTest, VerifyDefaultSendConfigParameters) { VerifyEmptyFlexfecConfig(default_send_config.rtp.flexfec); } -TEST_F(EndToEndTest, VerifyDefaultVideoReceiveConfigParameters) { +TEST_P(EndToEndTest, VerifyDefaultVideoReceiveConfigParameters) { VideoReceiveStream::Config default_receive_config(nullptr); EXPECT_EQ(RtcpMode::kCompound, default_receive_config.rtp.rtcp_mode) << "Reduced-size RTCP require rtcp-rsize to be negotiated."; @@ -3833,12 +3869,12 @@ TEST_F(EndToEndTest, VerifyDefaultVideoReceiveConfigParameters) { VerifyEmptyUlpfecConfig(default_receive_config.rtp.ulpfec); } -TEST_F(EndToEndTest, VerifyDefaultFlexfecReceiveConfigParameters) { +TEST_P(EndToEndTest, VerifyDefaultFlexfecReceiveConfigParameters) { FlexfecReceiveStream::Config default_receive_config; VerifyEmptyFlexfecConfig(default_receive_config); } -TEST_F(EndToEndTest, TransportSeqNumOnAudioAndVideo) { +TEST_P(EndToEndTest, TransportSeqNumOnAudioAndVideo) { static const int kExtensionId = 8; class TransportSequenceNumberTest : public test::EndToEndTest { public: @@ -3949,7 +3985,7 @@ class EndToEndLogTest : public EndToEndTest { std::vector paths_; }; -TEST_F(EndToEndLogTest, LogsEncodedFramesWhenRequested) { +TEST_P(EndToEndLogTest, LogsEncodedFramesWhenRequested) { static const int kNumFramesToRecord = 10; class LogEncodingObserver : public test::EndToEndTest, public EncodedFrameObserver {