diff --git a/webrtc/modules/BUILD.gn b/webrtc/modules/BUILD.gn index 21d0fdb532..e846f83e44 100644 --- a/webrtc/modules/BUILD.gn +++ b/webrtc/modules/BUILD.gn @@ -326,6 +326,7 @@ if (rtc_include_tests) { "video_coding/percentile_filter_unittest.cc", "video_coding/protection_bitrate_calculator_unittest.cc", "video_coding/receiver_unittest.cc", + "video_coding/rtp_frame_reference_finder_unittest.cc", "video_coding/sequence_number_util_unittest.cc", "video_coding/session_info_unittest.cc", "video_coding/test/stream_generator.cc", diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp index c0f9504d08..094204f723 100644 --- a/webrtc/modules/modules.gyp +++ b/webrtc/modules/modules.gyp @@ -167,14 +167,14 @@ '<(webrtc_root)/tools/tools.gyp:agc_test_utils', ], 'sources': [ - 'audio_coding/codecs/audio_decoder_factory_unittest.cc', - 'audio_coding/codecs/cng/audio_encoder_cng_unittest.cc', 'audio_coding/acm2/acm_receiver_unittest_oldapi.cc', 'audio_coding/acm2/audio_coding_module_unittest_oldapi.cc', 'audio_coding/acm2/call_statistics_unittest.cc', 'audio_coding/acm2/codec_manager_unittest.cc', 'audio_coding/acm2/initial_delay_manager_unittest.cc', 'audio_coding/acm2/rent_a_codec_unittest.cc', + 'audio_coding/codecs/audio_decoder_factory_unittest.cc', + 'audio_coding/codecs/cng/audio_encoder_cng_unittest.cc', 'audio_coding/codecs/cng/cng_unittest.cc', 'audio_coding/codecs/isac/fix/source/filterbanks_unittest.cc', 'audio_coding/codecs/isac/fix/source/filters_unittest.cc', @@ -183,10 +183,10 @@ 'audio_coding/codecs/isac/main/source/audio_encoder_isac_unittest.cc', 'audio_coding/codecs/isac/main/source/isac_unittest.cc', 'audio_coding/codecs/isac/unittest.cc', + 'audio_coding/codecs/mock/mock_audio_encoder.cc', 'audio_coding/codecs/opus/audio_encoder_opus_unittest.cc', 'audio_coding/codecs/opus/opus_unittest.cc', 'audio_coding/codecs/red/audio_encoder_copy_red_unittest.cc', - 'audio_coding/codecs/mock/mock_audio_encoder.cc', 'audio_coding/neteq/audio_classifier_unittest.cc', 'audio_coding/neteq/audio_multi_vector_unittest.cc', 'audio_coding/neteq/audio_vector_unittest.cc', @@ -202,6 +202,18 @@ 'audio_coding/neteq/dtmf_tone_generator_unittest.cc', 'audio_coding/neteq/expand_unittest.cc', 'audio_coding/neteq/merge_unittest.cc', + 'audio_coding/neteq/mock/mock_audio_decoder.h', + 'audio_coding/neteq/mock/mock_audio_vector.h', + 'audio_coding/neteq/mock/mock_buffer_level_filter.h', + 'audio_coding/neteq/mock/mock_decoder_database.h', + 'audio_coding/neteq/mock/mock_delay_manager.h', + 'audio_coding/neteq/mock/mock_delay_peak_detector.h', + 'audio_coding/neteq/mock/mock_dtmf_buffer.h', + 'audio_coding/neteq/mock/mock_dtmf_tone_generator.h', + 'audio_coding/neteq/mock/mock_expand.h', + 'audio_coding/neteq/mock/mock_external_decoder_pcm16b.h', + 'audio_coding/neteq/mock/mock_packet_buffer.h', + 'audio_coding/neteq/mock/mock_payload_splitter.h', 'audio_coding/neteq/nack_tracker_unittest.cc', 'audio_coding/neteq/neteq_external_decoder_unittest.cc', 'audio_coding/neteq/neteq_impl_unittest.cc', @@ -215,20 +227,8 @@ 'audio_coding/neteq/random_vector_unittest.cc', 'audio_coding/neteq/sync_buffer_unittest.cc', 'audio_coding/neteq/tick_timer_unittest.cc', - 'audio_coding/neteq/timestamp_scaler_unittest.cc', 'audio_coding/neteq/time_stretch_unittest.cc', - 'audio_coding/neteq/mock/mock_audio_decoder.h', - 'audio_coding/neteq/mock/mock_audio_vector.h', - 'audio_coding/neteq/mock/mock_buffer_level_filter.h', - 'audio_coding/neteq/mock/mock_decoder_database.h', - 'audio_coding/neteq/mock/mock_delay_manager.h', - 'audio_coding/neteq/mock/mock_delay_peak_detector.h', - 'audio_coding/neteq/mock/mock_dtmf_buffer.h', - 'audio_coding/neteq/mock/mock_dtmf_tone_generator.h', - 'audio_coding/neteq/mock/mock_expand.h', - 'audio_coding/neteq/mock/mock_external_decoder_pcm16b.h', - 'audio_coding/neteq/mock/mock_packet_buffer.h', - 'audio_coding/neteq/mock/mock_payload_splitter.h', + 'audio_coding/neteq/timestamp_scaler_unittest.cc', 'audio_coding/neteq/tools/input_audio_file_unittest.cc', 'audio_coding/neteq/tools/packet_unittest.cc', 'audio_conference_mixer/test/audio_conference_mixer_unittest.cc', @@ -284,8 +284,8 @@ 'pacing/paced_sender_unittest.cc', 'pacing/packet_router_unittest.cc', 'remote_bitrate_estimator/bwe_simulations.cc', - 'remote_bitrate_estimator/include/mock/mock_remote_bitrate_observer.h', 'remote_bitrate_estimator/include/mock/mock_remote_bitrate_estimator.h', + 'remote_bitrate_estimator/include/mock/mock_remote_bitrate_observer.h', 'remote_bitrate_estimator/inter_arrival_unittest.cc', 'remote_bitrate_estimator/overuse_detector_unittest.cc', 'remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time_unittest.cc', @@ -296,22 +296,21 @@ 'remote_bitrate_estimator/send_time_history_unittest.cc', 'remote_bitrate_estimator/test/bwe_test_framework_unittest.cc', 'remote_bitrate_estimator/test/bwe_unittest.cc', - 'remote_bitrate_estimator/test/metric_recorder_unittest.cc', 'remote_bitrate_estimator/test/estimators/nada_unittest.cc', + 'remote_bitrate_estimator/test/metric_recorder_unittest.cc', 'remote_bitrate_estimator/transport_feedback_adapter_unittest.cc', - 'rtp_rtcp/source/mock/mock_rtp_payload_strategy.h', 'rtp_rtcp/source/byte_io_unittest.cc', 'rtp_rtcp/source/fec_receiver_unittest.cc', 'rtp_rtcp/source/fec_test_helper.cc', 'rtp_rtcp/source/fec_test_helper.h', + 'rtp_rtcp/source/mock/mock_rtp_payload_strategy.h', 'rtp_rtcp/source/nack_rtx_unittest.cc', 'rtp_rtcp/source/packet_loss_stats_unittest.cc', - 'rtp_rtcp/source/producer_fec_unittest.cc', 'rtp_rtcp/source/playout_delay_oracle_unittest.cc', + 'rtp_rtcp/source/producer_fec_unittest.cc', 'rtp_rtcp/source/receive_statistics_unittest.cc', 'rtp_rtcp/source/remote_ntp_time_estimator_unittest.cc', 'rtp_rtcp/source/rtcp_format_remb_unittest.cc', - 'rtp_rtcp/source/rtcp_packet_unittest.cc', 'rtp_rtcp/source/rtcp_packet/app_unittest.cc', 'rtp_rtcp/source/rtcp_packet/bye_unittest.cc', 'rtp_rtcp/source/rtcp_packet/common_header_unittest.cc', @@ -335,6 +334,7 @@ 'rtp_rtcp/source/rtcp_packet/tmmbr_unittest.cc', 'rtp_rtcp/source/rtcp_packet/transport_feedback_unittest.cc', 'rtp_rtcp/source/rtcp_packet/voip_metric_unittest.cc', + 'rtp_rtcp/source/rtcp_packet_unittest.cc', 'rtp_rtcp/source/rtcp_receiver_unittest.cc', 'rtp_rtcp/source/rtcp_sender_unittest.cc', 'rtp_rtcp/source/rtcp_utility_unittest.cc', @@ -344,11 +344,11 @@ 'rtp_rtcp/source/rtp_format_vp8_test_helper.h', 'rtp_rtcp/source/rtp_format_vp8_unittest.cc', 'rtp_rtcp/source/rtp_format_vp9_unittest.cc', + 'rtp_rtcp/source/rtp_header_extension_unittest.cc', 'rtp_rtcp/source/rtp_packet_history_unittest.cc', 'rtp_rtcp/source/rtp_packet_unittest.cc', 'rtp_rtcp/source/rtp_payload_registry_unittest.cc', 'rtp_rtcp/source/rtp_rtcp_impl_unittest.cc', - 'rtp_rtcp/source/rtp_header_extension_unittest.cc', 'rtp_rtcp/source/rtp_sender_unittest.cc', 'rtp_rtcp/source/time_util_unittest.cc', 'rtp_rtcp/source/vp8_partition_aggregator_unittest.cc', @@ -369,29 +369,30 @@ 'video_coding/codecs/vp8/simulcast_encoder_adapter_unittest.cc', 'video_coding/codecs/vp8/simulcast_unittest.cc', 'video_coding/codecs/vp8/simulcast_unittest.h', - 'video_coding/frame_buffer2_unittest.cc', - 'video_coding/include/mock/mock_vcm_callbacks.h', 'video_coding/decoding_state_unittest.cc', + 'video_coding/frame_buffer2_unittest.cc', 'video_coding/histogram_unittest.cc', + 'video_coding/include/mock/mock_vcm_callbacks.h', 'video_coding/jitter_buffer_unittest.cc', 'video_coding/jitter_estimator_tests.cc', 'video_coding/nack_module_unittest.cc', - 'video_coding/video_packet_buffer_unittest.cc', 'video_coding/percentile_filter_unittest.cc', 'video_coding/protection_bitrate_calculator_unittest.cc', 'video_coding/receiver_unittest.cc', - 'video_coding/session_info_unittest.cc', + 'video_coding/rtp_frame_reference_finder_unittest.cc', 'video_coding/sequence_number_util_unittest.cc', - 'video_coding/timing_unittest.cc', - 'video_coding/video_coding_robustness_unittest.cc', - 'video_coding/video_receiver_unittest.cc', - 'video_coding/video_sender_unittest.cc', + 'video_coding/session_info_unittest.cc', 'video_coding/test/stream_generator.cc', 'video_coding/test/stream_generator.h', + 'video_coding/timing_unittest.cc', 'video_coding/utility/frame_dropper_unittest.cc', 'video_coding/utility/h264_bitstream_parser_unittest.cc', 'video_coding/utility/ivf_file_writer_unittest.cc', 'video_coding/utility/quality_scaler_unittest.cc', + 'video_coding/video_coding_robustness_unittest.cc', + 'video_coding/video_packet_buffer_unittest.cc', + 'video_coding/video_receiver_unittest.cc', + 'video_coding/video_sender_unittest.cc', 'video_processing/test/denoiser_test.cc', 'video_processing/test/video_processing_unittest.cc', 'video_processing/test/video_processing_unittest.h', diff --git a/webrtc/modules/video_coding/frame_object.h b/webrtc/modules/video_coding/frame_object.h index 5b299e673c..a63ae996b8 100644 --- a/webrtc/modules/video_coding/frame_object.h +++ b/webrtc/modules/video_coding/frame_object.h @@ -75,7 +75,7 @@ class RtpFrameObject : public FrameObject { RTPVideoTypeHeader* GetCodecHeader() const; private: - PacketBuffer* packet_buffer_; + rtc::scoped_refptr packet_buffer_; enum FrameType frame_type_; VideoCodecType codec_type_; uint16_t first_seq_num_; diff --git a/webrtc/modules/video_coding/packet_buffer.cc b/webrtc/modules/video_coding/packet_buffer.cc index df173504ff..0d36b9c3c9 100644 --- a/webrtc/modules/video_coding/packet_buffer.cc +++ b/webrtc/modules/video_coding/packet_buffer.cc @@ -12,7 +12,9 @@ #include #include +#include +#include "webrtc/base/atomicops.h" #include "webrtc/base/checks.h" #include "webrtc/base/logging.h" #include "webrtc/modules/video_coding/frame_object.h" @@ -21,10 +23,19 @@ namespace webrtc { namespace video_coding { +rtc::scoped_refptr PacketBuffer::Create( + Clock* clock, + size_t start_buffer_size, + size_t max_buffer_size, + OnReceivedFrameCallback* received_frame_callback) { + return rtc::scoped_refptr(new PacketBuffer( + clock, start_buffer_size, max_buffer_size, received_frame_callback)); +} + PacketBuffer::PacketBuffer(Clock* clock, size_t start_buffer_size, size_t max_buffer_size, - OnCompleteFrameCallback* frame_callback) + OnReceivedFrameCallback* received_frame_callback) : clock_(clock), size_(start_buffer_size), max_size_(max_buffer_size), @@ -33,13 +44,15 @@ PacketBuffer::PacketBuffer(Clock* clock, first_packet_received_(false), data_buffer_(start_buffer_size), sequence_buffer_(start_buffer_size), - reference_finder_(frame_callback) { + received_frame_callback_(received_frame_callback) { RTC_DCHECK_LE(start_buffer_size, max_buffer_size); // Buffer size must always be a power of 2. RTC_DCHECK((start_buffer_size & (start_buffer_size - 1)) == 0); RTC_DCHECK((max_buffer_size & (max_buffer_size - 1)) == 0); } +PacketBuffer::~PacketBuffer() {} + bool PacketBuffer::InsertPacket(const VCMPacket& packet) { rtc::CritScope lock(&crit_); uint16_t seq_num = packet.seqNum; @@ -69,12 +82,6 @@ bool PacketBuffer::InsertPacket(const VCMPacket& packet) { if (AheadOf(seq_num, last_seq_num_)) last_seq_num_ = seq_num; - // If this is a padding or FEC packet, don't insert it. - if (packet.sizeBytes == 0) { - reference_finder_.PaddingReceived(packet.seqNum); - return true; - } - sequence_buffer_[index].frame_begin = packet.isFirstPacket; sequence_buffer_[index].frame_end = packet.markerBit; sequence_buffer_[index].seq_num = packet.seqNum; @@ -169,7 +176,8 @@ void PacketBuffer::FindFrames(uint16_t seq_num) { std::unique_ptr frame( new RtpFrameObject(this, start_seq_num, seq_num, frame_size, max_nack_count, clock_->TimeInMilliseconds())); - reference_finder_.ManageFrame(std::move(frame)); + + received_frame_callback_->OnReceivedFrame(std::move(frame)); } index = (index + 1) % size_; @@ -239,5 +247,17 @@ void PacketBuffer::Clear() { first_packet_received_ = false; } +int PacketBuffer::AddRef() const { + return rtc::AtomicOps::Increment(&ref_count_); +} + +int PacketBuffer::Release() const { + int count = rtc::AtomicOps::Decrement(&ref_count_); + if (!count) { + delete this; + } + return count; +} + } // namespace video_coding } // namespace webrtc diff --git a/webrtc/modules/video_coding/packet_buffer.h b/webrtc/modules/video_coding/packet_buffer.h index ec187de086..34a2d402bb 100644 --- a/webrtc/modules/video_coding/packet_buffer.h +++ b/webrtc/modules/video_coding/packet_buffer.h @@ -12,8 +12,10 @@ #define WEBRTC_MODULES_VIDEO_CODING_PACKET_BUFFER_H_ #include +#include #include "webrtc/base/criticalsection.h" +#include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/base/thread_annotations.h" #include "webrtc/modules/include/module_common_types.h" #include "webrtc/modules/video_coding/packet.h" @@ -29,23 +31,37 @@ namespace video_coding { class FrameObject; class RtpFrameObject; -class OnCompleteFrameCallback { +// A received frame is a frame which has received all its packets. +class OnReceivedFrameCallback { public: - virtual ~OnCompleteFrameCallback() {} - virtual void OnCompleteFrame(std::unique_ptr frame) = 0; + virtual ~OnReceivedFrameCallback() {} + virtual void OnReceivedFrame(std::unique_ptr frame) = 0; }; class PacketBuffer { public: + static rtc::scoped_refptr Create( + Clock* clock, + size_t start_buffer_size, + size_t max_buffer_size, + OnReceivedFrameCallback* frame_callback); + + virtual ~PacketBuffer(); + + // Made virtual for testing. + virtual bool InsertPacket(const VCMPacket& packet); + void ClearTo(uint16_t seq_num); + void Clear(); + + int AddRef() const; + int Release() const; + + protected: // Both |start_buffer_size| and |max_buffer_size| must be a power of 2. PacketBuffer(Clock* clock, size_t start_buffer_size, size_t max_buffer_size, - OnCompleteFrameCallback* frame_callback); - - bool InsertPacket(const VCMPacket& packet); - void ClearTo(uint16_t seq_num); - void Clear(); + OnReceivedFrameCallback* frame_callback); private: friend RtpFrameObject; @@ -85,13 +101,16 @@ class PacketBuffer { void FindFrames(uint16_t seq_num) EXCLUSIVE_LOCKS_REQUIRED(crit_); // Copy the bitstream for |frame| to |destination|. - bool GetBitstream(const RtpFrameObject& frame, uint8_t* destination); + // Virtual for testing. + virtual bool GetBitstream(const RtpFrameObject& frame, uint8_t* destination); // Get the packet with sequence number |seq_num|. - VCMPacket* GetPacket(uint16_t seq_num); + // Virtual for testing. + virtual VCMPacket* GetPacket(uint16_t seq_num); // Mark all slots used by |frame| as not used. - void ReturnFrame(RtpFrameObject* frame); + // Virtual for testing. + virtual void ReturnFrame(RtpFrameObject* frame); rtc::CriticalSection crit_; @@ -115,9 +134,10 @@ class PacketBuffer { // and information needed to determine the continuity between packets. std::vector sequence_buffer_ GUARDED_BY(crit_); - // Frames that have received all their packets are handed off to the - // |reference_finder_| which finds the dependencies between the frames. - RtpFrameReferenceFinder reference_finder_; + // Called when a received frame is found. + OnReceivedFrameCallback* const received_frame_callback_; + + mutable volatile int ref_count_ = 0; }; } // namespace video_coding diff --git a/webrtc/modules/video_coding/rtp_frame_reference_finder.h b/webrtc/modules/video_coding/rtp_frame_reference_finder.h index a12d6d8fca..a812303b7e 100644 --- a/webrtc/modules/video_coding/rtp_frame_reference_finder.h +++ b/webrtc/modules/video_coding/rtp_frame_reference_finder.h @@ -26,8 +26,16 @@ namespace webrtc { namespace video_coding { +class FrameObject; class RtpFrameObject; -class OnCompleteFrameCallback; + +// A complete frame is a frame which has received all its packets and all its +// references are known. +class OnCompleteFrameCallback { + public: + virtual ~OnCompleteFrameCallback() {} + virtual void OnCompleteFrame(std::unique_ptr frame) = 0; +}; class RtpFrameReferenceFinder { public: diff --git a/webrtc/modules/video_coding/rtp_frame_reference_finder_unittest.cc b/webrtc/modules/video_coding/rtp_frame_reference_finder_unittest.cc new file mode 100644 index 0000000000..967acfc42b --- /dev/null +++ b/webrtc/modules/video_coding/rtp_frame_reference_finder_unittest.cc @@ -0,0 +1,1195 @@ +/* + * Copyright (c) 2016 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 + +#include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/random.h" +#include "webrtc/base/refcount.h" +#include "webrtc/modules/video_coding/frame_object.h" +#include "webrtc/modules/video_coding/packet_buffer.h" +#include "webrtc/system_wrappers/include/clock.h" + +namespace webrtc { +namespace video_coding { + +class FakePacketBuffer : public PacketBuffer { + public: + FakePacketBuffer() : PacketBuffer(nullptr, 0, 0, nullptr) {} + + VCMPacket* GetPacket(uint16_t seq_num) override { + auto packet_it = packets_.find(seq_num); + return packet_it == packets_.end() ? nullptr : &packet_it->second; + } + + bool InsertPacket(const VCMPacket& packet) override { + packets_[packet.seqNum] = packet; + return true; + } + + bool GetBitstream(const RtpFrameObject& frame, + uint8_t* destination) override { + return true; + } + + void ReturnFrame(RtpFrameObject* frame) override { + packets_.erase(frame->first_seq_num()); + } + + private: + std::map packets_; +}; + +class TestRtpFrameReferenceFinder : public ::testing::Test, + public OnCompleteFrameCallback { + protected: + TestRtpFrameReferenceFinder() + : rand_(0x8739211), + ref_packet_buffer_(new FakePacketBuffer()), + reference_finder_(new RtpFrameReferenceFinder(this)), + frames_from_callback_(FrameComp()) {} + + uint16_t Rand() { return rand_.Rand(std::numeric_limits::max()); } + + void OnCompleteFrame(std::unique_ptr frame) override { + uint16_t pid = frame->picture_id; + uint16_t sidx = frame->spatial_layer; + auto frame_it = frames_from_callback_.find(std::make_pair(pid, sidx)); + if (frame_it != frames_from_callback_.end()) { + ADD_FAILURE() << "Already received frame with (pid:sidx): (" << pid << ":" + << sidx << ")"; + return; + } + + frames_from_callback_.insert( + std::make_pair(std::make_pair(pid, sidx), std::move(frame))); + } + + void InsertGeneric(uint16_t seq_num_start, + uint16_t seq_num_end, + bool keyframe) { + VCMPacket packet; + packet.codec = kVideoCodecGeneric; + packet.seqNum = seq_num_start; + packet.frameType = keyframe ? kVideoFrameKey : kVideoFrameDelta; + + 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)); + } + + void InsertVp8(uint16_t seq_num_start, + uint16_t seq_num_end, + bool keyframe, + int32_t pid = kNoPictureId, + uint8_t tid = kNoTemporalIdx, + int32_t tl0 = kNoTl0PicIdx, + bool sync = false) { + VCMPacket packet; + packet.codec = kVideoCodecVP8; + packet.seqNum = seq_num_start; + 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); + std::unique_ptr frame(new RtpFrameObject( + ref_packet_buffer_, seq_num_start, seq_num_end, 0, 0, 0)); + reference_finder_->ManageFrame(std::move(frame)); + } + + void InsertVp9Gof(uint16_t seq_num_start, + uint16_t seq_num_end, + bool keyframe, + int32_t pid = kNoPictureId, + uint8_t sid = kNoSpatialIdx, + uint8_t tid = kNoTemporalIdx, + int32_t tl0 = kNoTl0PicIdx, + bool up_switch = false, + GofInfoVP9* ss = nullptr) { + VCMPacket packet; + packet.codec = kVideoCodecVP9; + packet.seqNum = seq_num_start; + packet.frameType = keyframe ? kVideoFrameKey : kVideoFrameDelta; + packet.video_header.codecHeader.VP9.flexible_mode = false; + packet.video_header.codecHeader.VP9.picture_id = pid % (1 << 15); + packet.video_header.codecHeader.VP9.temporal_idx = tid; + packet.video_header.codecHeader.VP9.spatial_idx = sid; + packet.video_header.codecHeader.VP9.tl0_pic_idx = tl0; + packet.video_header.codecHeader.VP9.temporal_up_switch = up_switch; + if (ss != nullptr) { + packet.video_header.codecHeader.VP9.ss_data_available = true; + packet.video_header.codecHeader.VP9.gof = *ss; + } + + 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)); + } + + void InsertVp9Flex(uint16_t seq_num_start, + uint16_t seq_num_end, + bool keyframe, + int32_t pid = kNoPictureId, + uint8_t sid = kNoSpatialIdx, + uint8_t tid = kNoTemporalIdx, + int32_t tl0 = kNoTl0PicIdx, + bool inter = false, + std::vector refs = std::vector()) { + VCMPacket packet; + packet.codec = kVideoCodecVP9; + packet.seqNum = seq_num_start; + packet.frameType = keyframe ? kVideoFrameKey : kVideoFrameDelta; + packet.video_header.codecHeader.VP9.inter_layer_predicted = inter; + packet.video_header.codecHeader.VP9.flexible_mode = true; + packet.video_header.codecHeader.VP9.picture_id = pid % (1 << 15); + packet.video_header.codecHeader.VP9.temporal_idx = tid; + packet.video_header.codecHeader.VP9.spatial_idx = sid; + packet.video_header.codecHeader.VP9.tl0_pic_idx = tl0; + 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); + std::unique_ptr frame(new RtpFrameObject( + ref_packet_buffer_, seq_num_start, seq_num_end, 0, 0, 0)); + reference_finder_->ManageFrame(std::move(frame)); + } + + // Check if a frame with picture id |pid| and spatial index |sidx| has been + // delivered from the packet buffer, and if so, if it has the references + // specified by |refs|. + template + void CheckReferences(uint16_t pid, uint16_t sidx, T... refs) const { + auto frame_it = frames_from_callback_.find(std::make_pair(pid, sidx)); + if (frame_it == frames_from_callback_.end()) { + ADD_FAILURE() << "Could not find frame with (pid:sidx): (" << pid << ":" + << sidx << ")"; + return; + } + + std::set actual_refs; + for (uint8_t r = 0; r < frame_it->second->num_references; ++r) { + actual_refs.insert(frame_it->second->references[r]); + } + + std::set expected_refs; + RefsToSet(&expected_refs, refs...); + + ASSERT_EQ(expected_refs, actual_refs); + } + + template + void CheckReferencesGeneric(uint16_t pid, T... refs) const { + CheckReferences(pid, 0, refs...); + } + + template + void CheckReferencesVp8(uint16_t pid, T... refs) const { + CheckReferences(pid, 0, refs...); + } + + template + void CheckReferencesVp9(uint16_t pid, uint8_t sidx, T... refs) const { + CheckReferences(pid, sidx, refs...); + } + + template + void RefsToSet(std::set* m, uint16_t ref, T... refs) const { + m->insert(ref); + RefsToSet(m, refs...); + } + + void RefsToSet(std::set* m) const {} + + Random rand_; + rtc::scoped_refptr ref_packet_buffer_; + std::unique_ptr reference_finder_; + struct FrameComp { + bool operator()(const std::pair f1, + const std::pair f2) const { + if (f1.first == f2.first) + return f1.second < f2.second; + return f1.first < f2.first; + } + }; + std::map, + std::unique_ptr, + FrameComp> + frames_from_callback_; +}; + +TEST_F(TestRtpFrameReferenceFinder, PaddingPackets) { + uint16_t sn = Rand(); + + InsertGeneric(sn, sn, true); + InsertGeneric(sn + 2, sn + 2, false); + EXPECT_EQ(1UL, frames_from_callback_.size()); + reference_finder_->PaddingReceived(sn + 1); + EXPECT_EQ(2UL, frames_from_callback_.size()); +} + +TEST_F(TestRtpFrameReferenceFinder, PaddingPacketsReordered) { + uint16_t sn = Rand(); + + InsertGeneric(sn, sn, true); + reference_finder_->PaddingReceived(sn + 1); + reference_finder_->PaddingReceived(sn + 4); + InsertGeneric(sn + 2, sn + 3, false); + + EXPECT_EQ(2UL, frames_from_callback_.size()); + CheckReferencesGeneric(sn); + CheckReferencesGeneric(sn + 3, sn); +} + +TEST_F(TestRtpFrameReferenceFinder, PaddingPacketsReorderedMultipleKeyframes) { + uint16_t sn = Rand(); + + InsertGeneric(sn, sn, true); + reference_finder_->PaddingReceived(sn + 1); + reference_finder_->PaddingReceived(sn + 4); + InsertGeneric(sn + 2, sn + 3, false); + InsertGeneric(sn + 5, sn + 5, true); + reference_finder_->PaddingReceived(sn + 6); + reference_finder_->PaddingReceived(sn + 9); + InsertGeneric(sn + 7, sn + 8, false); + + EXPECT_EQ(4UL, frames_from_callback_.size()); +} + +TEST_F(TestRtpFrameReferenceFinder, Vp8NoPictureId) { + uint16_t sn = Rand(); + + InsertVp8(sn, sn + 2, true); + ASSERT_EQ(1UL, frames_from_callback_.size()); + + InsertVp8(sn + 3, sn + 4, false); + ASSERT_EQ(2UL, frames_from_callback_.size()); + + InsertVp8(sn + 5, sn + 8, false); + ASSERT_EQ(3UL, frames_from_callback_.size()); + + InsertVp8(sn + 9, sn + 9, false); + ASSERT_EQ(4UL, frames_from_callback_.size()); + + InsertVp8(sn + 10, sn + 11, false); + ASSERT_EQ(5UL, frames_from_callback_.size()); + + InsertVp8(sn + 12, sn + 12, true); + ASSERT_EQ(6UL, frames_from_callback_.size()); + + InsertVp8(sn + 13, sn + 17, false); + ASSERT_EQ(7UL, frames_from_callback_.size()); + + InsertVp8(sn + 18, sn + 18, false); + ASSERT_EQ(8UL, frames_from_callback_.size()); + + InsertVp8(sn + 19, sn + 20, false); + ASSERT_EQ(9UL, frames_from_callback_.size()); + + InsertVp8(sn + 21, sn + 21, false); + + ASSERT_EQ(10UL, frames_from_callback_.size()); + CheckReferencesVp8(sn + 2); + CheckReferencesVp8(sn + 4, sn + 2); + CheckReferencesVp8(sn + 8, sn + 4); + CheckReferencesVp8(sn + 9, sn + 8); + CheckReferencesVp8(sn + 11, sn + 9); + CheckReferencesVp8(sn + 12); + CheckReferencesVp8(sn + 17, sn + 12); + CheckReferencesVp8(sn + 18, sn + 17); + CheckReferencesVp8(sn + 20, sn + 18); + CheckReferencesVp8(sn + 21, sn + 20); +} + +TEST_F(TestRtpFrameReferenceFinder, Vp8NoPictureIdReordered) { + uint16_t sn = 0xfffa; + + InsertVp8(sn, sn + 2, true); + InsertVp8(sn + 3, sn + 4, false); + InsertVp8(sn + 5, sn + 8, false); + InsertVp8(sn + 9, sn + 9, false); + InsertVp8(sn + 10, sn + 11, false); + InsertVp8(sn + 12, sn + 12, true); + InsertVp8(sn + 13, sn + 17, false); + InsertVp8(sn + 18, sn + 18, false); + InsertVp8(sn + 19, sn + 20, false); + InsertVp8(sn + 21, sn + 21, false); + + ASSERT_EQ(10UL, frames_from_callback_.size()); + CheckReferencesVp8(sn + 2); + CheckReferencesVp8(sn + 4, sn + 2); + CheckReferencesVp8(sn + 8, sn + 4); + CheckReferencesVp8(sn + 9, sn + 8); + CheckReferencesVp8(sn + 11, sn + 9); + CheckReferencesVp8(sn + 12); + CheckReferencesVp8(sn + 17, sn + 12); + CheckReferencesVp8(sn + 18, sn + 17); + CheckReferencesVp8(sn + 20, sn + 18); + CheckReferencesVp8(sn + 21, sn + 20); +} + +TEST_F(TestRtpFrameReferenceFinder, Vp8KeyFrameReferences) { + uint16_t sn = Rand(); + InsertVp8(sn, sn, true); + + ASSERT_EQ(1UL, frames_from_callback_.size()); + CheckReferencesVp8(sn); +} + +// Test with 1 temporal layer. +TEST_F(TestRtpFrameReferenceFinder, Vp8TemporalLayers_0) { + uint16_t pid = Rand(); + uint16_t sn = Rand(); + + InsertVp8(sn, sn, true, pid, 0, 1); + InsertVp8(sn + 1, sn + 1, false, pid + 1, 0, 2); + InsertVp8(sn + 2, sn + 2, false, pid + 2, 0, 3); + InsertVp8(sn + 3, sn + 3, false, pid + 3, 0, 4); + + ASSERT_EQ(4UL, frames_from_callback_.size()); + CheckReferencesVp8(pid); + CheckReferencesVp8(pid + 1, pid); + CheckReferencesVp8(pid + 2, pid + 1); + CheckReferencesVp8(pid + 3, pid + 2); +} + +// Test with 1 temporal layer. +TEST_F(TestRtpFrameReferenceFinder, Vp8TemporalLayersReordering_0) { + uint16_t pid = Rand(); + uint16_t sn = Rand(); + + InsertVp8(sn, sn, true, pid, 0, 1); + InsertVp8(sn + 1, sn + 1, false, pid + 1, 0, 2); + InsertVp8(sn + 3, sn + 3, false, pid + 3, 0, 4); + InsertVp8(sn + 2, sn + 2, false, pid + 2, 0, 3); + InsertVp8(sn + 5, sn + 5, false, pid + 5, 0, 6); + InsertVp8(sn + 6, sn + 6, false, pid + 6, 0, 7); + InsertVp8(sn + 4, sn + 4, false, pid + 4, 0, 5); + + ASSERT_EQ(7UL, frames_from_callback_.size()); + CheckReferencesVp8(pid); + CheckReferencesVp8(pid + 1, pid); + CheckReferencesVp8(pid + 2, pid + 1); + CheckReferencesVp8(pid + 3, pid + 2); + CheckReferencesVp8(pid + 4, pid + 3); + CheckReferencesVp8(pid + 5, pid + 4); + CheckReferencesVp8(pid + 6, pid + 5); +} + +// Test with 2 temporal layers in a 01 pattern. +TEST_F(TestRtpFrameReferenceFinder, Vp8TemporalLayers_01) { + uint16_t pid = Rand(); + uint16_t sn = Rand(); + + InsertVp8(sn, sn, true, pid, 0, 255); + InsertVp8(sn + 1, sn + 1, false, pid + 1, 1, 255, true); + InsertVp8(sn + 2, sn + 2, false, pid + 2, 0, 0); + InsertVp8(sn + 3, sn + 3, false, pid + 3, 1, 0); + + ASSERT_EQ(4UL, frames_from_callback_.size()); + CheckReferencesVp8(pid); + CheckReferencesVp8(pid + 1, pid); + CheckReferencesVp8(pid + 2, pid); + CheckReferencesVp8(pid + 3, pid + 1, pid + 2); +} + +// Test with 2 temporal layers in a 01 pattern. +TEST_F(TestRtpFrameReferenceFinder, Vp8TemporalLayersReordering_01) { + uint16_t pid = Rand(); + uint16_t sn = Rand(); + + InsertVp8(sn + 1, sn + 1, false, pid + 1, 1, 255, true); + InsertVp8(sn, sn, true, pid, 0, 255); + InsertVp8(sn + 3, sn + 3, false, pid + 3, 1, 0); + InsertVp8(sn + 5, sn + 5, false, pid + 5, 1, 1); + InsertVp8(sn + 2, sn + 2, false, pid + 2, 0, 0); + InsertVp8(sn + 4, sn + 4, false, pid + 4, 0, 1); + InsertVp8(sn + 6, sn + 6, false, pid + 6, 0, 2); + InsertVp8(sn + 7, sn + 7, false, pid + 7, 1, 2); + + ASSERT_EQ(8UL, frames_from_callback_.size()); + CheckReferencesVp8(pid); + CheckReferencesVp8(pid + 1, pid); + CheckReferencesVp8(pid + 2, pid); + CheckReferencesVp8(pid + 3, pid + 1, pid + 2); + CheckReferencesVp8(pid + 4, pid + 2); + CheckReferencesVp8(pid + 5, pid + 3, pid + 4); + CheckReferencesVp8(pid + 6, pid + 4); + CheckReferencesVp8(pid + 7, pid + 5, pid + 6); +} + +// Test with 3 temporal layers in a 0212 pattern. +TEST_F(TestRtpFrameReferenceFinder, Vp8TemporalLayers_0212) { + uint16_t pid = Rand(); + uint16_t sn = Rand(); + + InsertVp8(sn, sn, true, pid, 0, 55); + InsertVp8(sn + 1, sn + 1, false, pid + 1, 2, 55, true); + InsertVp8(sn + 2, sn + 2, false, pid + 2, 1, 55, true); + InsertVp8(sn + 3, sn + 3, false, pid + 3, 2, 55); + InsertVp8(sn + 4, sn + 4, false, pid + 4, 0, 56); + InsertVp8(sn + 5, sn + 5, false, pid + 5, 2, 56); + InsertVp8(sn + 6, sn + 6, false, pid + 6, 1, 56); + InsertVp8(sn + 7, sn + 7, false, pid + 7, 2, 56); + InsertVp8(sn + 8, sn + 8, false, pid + 8, 0, 57); + InsertVp8(sn + 9, sn + 9, false, pid + 9, 2, 57, true); + InsertVp8(sn + 10, sn + 10, false, pid + 10, 1, 57, true); + InsertVp8(sn + 11, sn + 11, false, pid + 11, 2, 57); + + ASSERT_EQ(12UL, frames_from_callback_.size()); + CheckReferencesVp8(pid); + CheckReferencesVp8(pid + 1, pid); + CheckReferencesVp8(pid + 2, pid); + CheckReferencesVp8(pid + 3, pid, pid + 1, pid + 2); + CheckReferencesVp8(pid + 4, pid); + CheckReferencesVp8(pid + 5, pid + 2, pid + 3, pid + 4); + CheckReferencesVp8(pid + 6, pid + 2, pid + 4); + CheckReferencesVp8(pid + 7, pid + 4, pid + 5, pid + 6); + CheckReferencesVp8(pid + 8, pid + 4); + CheckReferencesVp8(pid + 9, pid + 8); + CheckReferencesVp8(pid + 10, pid + 8); + CheckReferencesVp8(pid + 11, pid + 8, pid + 9, pid + 10); +} + +// Test with 3 temporal layers in a 0212 pattern. +TEST_F(TestRtpFrameReferenceFinder, Vp8TemporalLayersMissingFrame_0212) { + uint16_t pid = Rand(); + uint16_t sn = Rand(); + + InsertVp8(sn, sn, true, pid, 0, 55, false); + InsertVp8(sn + 2, sn + 2, false, pid + 2, 1, 55, true); + InsertVp8(sn + 3, sn + 3, false, pid + 3, 2, 55, false); + + ASSERT_EQ(2UL, frames_from_callback_.size()); + CheckReferencesVp8(pid); + CheckReferencesVp8(pid + 2, pid); +} + +// Test with 3 temporal layers in a 0212 pattern. +TEST_F(TestRtpFrameReferenceFinder, Vp8TemporalLayersReordering_0212) { + uint16_t pid = 126; + uint16_t sn = Rand(); + + InsertVp8(sn + 1, sn + 1, false, pid + 1, 2, 55, true); + InsertVp8(sn, sn, true, pid, 0, 55, false); + InsertVp8(sn + 2, sn + 2, false, pid + 2, 1, 55, true); + InsertVp8(sn + 4, sn + 4, false, pid + 4, 0, 56, false); + InsertVp8(sn + 5, sn + 5, false, pid + 5, 2, 56, false); + InsertVp8(sn + 3, sn + 3, false, pid + 3, 2, 55, false); + InsertVp8(sn + 7, sn + 7, false, pid + 7, 2, 56, false); + InsertVp8(sn + 9, sn + 9, false, pid + 9, 2, 57, true); + InsertVp8(sn + 6, sn + 6, false, pid + 6, 1, 56, false); + InsertVp8(sn + 8, sn + 8, false, pid + 8, 0, 57, false); + InsertVp8(sn + 11, sn + 11, false, pid + 11, 2, 57, false); + InsertVp8(sn + 10, sn + 10, false, pid + 10, 1, 57, true); + + ASSERT_EQ(12UL, frames_from_callback_.size()); + CheckReferencesVp8(pid); + CheckReferencesVp8(pid + 1, pid); + CheckReferencesVp8(pid + 2, pid); + CheckReferencesVp8(pid + 3, pid, pid + 1, pid + 2); + CheckReferencesVp8(pid + 4, pid); + CheckReferencesVp8(pid + 5, pid + 2, pid + 3, pid + 4); + CheckReferencesVp8(pid + 6, pid + 2, pid + 4); + CheckReferencesVp8(pid + 7, pid + 4, pid + 5, pid + 6); + CheckReferencesVp8(pid + 8, pid + 4); + CheckReferencesVp8(pid + 9, pid + 8); + CheckReferencesVp8(pid + 10, pid + 8); + CheckReferencesVp8(pid + 11, pid + 8, pid + 9, pid + 10); +} + +TEST_F(TestRtpFrameReferenceFinder, Vp8InsertManyFrames_0212) { + uint16_t pid = Rand(); + uint16_t sn = Rand(); + + const int keyframes_to_insert = 50; + const int frames_per_keyframe = 120; // Should be a multiple of 4. + uint8_t tl0 = 128; + + for (int k = 0; k < keyframes_to_insert; ++k) { + InsertVp8(sn, sn, true, pid, 0, tl0, false); + InsertVp8(sn + 1, sn + 1, false, pid + 1, 2, tl0, true); + InsertVp8(sn + 2, sn + 2, false, pid + 2, 1, tl0, true); + InsertVp8(sn + 3, sn + 3, false, pid + 3, 2, tl0, false); + CheckReferencesVp8(pid); + CheckReferencesVp8(pid + 1, pid); + CheckReferencesVp8(pid + 2, pid); + CheckReferencesVp8(pid + 3, pid, pid + 1, pid + 2); + frames_from_callback_.clear(); + ++tl0; + + for (int f = 4; f < frames_per_keyframe; f += 4) { + uint16_t sf = sn + f; + uint16_t pidf = pid + f; + + InsertVp8(sf, sf, false, pidf, 0, tl0, false); + InsertVp8(sf + 1, sf + 1, false, pidf + 1, 2, tl0, false); + InsertVp8(sf + 2, sf + 2, false, pidf + 2, 1, tl0, false); + InsertVp8(sf + 3, sf + 3, false, pidf + 3, 2, tl0, false); + CheckReferencesVp8(pidf, pidf - 4); + CheckReferencesVp8(pidf + 1, pidf, pidf - 1, pidf - 2); + CheckReferencesVp8(pidf + 2, pidf, pidf - 2); + CheckReferencesVp8(pidf + 3, pidf, pidf + 1, pidf + 2); + frames_from_callback_.clear(); + ++tl0; + } + + pid += frames_per_keyframe; + sn += frames_per_keyframe; + } +} + +TEST_F(TestRtpFrameReferenceFinder, Vp8LayerSync) { + uint16_t pid = Rand(); + uint16_t sn = Rand(); + + InsertVp8(sn, sn, true, pid, 0, 0, false); + InsertVp8(sn + 1, sn + 1, false, pid + 1, 1, 0, true); + InsertVp8(sn + 2, sn + 2, false, pid + 2, 0, 1, false); + ASSERT_EQ(3UL, frames_from_callback_.size()); + + InsertVp8(sn + 4, sn + 4, false, pid + 4, 0, 2, false); + InsertVp8(sn + 5, sn + 5, false, pid + 5, 1, 2, true); + InsertVp8(sn + 6, sn + 6, false, pid + 6, 0, 3, false); + InsertVp8(sn + 7, sn + 7, false, pid + 7, 1, 3, false); + + ASSERT_EQ(7UL, frames_from_callback_.size()); + CheckReferencesVp8(pid); + CheckReferencesVp8(pid + 1, pid); + CheckReferencesVp8(pid + 2, pid); + CheckReferencesVp8(pid + 4, pid + 2); + CheckReferencesVp8(pid + 5, pid + 4); + CheckReferencesVp8(pid + 6, pid + 4); + CheckReferencesVp8(pid + 7, pid + 6, pid + 5); +} + +TEST_F(TestRtpFrameReferenceFinder, Vp9GofInsertOneFrame) { + uint16_t pid = Rand(); + uint16_t sn = Rand(); + GofInfoVP9 ss; + ss.SetGofInfoVP9(kTemporalStructureMode1); + + InsertVp9Gof(sn, sn, true, pid, 0, 0, 0, false, &ss); + + CheckReferencesVp9(pid, 0); +} + +TEST_F(TestRtpFrameReferenceFinder, Vp9NoPictureIdReordered) { + uint16_t sn = 0xfffa; + + InsertVp9Gof(sn, sn + 2, true); + InsertVp9Gof(sn + 3, sn + 4, false); + InsertVp9Gof(sn + 9, sn + 9, false); + InsertVp9Gof(sn + 5, sn + 8, false); + InsertVp9Gof(sn + 12, sn + 12, true); + InsertVp9Gof(sn + 10, sn + 11, false); + InsertVp9Gof(sn + 13, sn + 17, false); + InsertVp9Gof(sn + 19, sn + 20, false); + InsertVp9Gof(sn + 21, sn + 21, false); + InsertVp9Gof(sn + 18, sn + 18, false); + + ASSERT_EQ(10UL, frames_from_callback_.size()); + CheckReferencesVp9(sn + 2, 0); + CheckReferencesVp9(sn + 4, 0, sn + 2); + CheckReferencesVp9(sn + 8, 0, sn + 4); + CheckReferencesVp9(sn + 9, 0, sn + 8); + CheckReferencesVp9(sn + 11, 0, sn + 9); + CheckReferencesVp9(sn + 12, 0); + CheckReferencesVp9(sn + 17, 0, sn + 12); + CheckReferencesVp9(sn + 18, 0, sn + 17); + CheckReferencesVp9(sn + 20, 0, sn + 18); + CheckReferencesVp9(sn + 21, 0, sn + 20); +} + +TEST_F(TestRtpFrameReferenceFinder, Vp9GofTemporalLayers_0) { + uint16_t pid = Rand(); + uint16_t sn = Rand(); + GofInfoVP9 ss; + ss.SetGofInfoVP9(kTemporalStructureMode1); // Only 1 spatial layer. + + InsertVp9Gof(sn, sn, true, pid, 0, 0, 0, false, &ss); + InsertVp9Gof(sn + 1, sn + 1, false, pid + 1, 0, 0, 1, false); + InsertVp9Gof(sn + 2, sn + 2, false, pid + 2, 0, 0, 2, false); + InsertVp9Gof(sn + 3, sn + 3, false, pid + 3, 0, 0, 3, false); + InsertVp9Gof(sn + 4, sn + 4, false, pid + 4, 0, 0, 4, false); + InsertVp9Gof(sn + 5, sn + 5, false, pid + 5, 0, 0, 5, false); + InsertVp9Gof(sn + 6, sn + 6, false, pid + 6, 0, 0, 6, false); + InsertVp9Gof(sn + 7, sn + 7, false, pid + 7, 0, 0, 7, false); + InsertVp9Gof(sn + 8, sn + 8, false, pid + 8, 0, 0, 8, false); + InsertVp9Gof(sn + 9, sn + 9, false, pid + 9, 0, 0, 9, false); + InsertVp9Gof(sn + 10, sn + 10, false, pid + 10, 0, 0, 10, false); + InsertVp9Gof(sn + 11, sn + 11, false, pid + 11, 0, 0, 11, false); + InsertVp9Gof(sn + 12, sn + 12, false, pid + 12, 0, 0, 12, false); + InsertVp9Gof(sn + 13, sn + 13, false, pid + 13, 0, 0, 13, false); + InsertVp9Gof(sn + 14, sn + 14, false, pid + 14, 0, 0, 14, false); + InsertVp9Gof(sn + 15, sn + 15, false, pid + 15, 0, 0, 15, false); + InsertVp9Gof(sn + 16, sn + 16, false, pid + 16, 0, 0, 16, false); + InsertVp9Gof(sn + 17, sn + 17, false, pid + 17, 0, 0, 17, false); + InsertVp9Gof(sn + 18, sn + 18, false, pid + 18, 0, 0, 18, false); + InsertVp9Gof(sn + 19, sn + 19, false, pid + 19, 0, 0, 19, false); + + ASSERT_EQ(20UL, frames_from_callback_.size()); + CheckReferencesVp9(pid, 0); + CheckReferencesVp9(pid + 1, 0, pid); + CheckReferencesVp9(pid + 2, 0, pid + 1); + CheckReferencesVp9(pid + 3, 0, pid + 2); + CheckReferencesVp9(pid + 4, 0, pid + 3); + CheckReferencesVp9(pid + 5, 0, pid + 4); + CheckReferencesVp9(pid + 6, 0, pid + 5); + CheckReferencesVp9(pid + 7, 0, pid + 6); + CheckReferencesVp9(pid + 8, 0, pid + 7); + CheckReferencesVp9(pid + 9, 0, pid + 8); + CheckReferencesVp9(pid + 10, 0, pid + 9); + CheckReferencesVp9(pid + 11, 0, pid + 10); + CheckReferencesVp9(pid + 12, 0, pid + 11); + CheckReferencesVp9(pid + 13, 0, pid + 12); + CheckReferencesVp9(pid + 14, 0, pid + 13); + CheckReferencesVp9(pid + 15, 0, pid + 14); + CheckReferencesVp9(pid + 16, 0, pid + 15); + CheckReferencesVp9(pid + 17, 0, pid + 16); + CheckReferencesVp9(pid + 18, 0, pid + 17); + CheckReferencesVp9(pid + 19, 0, pid + 18); +} + +TEST_F(TestRtpFrameReferenceFinder, Vp9GofTemporalLayersReordered_0) { + uint16_t pid = Rand(); + uint16_t sn = Rand(); + GofInfoVP9 ss; + ss.SetGofInfoVP9(kTemporalStructureMode1); // Only 1 spatial layer. + + InsertVp9Gof(sn + 2, sn + 2, false, pid + 2, 0, 0, 2, false); + InsertVp9Gof(sn + 1, sn + 1, false, pid + 1, 0, 0, 1, false); + InsertVp9Gof(sn, sn, true, pid, 0, 0, 0, false, &ss); + InsertVp9Gof(sn + 4, sn + 4, false, pid + 4, 0, 0, 4, false); + InsertVp9Gof(sn + 3, sn + 3, false, pid + 3, 0, 0, 3, false); + InsertVp9Gof(sn + 5, sn + 5, false, pid + 5, 0, 0, 5, false); + InsertVp9Gof(sn + 7, sn + 7, false, pid + 7, 0, 0, 7, false); + InsertVp9Gof(sn + 6, sn + 6, false, pid + 6, 0, 0, 6, false); + InsertVp9Gof(sn + 8, sn + 8, false, pid + 8, 0, 0, 8, false); + InsertVp9Gof(sn + 10, sn + 10, false, pid + 10, 0, 0, 10, false); + InsertVp9Gof(sn + 13, sn + 13, false, pid + 13, 0, 0, 13, false); + InsertVp9Gof(sn + 11, sn + 11, false, pid + 11, 0, 0, 11, false); + InsertVp9Gof(sn + 9, sn + 9, false, pid + 9, 0, 0, 9, false); + InsertVp9Gof(sn + 16, sn + 16, false, pid + 16, 0, 0, 16, false); + InsertVp9Gof(sn + 14, sn + 14, false, pid + 14, 0, 0, 14, false); + InsertVp9Gof(sn + 15, sn + 15, false, pid + 15, 0, 0, 15, false); + InsertVp9Gof(sn + 12, sn + 12, false, pid + 12, 0, 0, 12, false); + InsertVp9Gof(sn + 17, sn + 17, false, pid + 17, 0, 0, 17, false); + InsertVp9Gof(sn + 19, sn + 19, false, pid + 19, 0, 0, 19, false); + InsertVp9Gof(sn + 18, sn + 18, false, pid + 18, 0, 0, 18, false); + + ASSERT_EQ(20UL, frames_from_callback_.size()); + CheckReferencesVp9(pid, 0); + CheckReferencesVp9(pid + 1, 0, pid); + CheckReferencesVp9(pid + 2, 0, pid + 1); + CheckReferencesVp9(pid + 3, 0, pid + 2); + CheckReferencesVp9(pid + 4, 0, pid + 3); + CheckReferencesVp9(pid + 5, 0, pid + 4); + CheckReferencesVp9(pid + 6, 0, pid + 5); + CheckReferencesVp9(pid + 7, 0, pid + 6); + CheckReferencesVp9(pid + 8, 0, pid + 7); + CheckReferencesVp9(pid + 9, 0, pid + 8); + CheckReferencesVp9(pid + 10, 0, pid + 9); + CheckReferencesVp9(pid + 11, 0, pid + 10); + CheckReferencesVp9(pid + 12, 0, pid + 11); + CheckReferencesVp9(pid + 13, 0, pid + 12); + CheckReferencesVp9(pid + 14, 0, pid + 13); + CheckReferencesVp9(pid + 15, 0, pid + 14); + CheckReferencesVp9(pid + 16, 0, pid + 15); + CheckReferencesVp9(pid + 17, 0, pid + 16); + CheckReferencesVp9(pid + 18, 0, pid + 17); + CheckReferencesVp9(pid + 19, 0, pid + 18); +} + +TEST_F(TestRtpFrameReferenceFinder, Vp9GofSkipFramesTemporalLayers_01) { + uint16_t pid = Rand(); + uint16_t sn = Rand(); + GofInfoVP9 ss; + ss.SetGofInfoVP9(kTemporalStructureMode2); // 0101 pattern + + InsertVp9Gof(sn, sn, true, pid, 0, 0, 0, false, &ss); + InsertVp9Gof(sn + 1, sn + 1, false, pid + 1, 0, 1, 0, false); + // Skip GOF with tl0 1 + InsertVp9Gof(sn + 4, sn + 4, true, pid + 4, 0, 0, 2, false, &ss); + InsertVp9Gof(sn + 5, sn + 5, false, pid + 5, 0, 1, 2, false); + // Skip GOF with tl0 3 + // Skip GOF with tl0 4 + InsertVp9Gof(sn + 10, sn + 10, false, pid + 10, 0, 0, 5, false, &ss); + InsertVp9Gof(sn + 11, sn + 11, false, pid + 11, 0, 1, 5, false); + + ASSERT_EQ(6UL, frames_from_callback_.size()); + CheckReferencesVp9(pid, 0); + CheckReferencesVp9(pid + 1, 0, pid); + CheckReferencesVp9(pid + 4, 0); + CheckReferencesVp9(pid + 5, 0, pid + 4); + CheckReferencesVp9(pid + 10, 0, pid + 8); + CheckReferencesVp9(pid + 11, 0, pid + 10); +} + +TEST_F(TestRtpFrameReferenceFinder, Vp9GofSkipFramesTemporalLayers_0212) { + uint16_t pid = Rand(); + uint16_t sn = Rand(); + GofInfoVP9 ss; + ss.SetGofInfoVP9(kTemporalStructureMode3); // 02120212 pattern + + InsertVp9Gof(sn, sn, true, pid, 0, 0, 0, false, &ss); + InsertVp9Gof(sn + 1, sn + 1, false, pid + 1, 0, 2, 0, false); + InsertVp9Gof(sn + 2, sn + 2, false, pid + 2, 0, 1, 0, false); + InsertVp9Gof(sn + 3, sn + 3, false, pid + 3, 0, 2, 0, false); + + ASSERT_EQ(4UL, frames_from_callback_.size()); + CheckReferencesVp9(pid, 0); + CheckReferencesVp9(pid + 1, 0, pid); + CheckReferencesVp9(pid + 2, 0, pid); + CheckReferencesVp9(pid + 3, 0, pid + 1, pid + 2); + + // Skip frames with tl0 = 1 + + InsertVp9Gof(sn + 8, sn + 8, true, pid + 8, 0, 0, 2, false, &ss); + InsertVp9Gof(sn + 9, sn + 9, false, pid + 9, 0, 2, 2, false); + InsertVp9Gof(sn + 10, sn + 10, false, pid + 10, 0, 1, 2, false); + InsertVp9Gof(sn + 11, sn + 11, false, pid + 11, 0, 2, 2, false); + + ASSERT_EQ(8UL, frames_from_callback_.size()); + CheckReferencesVp9(pid + 8, 0); + CheckReferencesVp9(pid + 9, 0, pid + 8); + CheckReferencesVp9(pid + 10, 0, pid + 8); + CheckReferencesVp9(pid + 11, 0, pid + 9, pid + 10); + + // Now insert frames with tl0 = 1 + InsertVp9Gof(sn + 4, sn + 4, true, pid + 4, 0, 0, 1, false, &ss); + InsertVp9Gof(sn + 7, sn + 7, false, pid + 7, 0, 2, 1, false); + + ASSERT_EQ(9UL, frames_from_callback_.size()); + CheckReferencesVp9(pid + 4, 0); + + // Rest of frames belonging to tl0 = 1 + InsertVp9Gof(sn + 5, sn + 5, false, pid + 5, 0, 2, 1, false); + InsertVp9Gof(sn + 6, sn + 6, false, pid + 6, 0, 1, 1, true); // up-switch + + ASSERT_EQ(12UL, frames_from_callback_.size()); + CheckReferencesVp9(pid + 5, 0, pid + 4); + CheckReferencesVp9(pid + 6, 0, pid + 4); + CheckReferencesVp9(pid + 7, 0, pid + 6); +} + +TEST_F(TestRtpFrameReferenceFinder, Vp9GofTemporalLayers_01) { + uint16_t pid = Rand(); + uint16_t sn = Rand(); + GofInfoVP9 ss; + ss.SetGofInfoVP9(kTemporalStructureMode2); // 0101 pattern + + InsertVp9Gof(sn, sn, true, pid, 0, 0, 0, false, &ss); + InsertVp9Gof(sn + 1, sn + 1, false, pid + 1, 0, 1, 0, false); + InsertVp9Gof(sn + 2, sn + 2, false, pid + 2, 0, 0, 1, false); + InsertVp9Gof(sn + 3, sn + 3, false, pid + 3, 0, 1, 1, false); + InsertVp9Gof(sn + 4, sn + 4, false, pid + 4, 0, 0, 2, false); + InsertVp9Gof(sn + 5, sn + 5, false, pid + 5, 0, 1, 2, false); + InsertVp9Gof(sn + 6, sn + 6, false, pid + 6, 0, 0, 3, false); + InsertVp9Gof(sn + 7, sn + 7, false, pid + 7, 0, 1, 3, false); + InsertVp9Gof(sn + 8, sn + 8, false, pid + 8, 0, 0, 4, false); + InsertVp9Gof(sn + 9, sn + 9, false, pid + 9, 0, 1, 4, false); + InsertVp9Gof(sn + 10, sn + 10, false, pid + 10, 0, 0, 5, false); + InsertVp9Gof(sn + 11, sn + 11, false, pid + 11, 0, 1, 5, false); + InsertVp9Gof(sn + 12, sn + 12, false, pid + 12, 0, 0, 6, false); + InsertVp9Gof(sn + 13, sn + 13, false, pid + 13, 0, 1, 6, false); + InsertVp9Gof(sn + 14, sn + 14, false, pid + 14, 0, 0, 7, false); + InsertVp9Gof(sn + 15, sn + 15, false, pid + 15, 0, 1, 7, false); + InsertVp9Gof(sn + 16, sn + 16, false, pid + 16, 0, 0, 8, false); + InsertVp9Gof(sn + 17, sn + 17, false, pid + 17, 0, 1, 8, false); + InsertVp9Gof(sn + 18, sn + 18, false, pid + 18, 0, 0, 9, false); + InsertVp9Gof(sn + 19, sn + 19, false, pid + 19, 0, 1, 9, false); + + ASSERT_EQ(20UL, frames_from_callback_.size()); + CheckReferencesVp9(pid, 0); + CheckReferencesVp9(pid + 1, 0, pid); + CheckReferencesVp9(pid + 2, 0, pid); + CheckReferencesVp9(pid + 3, 0, pid + 2); + CheckReferencesVp9(pid + 4, 0, pid + 2); + CheckReferencesVp9(pid + 5, 0, pid + 4); + CheckReferencesVp9(pid + 6, 0, pid + 4); + CheckReferencesVp9(pid + 7, 0, pid + 6); + CheckReferencesVp9(pid + 8, 0, pid + 6); + CheckReferencesVp9(pid + 9, 0, pid + 8); + CheckReferencesVp9(pid + 10, 0, pid + 8); + CheckReferencesVp9(pid + 11, 0, pid + 10); + CheckReferencesVp9(pid + 12, 0, pid + 10); + CheckReferencesVp9(pid + 13, 0, pid + 12); + CheckReferencesVp9(pid + 14, 0, pid + 12); + CheckReferencesVp9(pid + 15, 0, pid + 14); + CheckReferencesVp9(pid + 16, 0, pid + 14); + CheckReferencesVp9(pid + 17, 0, pid + 16); + CheckReferencesVp9(pid + 18, 0, pid + 16); + CheckReferencesVp9(pid + 19, 0, pid + 18); +} + +TEST_F(TestRtpFrameReferenceFinder, Vp9GofTemporalLayersReordered_01) { + uint16_t pid = Rand(); + uint16_t sn = Rand(); + GofInfoVP9 ss; + ss.SetGofInfoVP9(kTemporalStructureMode2); // 01 pattern + + InsertVp9Gof(sn + 1, sn + 1, false, pid + 1, 0, 1, 0, false); + InsertVp9Gof(sn, sn, true, pid, 0, 0, 0, false, &ss); + InsertVp9Gof(sn + 2, sn + 2, false, pid + 2, 0, 0, 1, false); + InsertVp9Gof(sn + 4, sn + 4, false, pid + 4, 0, 0, 2, false); + InsertVp9Gof(sn + 3, sn + 3, false, pid + 3, 0, 1, 1, false); + InsertVp9Gof(sn + 5, sn + 5, false, pid + 5, 0, 1, 2, false); + InsertVp9Gof(sn + 7, sn + 7, false, pid + 7, 0, 1, 3, false); + InsertVp9Gof(sn + 6, sn + 6, false, pid + 6, 0, 0, 3, false); + InsertVp9Gof(sn + 10, sn + 10, false, pid + 10, 0, 0, 5, false); + InsertVp9Gof(sn + 8, sn + 8, false, pid + 8, 0, 0, 4, false); + InsertVp9Gof(sn + 9, sn + 9, false, pid + 9, 0, 1, 4, false); + InsertVp9Gof(sn + 11, sn + 11, false, pid + 11, 0, 1, 5, false); + InsertVp9Gof(sn + 13, sn + 13, false, pid + 13, 0, 1, 6, false); + InsertVp9Gof(sn + 16, sn + 16, false, pid + 16, 0, 0, 8, false); + InsertVp9Gof(sn + 12, sn + 12, false, pid + 12, 0, 0, 6, false); + InsertVp9Gof(sn + 14, sn + 14, false, pid + 14, 0, 0, 7, false); + InsertVp9Gof(sn + 17, sn + 17, false, pid + 17, 0, 1, 8, false); + InsertVp9Gof(sn + 19, sn + 19, false, pid + 19, 0, 1, 9, false); + InsertVp9Gof(sn + 15, sn + 15, false, pid + 15, 0, 1, 7, false); + InsertVp9Gof(sn + 18, sn + 18, false, pid + 18, 0, 0, 9, false); + + ASSERT_EQ(20UL, frames_from_callback_.size()); + CheckReferencesVp9(pid, 0); + CheckReferencesVp9(pid + 1, 0, pid); + CheckReferencesVp9(pid + 2, 0, pid); + CheckReferencesVp9(pid + 3, 0, pid + 2); + CheckReferencesVp9(pid + 4, 0, pid + 2); + CheckReferencesVp9(pid + 5, 0, pid + 4); + CheckReferencesVp9(pid + 6, 0, pid + 4); + CheckReferencesVp9(pid + 7, 0, pid + 6); + CheckReferencesVp9(pid + 8, 0, pid + 6); + CheckReferencesVp9(pid + 9, 0, pid + 8); + CheckReferencesVp9(pid + 10, 0, pid + 8); + CheckReferencesVp9(pid + 11, 0, pid + 10); + CheckReferencesVp9(pid + 12, 0, pid + 10); + CheckReferencesVp9(pid + 13, 0, pid + 12); + CheckReferencesVp9(pid + 14, 0, pid + 12); + CheckReferencesVp9(pid + 15, 0, pid + 14); + CheckReferencesVp9(pid + 16, 0, pid + 14); + CheckReferencesVp9(pid + 17, 0, pid + 16); + CheckReferencesVp9(pid + 18, 0, pid + 16); + CheckReferencesVp9(pid + 19, 0, pid + 18); +} + +TEST_F(TestRtpFrameReferenceFinder, Vp9GofTemporalLayers_0212) { + uint16_t pid = Rand(); + uint16_t sn = Rand(); + GofInfoVP9 ss; + ss.SetGofInfoVP9(kTemporalStructureMode3); // 0212 pattern + + InsertVp9Gof(sn, sn, true, pid, 0, 0, 0, false, &ss); + InsertVp9Gof(sn + 1, sn + 1, false, pid + 1, 0, 2, 0, false); + InsertVp9Gof(sn + 2, sn + 2, false, pid + 2, 0, 1, 0, false); + InsertVp9Gof(sn + 3, sn + 3, false, pid + 3, 0, 2, 0, false); + InsertVp9Gof(sn + 4, sn + 4, false, pid + 4, 0, 0, 1, false); + InsertVp9Gof(sn + 5, sn + 5, false, pid + 5, 0, 2, 1, false); + InsertVp9Gof(sn + 6, sn + 6, false, pid + 6, 0, 1, 1, false); + InsertVp9Gof(sn + 7, sn + 7, false, pid + 7, 0, 2, 1, false); + InsertVp9Gof(sn + 8, sn + 8, false, pid + 8, 0, 0, 2, false); + InsertVp9Gof(sn + 9, sn + 9, false, pid + 9, 0, 2, 2, false); + InsertVp9Gof(sn + 10, sn + 10, false, pid + 10, 0, 1, 2, false); + InsertVp9Gof(sn + 11, sn + 11, false, pid + 11, 0, 2, 2, false); + InsertVp9Gof(sn + 12, sn + 12, false, pid + 12, 0, 0, 3, false); + InsertVp9Gof(sn + 13, sn + 13, false, pid + 13, 0, 2, 3, false); + InsertVp9Gof(sn + 14, sn + 14, false, pid + 14, 0, 1, 3, false); + InsertVp9Gof(sn + 15, sn + 15, false, pid + 15, 0, 2, 3, false); + InsertVp9Gof(sn + 16, sn + 16, false, pid + 16, 0, 0, 4, false); + InsertVp9Gof(sn + 17, sn + 17, false, pid + 17, 0, 2, 4, false); + InsertVp9Gof(sn + 18, sn + 18, false, pid + 18, 0, 1, 4, false); + InsertVp9Gof(sn + 19, sn + 19, false, pid + 19, 0, 2, 4, false); + + ASSERT_EQ(20UL, frames_from_callback_.size()); + CheckReferencesVp9(pid, 0); + CheckReferencesVp9(pid + 1, 0, pid); + CheckReferencesVp9(pid + 2, 0, pid); + CheckReferencesVp9(pid + 3, 0, pid + 1, pid + 2); + CheckReferencesVp9(pid + 4, 0, pid); + CheckReferencesVp9(pid + 5, 0, pid + 4); + CheckReferencesVp9(pid + 6, 0, pid + 4); + CheckReferencesVp9(pid + 7, 0, pid + 5, pid + 6); + CheckReferencesVp9(pid + 8, 0, pid + 4); + CheckReferencesVp9(pid + 9, 0, pid + 8); + CheckReferencesVp9(pid + 10, 0, pid + 8); + CheckReferencesVp9(pid + 11, 0, pid + 9, pid + 10); + CheckReferencesVp9(pid + 12, 0, pid + 8); + CheckReferencesVp9(pid + 13, 0, pid + 12); + CheckReferencesVp9(pid + 14, 0, pid + 12); + CheckReferencesVp9(pid + 15, 0, pid + 13, pid + 14); + CheckReferencesVp9(pid + 16, 0, pid + 12); + CheckReferencesVp9(pid + 17, 0, pid + 16); + CheckReferencesVp9(pid + 18, 0, pid + 16); + CheckReferencesVp9(pid + 19, 0, pid + 17, pid + 18); +} + +TEST_F(TestRtpFrameReferenceFinder, Vp9GofTemporalLayersReordered_0212) { + uint16_t pid = Rand(); + uint16_t sn = Rand(); + GofInfoVP9 ss; + ss.SetGofInfoVP9(kTemporalStructureMode3); // 0212 pattern + + InsertVp9Gof(sn + 2, sn + 2, false, pid + 2, 0, 1, 0, false); + InsertVp9Gof(sn + 1, sn + 1, false, pid + 1, 0, 2, 0, false); + InsertVp9Gof(sn, sn, true, pid, 0, 0, 0, false, &ss); + InsertVp9Gof(sn + 3, sn + 3, false, pid + 3, 0, 2, 0, false); + InsertVp9Gof(sn + 6, sn + 6, false, pid + 6, 0, 1, 1, false); + InsertVp9Gof(sn + 5, sn + 5, false, pid + 5, 0, 2, 1, false); + InsertVp9Gof(sn + 4, sn + 4, false, pid + 4, 0, 0, 1, false); + InsertVp9Gof(sn + 9, sn + 9, false, pid + 9, 0, 2, 2, false); + InsertVp9Gof(sn + 7, sn + 7, false, pid + 7, 0, 2, 1, false); + InsertVp9Gof(sn + 8, sn + 8, false, pid + 8, 0, 0, 2, false); + InsertVp9Gof(sn + 11, sn + 11, false, pid + 11, 0, 2, 2, false); + InsertVp9Gof(sn + 10, sn + 10, false, pid + 10, 0, 1, 2, false); + InsertVp9Gof(sn + 13, sn + 13, false, pid + 13, 0, 2, 3, false); + InsertVp9Gof(sn + 12, sn + 12, false, pid + 12, 0, 0, 3, false); + InsertVp9Gof(sn + 14, sn + 14, false, pid + 14, 0, 1, 3, false); + InsertVp9Gof(sn + 16, sn + 16, false, pid + 16, 0, 0, 4, false); + InsertVp9Gof(sn + 15, sn + 15, false, pid + 15, 0, 2, 3, false); + InsertVp9Gof(sn + 17, sn + 17, false, pid + 17, 0, 2, 4, false); + InsertVp9Gof(sn + 19, sn + 19, false, pid + 19, 0, 2, 4, false); + InsertVp9Gof(sn + 18, sn + 18, false, pid + 18, 0, 1, 4, false); + + ASSERT_EQ(20UL, frames_from_callback_.size()); + CheckReferencesVp9(pid, 0); + CheckReferencesVp9(pid + 1, 0, pid); + CheckReferencesVp9(pid + 2, 0, pid); + CheckReferencesVp9(pid + 3, 0, pid + 1, pid + 2); + CheckReferencesVp9(pid + 4, 0, pid); + CheckReferencesVp9(pid + 5, 0, pid + 4); + CheckReferencesVp9(pid + 6, 0, pid + 4); + CheckReferencesVp9(pid + 7, 0, pid + 5, pid + 6); + CheckReferencesVp9(pid + 8, 0, pid + 4); + CheckReferencesVp9(pid + 9, 0, pid + 8); + CheckReferencesVp9(pid + 10, 0, pid + 8); + CheckReferencesVp9(pid + 11, 0, pid + 9, pid + 10); + CheckReferencesVp9(pid + 12, 0, pid + 8); + CheckReferencesVp9(pid + 13, 0, pid + 12); + CheckReferencesVp9(pid + 14, 0, pid + 12); + CheckReferencesVp9(pid + 15, 0, pid + 13, pid + 14); + CheckReferencesVp9(pid + 16, 0, pid + 12); + CheckReferencesVp9(pid + 17, 0, pid + 16); + CheckReferencesVp9(pid + 18, 0, pid + 16); + CheckReferencesVp9(pid + 19, 0, pid + 17, pid + 18); +} + +TEST_F(TestRtpFrameReferenceFinder, Vp9GofTemporalLayersUpSwitch_02120212) { + uint16_t pid = Rand(); + uint16_t sn = Rand(); + GofInfoVP9 ss; + ss.SetGofInfoVP9(kTemporalStructureMode4); // 02120212 pattern + + InsertVp9Gof(sn, sn, true, pid, 0, 0, 0, false, &ss); + InsertVp9Gof(sn + 1, sn + 1, false, pid + 1, 0, 2, 0, false); + InsertVp9Gof(sn + 2, sn + 2, false, pid + 2, 0, 1, 0, false); + InsertVp9Gof(sn + 3, sn + 3, false, pid + 3, 0, 2, 0, false); + InsertVp9Gof(sn + 4, sn + 4, false, pid + 4, 0, 0, 1, false); + InsertVp9Gof(sn + 5, sn + 5, false, pid + 5, 0, 2, 1, false); + InsertVp9Gof(sn + 6, sn + 6, false, pid + 6, 0, 1, 1, true); + InsertVp9Gof(sn + 7, sn + 7, false, pid + 7, 0, 2, 1, false); + InsertVp9Gof(sn + 8, sn + 8, false, pid + 8, 0, 0, 2, true); + InsertVp9Gof(sn + 9, sn + 9, false, pid + 9, 0, 2, 2, false); + InsertVp9Gof(sn + 10, sn + 10, false, pid + 10, 0, 1, 2, false); + InsertVp9Gof(sn + 11, sn + 11, false, pid + 11, 0, 2, 2, true); + InsertVp9Gof(sn + 12, sn + 12, false, pid + 12, 0, 0, 3, false); + InsertVp9Gof(sn + 13, sn + 13, false, pid + 13, 0, 2, 3, false); + InsertVp9Gof(sn + 14, sn + 14, false, pid + 14, 0, 1, 3, false); + InsertVp9Gof(sn + 15, sn + 15, false, pid + 15, 0, 2, 3, false); + + ASSERT_EQ(16UL, frames_from_callback_.size()); + CheckReferencesVp9(pid, 0); + CheckReferencesVp9(pid + 1, 0, pid); + CheckReferencesVp9(pid + 2, 0, pid); + CheckReferencesVp9(pid + 3, 0, pid + 1, pid + 2); + CheckReferencesVp9(pid + 4, 0, pid); + CheckReferencesVp9(pid + 5, 0, pid + 3, pid + 4); + CheckReferencesVp9(pid + 6, 0, pid + 2, pid + 4); + CheckReferencesVp9(pid + 7, 0, pid + 6); + CheckReferencesVp9(pid + 8, 0, pid + 4); + CheckReferencesVp9(pid + 9, 0, pid + 8); + CheckReferencesVp9(pid + 10, 0, pid + 8); + CheckReferencesVp9(pid + 11, 0, pid + 9, pid + 10); + CheckReferencesVp9(pid + 12, 0, pid + 8); + CheckReferencesVp9(pid + 13, 0, pid + 11, pid + 12); + CheckReferencesVp9(pid + 14, 0, pid + 10, pid + 12); + CheckReferencesVp9(pid + 15, 0, pid + 13, pid + 14); +} + +TEST_F(TestRtpFrameReferenceFinder, + Vp9GofTemporalLayersUpSwitchReordered_02120212) { + uint16_t pid = Rand(); + uint16_t sn = Rand(); + GofInfoVP9 ss; + ss.SetGofInfoVP9(kTemporalStructureMode4); // 02120212 pattern + + InsertVp9Gof(sn + 1, sn + 1, false, pid + 1, 0, 2, 0, false); + InsertVp9Gof(sn, sn, true, pid, 0, 0, 0, false, &ss); + InsertVp9Gof(sn + 4, sn + 4, false, pid + 4, 0, 0, 1, false); + InsertVp9Gof(sn + 2, sn + 2, false, pid + 2, 0, 1, 0, false); + InsertVp9Gof(sn + 5, sn + 5, false, pid + 5, 0, 2, 1, false); + InsertVp9Gof(sn + 3, sn + 3, false, pid + 3, 0, 2, 0, false); + InsertVp9Gof(sn + 7, sn + 7, false, pid + 7, 0, 2, 1, false); + InsertVp9Gof(sn + 9, sn + 9, false, pid + 9, 0, 2, 2, false); + InsertVp9Gof(sn + 6, sn + 6, false, pid + 6, 0, 1, 1, true); + InsertVp9Gof(sn + 12, sn + 12, false, pid + 12, 0, 0, 3, false); + InsertVp9Gof(sn + 10, sn + 10, false, pid + 10, 0, 1, 2, false); + InsertVp9Gof(sn + 8, sn + 8, false, pid + 8, 0, 0, 2, true); + InsertVp9Gof(sn + 11, sn + 11, false, pid + 11, 0, 2, 2, true); + InsertVp9Gof(sn + 13, sn + 13, false, pid + 13, 0, 2, 3, false); + InsertVp9Gof(sn + 15, sn + 15, false, pid + 15, 0, 2, 3, false); + InsertVp9Gof(sn + 14, sn + 14, false, pid + 14, 0, 1, 3, false); + + ASSERT_EQ(16UL, frames_from_callback_.size()); + CheckReferencesVp9(pid, 0); + CheckReferencesVp9(pid + 1, 0, pid); + CheckReferencesVp9(pid + 2, 0, pid); + CheckReferencesVp9(pid + 3, 0, pid + 1, pid + 2); + CheckReferencesVp9(pid + 4, 0, pid); + CheckReferencesVp9(pid + 5, 0, pid + 3, pid + 4); + CheckReferencesVp9(pid + 6, 0, pid + 2, pid + 4); + CheckReferencesVp9(pid + 7, 0, pid + 6); + CheckReferencesVp9(pid + 8, 0, pid + 4); + CheckReferencesVp9(pid + 9, 0, pid + 8); + CheckReferencesVp9(pid + 10, 0, pid + 8); + CheckReferencesVp9(pid + 11, 0, pid + 9, pid + 10); + CheckReferencesVp9(pid + 12, 0, pid + 8); + CheckReferencesVp9(pid + 13, 0, pid + 11, pid + 12); + CheckReferencesVp9(pid + 14, 0, pid + 10, pid + 12); + CheckReferencesVp9(pid + 15, 0, pid + 13, pid + 14); +} + +TEST_F(TestRtpFrameReferenceFinder, Vp9GofTemporalLayersReordered_01_0212) { + uint16_t pid = Rand(); + uint16_t sn = Rand(); + GofInfoVP9 ss; + ss.SetGofInfoVP9(kTemporalStructureMode2); // 01 pattern + + InsertVp9Gof(sn + 1, sn + 1, false, pid + 1, 0, 1, 0, false); + InsertVp9Gof(sn, sn, true, pid, 0, 0, 0, false, &ss); + InsertVp9Gof(sn + 3, sn + 3, false, pid + 3, 0, 1, 1, false); + InsertVp9Gof(sn + 6, sn + 6, false, pid + 6, 0, 1, 2, false); + ss.SetGofInfoVP9(kTemporalStructureMode3); // 0212 pattern + InsertVp9Gof(sn + 4, sn + 4, false, pid + 4, 0, 0, 2, false, &ss); + InsertVp9Gof(sn + 2, sn + 2, false, pid + 2, 0, 0, 1, false); + InsertVp9Gof(sn + 5, sn + 5, false, pid + 5, 0, 2, 2, false); + InsertVp9Gof(sn + 8, sn + 8, false, pid + 8, 0, 0, 3, false); + InsertVp9Gof(sn + 10, sn + 10, false, pid + 10, 0, 1, 3, false); + InsertVp9Gof(sn + 7, sn + 7, false, pid + 7, 0, 2, 2, false); + InsertVp9Gof(sn + 11, sn + 11, false, pid + 11, 0, 2, 3, false); + InsertVp9Gof(sn + 9, sn + 9, false, pid + 9, 0, 2, 3, false); + + ASSERT_EQ(12UL, frames_from_callback_.size()); + CheckReferencesVp9(pid, 0); + CheckReferencesVp9(pid + 1, 0, pid); + CheckReferencesVp9(pid + 2, 0, pid); + CheckReferencesVp9(pid + 3, 0, pid + 2); + CheckReferencesVp9(pid + 4, 0, pid); + CheckReferencesVp9(pid + 5, 0, pid + 4); + CheckReferencesVp9(pid + 6, 0, pid + 4); + CheckReferencesVp9(pid + 7, 0, pid + 5, pid + 6); + CheckReferencesVp9(pid + 8, 0, pid + 4); + CheckReferencesVp9(pid + 9, 0, pid + 8); + CheckReferencesVp9(pid + 10, 0, pid + 8); + CheckReferencesVp9(pid + 11, 0, pid + 9, pid + 10); +} + +TEST_F(TestRtpFrameReferenceFinder, Vp9FlexibleModeOneFrame) { + uint16_t pid = Rand(); + uint16_t sn = Rand(); + + InsertVp9Flex(sn, sn, true, pid, 0, 0, 0, false); + + ASSERT_EQ(1UL, frames_from_callback_.size()); + CheckReferencesVp9(pid, 0); +} + +TEST_F(TestRtpFrameReferenceFinder, Vp9FlexibleModeTwoSpatialLayers) { + uint16_t pid = Rand(); + uint16_t sn = Rand(); + + InsertVp9Flex(sn, sn, true, pid, 0, 0, 0, false); + InsertVp9Flex(sn + 1, sn + 1, true, pid, 1, 0, 0, true); + InsertVp9Flex(sn + 2, sn + 2, false, pid + 1, 1, 0, 0, false, {1}); + InsertVp9Flex(sn + 3, sn + 3, false, pid + 2, 0, 0, 1, false, {2}); + InsertVp9Flex(sn + 4, sn + 4, false, pid + 2, 1, 0, 1, false, {1}); + InsertVp9Flex(sn + 5, sn + 5, false, pid + 3, 1, 0, 1, false, {1}); + InsertVp9Flex(sn + 6, sn + 6, false, pid + 4, 0, 0, 2, false, {2}); + InsertVp9Flex(sn + 7, sn + 7, false, pid + 4, 1, 0, 2, false, {1}); + InsertVp9Flex(sn + 8, sn + 8, false, pid + 5, 1, 0, 2, false, {1}); + InsertVp9Flex(sn + 9, sn + 9, false, pid + 6, 0, 0, 3, false, {2}); + InsertVp9Flex(sn + 10, sn + 10, false, pid + 6, 1, 0, 3, false, {1}); + InsertVp9Flex(sn + 11, sn + 11, false, pid + 7, 1, 0, 3, false, {1}); + InsertVp9Flex(sn + 12, sn + 12, false, pid + 8, 0, 0, 4, false, {2}); + InsertVp9Flex(sn + 13, sn + 13, false, pid + 8, 1, 0, 4, false, {1}); + + ASSERT_EQ(14UL, frames_from_callback_.size()); + CheckReferencesVp9(pid, 0); + CheckReferencesVp9(pid, 1); + CheckReferencesVp9(pid + 1, 1, pid); + CheckReferencesVp9(pid + 2, 0, pid); + CheckReferencesVp9(pid + 2, 1, pid + 1); + CheckReferencesVp9(pid + 3, 1, pid + 2); + CheckReferencesVp9(pid + 4, 0, pid + 2); + CheckReferencesVp9(pid + 4, 1, pid + 3); + CheckReferencesVp9(pid + 5, 1, pid + 4); + CheckReferencesVp9(pid + 6, 0, pid + 4); + CheckReferencesVp9(pid + 6, 1, pid + 5); + CheckReferencesVp9(pid + 7, 1, pid + 6); + CheckReferencesVp9(pid + 8, 0, pid + 6); + CheckReferencesVp9(pid + 8, 1, pid + 7); +} + +TEST_F(TestRtpFrameReferenceFinder, Vp9FlexibleModeTwoSpatialLayersReordered) { + uint16_t pid = Rand(); + uint16_t sn = Rand(); + + InsertVp9Flex(sn + 1, sn + 1, true, pid, 1, 0, 0, true); + InsertVp9Flex(sn + 2, sn + 2, false, pid + 1, 1, 0, 0, false, {1}); + InsertVp9Flex(sn, sn, true, pid, 0, 0, 0, false); + InsertVp9Flex(sn + 4, sn + 4, false, pid + 2, 1, 0, 1, false, {1}); + InsertVp9Flex(sn + 5, sn + 5, false, pid + 3, 1, 0, 1, false, {1}); + InsertVp9Flex(sn + 3, sn + 3, false, pid + 2, 0, 0, 1, false, {2}); + InsertVp9Flex(sn + 7, sn + 7, false, pid + 4, 1, 0, 2, false, {1}); + InsertVp9Flex(sn + 6, sn + 6, false, pid + 4, 0, 0, 2, false, {2}); + InsertVp9Flex(sn + 8, sn + 8, false, pid + 5, 1, 0, 2, false, {1}); + InsertVp9Flex(sn + 9, sn + 9, false, pid + 6, 0, 0, 3, false, {2}); + InsertVp9Flex(sn + 11, sn + 11, false, pid + 7, 1, 0, 3, false, {1}); + InsertVp9Flex(sn + 10, sn + 10, false, pid + 6, 1, 0, 3, false, {1}); + InsertVp9Flex(sn + 13, sn + 13, false, pid + 8, 1, 0, 4, false, {1}); + InsertVp9Flex(sn + 12, sn + 12, false, pid + 8, 0, 0, 4, false, {2}); + + ASSERT_EQ(14UL, frames_from_callback_.size()); + CheckReferencesVp9(pid, 0); + CheckReferencesVp9(pid, 1); + CheckReferencesVp9(pid + 1, 1, pid); + CheckReferencesVp9(pid + 2, 0, pid); + CheckReferencesVp9(pid + 2, 1, pid + 1); + CheckReferencesVp9(pid + 3, 1, pid + 2); + CheckReferencesVp9(pid + 4, 0, pid + 2); + CheckReferencesVp9(pid + 4, 1, pid + 3); + CheckReferencesVp9(pid + 5, 1, pid + 4); + CheckReferencesVp9(pid + 6, 0, pid + 4); + CheckReferencesVp9(pid + 6, 1, pid + 5); + CheckReferencesVp9(pid + 7, 1, pid + 6); + CheckReferencesVp9(pid + 8, 0, pid + 6); + CheckReferencesVp9(pid + 8, 1, pid + 7); +} + +} // namespace video_coding +} // namespace webrtc diff --git a/webrtc/modules/video_coding/video_packet_buffer_unittest.cc b/webrtc/modules/video_coding/video_packet_buffer_unittest.cc index ee9a853a24..f4ae5c7508 100644 --- a/webrtc/modules/video_coding/video_packet_buffer_unittest.cc +++ b/webrtc/modules/video_coding/video_packet_buffer_unittest.cc @@ -9,7 +9,6 @@ */ #include -#include #include #include #include @@ -24,274 +23,83 @@ namespace webrtc { namespace video_coding { class TestPacketBuffer : public ::testing::Test, - public OnCompleteFrameCallback { + public OnReceivedFrameCallback { protected: TestPacketBuffer() - : rand_(0x8739211), + : rand_(0x7732213), clock_(new SimulatedClock(0)), - packet_buffer_(new PacketBuffer(clock_.get(), - kStartSize, - kMaxSize, - this)), - frames_from_callback_(FrameComp()), - dummy_data_(new uint8_t[kDummyDataSize]()) {} + packet_buffer_( + PacketBuffer::Create(clock_.get(), kStartSize, kMaxSize, this)) {} - uint16_t Rand() { return rand_.Rand(std::numeric_limits::max()); } + uint16_t Rand() { return rand_.Rand(); } - void OnCompleteFrame(std::unique_ptr frame) override { - uint16_t pid = frame->picture_id; - uint16_t sidx = frame->spatial_layer; - auto frame_it = frames_from_callback_.find(std::make_pair(pid, sidx)); - if (frame_it != frames_from_callback_.end()) { - ADD_FAILURE() << "Already received frame with (pid:sidx): (" - << pid << ":" << sidx << ")"; + void OnReceivedFrame(std::unique_ptr frame) override { + uint16_t first_seq_num = frame->first_seq_num(); + if (frames_from_callback_.find(first_seq_num) != + frames_from_callback_.end()) { + ADD_FAILURE() << "Already received frame with first sequence number " + << first_seq_num << "."; return; } - frames_from_callback_.insert( - std::make_pair(std::make_pair(pid, sidx), std::move(frame))); + std::make_pair(frame->first_seq_num(), std::move(frame))); } - void TearDown() override { - // All frame objects must be destroyed before the packet buffer since - // a frame object will try to remove itself from the packet buffer - // upon destruction. - frames_from_callback_.clear(); - } - - // Short version of true and false. - enum { - kT = true, - kF = false - }; - - // Insert a generic packet into the packet buffer. - void InsertGeneric(uint16_t seq_num, // packet sequence number - bool keyframe, // is keyframe - bool first, // is first packet of frame - bool last, // is last packet of frame - int data_size = -1, // size of data - uint8_t* data = nullptr) { // data pointer - if (data_size == -1) { - data_size = kDummyDataSize; - data = dummy_data_.get(); - } + enum IsKeyFrame { kKeyFrame, kDeltaFrame }; + enum IsFirst { kFirst, kNotFirst }; + enum IsLast { kLast, kNotLast }; + void InsertPacket(uint16_t seq_num, // packet sequence number + IsKeyFrame keyframe, // is keyframe + IsFirst first, // is first packet of frame + IsLast last, // is last packet of frame + int data_size = 0, // size of data + uint8_t* data = nullptr) { // data pointer VCMPacket packet; packet.codec = kVideoCodecGeneric; packet.seqNum = seq_num; packet.frameType = keyframe ? kVideoFrameKey : kVideoFrameDelta; - packet.isFirstPacket = first; - packet.markerBit = last; + packet.isFirstPacket = first == kFirst; + packet.markerBit = last == kLast; packet.sizeBytes = data_size; packet.dataPtr = data; EXPECT_TRUE(packet_buffer_->InsertPacket(packet)); } - // Insert a Vp8 packet into the packet buffer. - void InsertVp8(uint16_t seq_num, // packet sequence number - bool keyframe, // is keyframe - bool first, // is first packet of frame - bool last, // is last packet of frame - bool sync = false, // is sync frame - int32_t pid = kNoPictureId, // picture id - uint8_t tid = kNoTemporalIdx, // temporal id - int32_t tl0 = kNoTl0PicIdx, // tl0 pic index - int data_size = -1, // size of data - uint8_t* data = nullptr) { // data pointer - if (data_size == -1) { - data_size = kDummyDataSize; - data = dummy_data_.get(); - } - - VCMPacket packet; - packet.codec = kVideoCodecVP8; - packet.seqNum = seq_num; - packet.frameType = keyframe ? kVideoFrameKey : kVideoFrameDelta; - packet.isFirstPacket = first; - packet.markerBit = last; - packet.sizeBytes = data_size; - packet.dataPtr = data; - 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; - - EXPECT_TRUE(packet_buffer_->InsertPacket(packet)); + void CheckFrame(uint16_t first_seq_num) { + auto frame_it = frames_from_callback_.find(first_seq_num); + ASSERT_FALSE(frame_it == frames_from_callback_.end()) + << "Could not find frame with first sequence number " << first_seq_num + << "."; } - // Insert a Vp9 packet into the packet buffer. - void InsertVp9Gof(uint16_t seq_num, // packet sequence number - bool keyframe, // is keyframe - bool first, // is first packet of frame - bool last, // is last packet of frame - bool up = false, // frame is up-switch point - int32_t pid = kNoPictureId, // picture id - uint8_t sid = kNoSpatialIdx, // spatial id - uint8_t tid = kNoTemporalIdx, // temporal id - int32_t tl0 = kNoTl0PicIdx, // tl0 pic index - GofInfoVP9* ss = nullptr, // scalability structure - int data_size = -1, // size of data - uint8_t* data = nullptr) { // data pointer - if (data_size == -1) { - data_size = kDummyDataSize; - data = dummy_data_.get(); - } - - VCMPacket packet; - packet.codec = kVideoCodecVP9; - packet.seqNum = seq_num; - packet.frameType = keyframe ? kVideoFrameKey : kVideoFrameDelta; - packet.isFirstPacket = first; - packet.markerBit = last; - packet.sizeBytes = data_size; - packet.dataPtr = data; - packet.video_header.codecHeader.VP9.flexible_mode = false; - packet.video_header.codecHeader.VP9.picture_id = pid % (1 << 15); - packet.video_header.codecHeader.VP9.temporal_idx = tid; - packet.video_header.codecHeader.VP9.spatial_idx = sid; - packet.video_header.codecHeader.VP9.tl0_pic_idx = tl0; - packet.video_header.codecHeader.VP9.temporal_up_switch = up; - if (ss != nullptr) { - packet.video_header.codecHeader.VP9.ss_data_available = true; - packet.video_header.codecHeader.VP9.gof = *ss; - } - - EXPECT_TRUE(packet_buffer_->InsertPacket(packet)); - } - - // Insert a Vp9 packet into the packet buffer. - void InsertVp9Flex( - uint16_t seq_num, // packet sequence number - bool keyframe, // is keyframe - bool first, // is first packet of frame - bool last, // is last packet of frame - bool inter, // depends on S-1 layer - int32_t pid = kNoPictureId, // picture id - uint8_t sid = kNoSpatialIdx, // spatial id - uint8_t tid = kNoTemporalIdx, // temporal id - int32_t tl0 = kNoTl0PicIdx, // tl0 pic index - std::vector refs = std::vector(), // frame references - int data_size = -1, // size of data - uint8_t* data = nullptr) { // data pointer - if (data_size == -1) { - data_size = kDummyDataSize; - data = dummy_data_.get(); - } - - VCMPacket packet; - packet.codec = kVideoCodecVP9; - packet.seqNum = seq_num; - packet.frameType = keyframe ? kVideoFrameKey : kVideoFrameDelta; - packet.isFirstPacket = first; - packet.markerBit = last; - packet.sizeBytes = data_size; - packet.dataPtr = data; - packet.video_header.codecHeader.VP9.inter_layer_predicted = inter; - packet.video_header.codecHeader.VP9.flexible_mode = true; - packet.video_header.codecHeader.VP9.picture_id = pid % (1 << 15); - packet.video_header.codecHeader.VP9.temporal_idx = tid; - packet.video_header.codecHeader.VP9.spatial_idx = sid; - packet.video_header.codecHeader.VP9.tl0_pic_idx = tl0; - 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]; - - EXPECT_TRUE(packet_buffer_->InsertPacket(packet)); - } - - // Check if a frame with picture id |pid| and spatial index |sidx| has been - // delivered from the packet buffer, and if so, if it has the references - // specified by |refs|. - template - void CheckReferences(uint16_t pid, uint16_t sidx, T... refs) const { - auto frame_it = frames_from_callback_.find(std::make_pair(pid, sidx)); - if (frame_it == frames_from_callback_.end()) { - ADD_FAILURE() << "Could not find frame with (pid:sidx): (" - << pid << ":" << sidx << ")"; - return; - } - - std::set actual_refs; - for (uint8_t r = 0; r < frame_it->second->num_references; ++r) { - actual_refs.insert(frame_it->second->references[r]); - } - - std::set expected_refs; - RefsToSet(&expected_refs, refs...); - - ASSERT_EQ(expected_refs, actual_refs); - } - - template - void CheckReferencesGeneric(uint16_t pid, T... refs) const { - CheckReferences(pid, 0, refs...); - } - - template - void CheckReferencesVp8(uint16_t pid, T... refs) const { - CheckReferences(pid, 0, refs...); - } - - template - void CheckReferencesVp9(uint16_t pid, uint8_t sidx, T... refs) const { - CheckReferences(pid, sidx, refs...); - } - - template - void RefsToSet(std::set* m, uint16_t ref, T... refs) const { - m->insert(ref); - RefsToSet(m, refs...); - } - - void RefsToSet(std::set* m) const {} - const int kStartSize = 16; const int kMaxSize = 64; - const int kDummyDataSize = 4; Random rand_; std::unique_ptr clock_; - std::unique_ptr packet_buffer_; - struct FrameComp { - bool operator()(const std::pair f1, - const std::pair f2) const { - if (f1.first == f2.first) - return f1.second < f2.second; - return f1.first < f2.first; - } - }; - std::map, - std::unique_ptr, - FrameComp> frames_from_callback_; - - std::unique_ptr dummy_data_; + rtc::scoped_refptr packet_buffer_; + std::map> frames_from_callback_; }; TEST_F(TestPacketBuffer, InsertOnePacket) { - VCMPacket packet; - packet.seqNum = Rand(); - EXPECT_TRUE(packet_buffer_->InsertPacket(packet)); + uint16_t seq_num = Rand(); + InsertPacket(seq_num, kKeyFrame, kFirst, kLast); } TEST_F(TestPacketBuffer, InsertMultiplePackets) { - VCMPacket packet; - packet.seqNum = Rand(); - EXPECT_TRUE(packet_buffer_->InsertPacket(packet)); - ++packet.seqNum; - EXPECT_TRUE(packet_buffer_->InsertPacket(packet)); - ++packet.seqNum; - EXPECT_TRUE(packet_buffer_->InsertPacket(packet)); + uint16_t seq_num = Rand(); + InsertPacket(seq_num, kKeyFrame, kFirst, kLast); + InsertPacket(seq_num + 1, kKeyFrame, kFirst, kLast); + InsertPacket(seq_num + 2, kKeyFrame, kFirst, kLast); + InsertPacket(seq_num + 3, kKeyFrame, kFirst, kLast); } TEST_F(TestPacketBuffer, InsertDuplicatePacket) { - VCMPacket packet; - packet.seqNum = Rand(); - EXPECT_TRUE(packet_buffer_->InsertPacket(packet)); - ++packet.seqNum; - EXPECT_TRUE(packet_buffer_->InsertPacket(packet)); - EXPECT_TRUE(packet_buffer_->InsertPacket(packet)); + uint16_t seq_num = Rand(); + InsertPacket(seq_num, kKeyFrame, kFirst, kLast); + InsertPacket(seq_num, kKeyFrame, kFirst, kLast); } TEST_F(TestPacketBuffer, NackCount) { @@ -303,8 +111,6 @@ TEST_F(TestPacketBuffer, NackCount) { packet.frameType = kVideoFrameKey; packet.isFirstPacket = true; packet.markerBit = false; - packet.dataPtr = dummy_data_.get(); - packet.sizeBytes = kDummyDataSize; packet.timesNacked = 0; packet_buffer_->InsertPacket(packet); @@ -325,20 +131,18 @@ TEST_F(TestPacketBuffer, NackCount) { ASSERT_EQ(1UL, frames_from_callback_.size()); - FrameObject* frame = frames_from_callback_.begin()->second.get(); - RtpFrameObject* rtp_frame = static_cast(frame); - EXPECT_EQ(3, rtp_frame->times_nacked()); + RtpFrameObject* frame = frames_from_callback_.begin()->second.get(); + EXPECT_EQ(3, frame->times_nacked()); } TEST_F(TestPacketBuffer, FrameSize) { uint16_t seq_num = Rand(); uint8_t data[] = {1, 2, 3, 4, 5}; - // seq_num , kf, frst, lst, size, data - InsertGeneric(seq_num , kT, kT , kF , 5 , data); - InsertGeneric(seq_num + 1, kT, kF , kF , 5 , data); - InsertGeneric(seq_num + 2, kT, kF , kF , 5 , data); - InsertGeneric(seq_num + 3, kT, kF , kT , 5 , data); + InsertPacket(seq_num, kKeyFrame, kFirst, kNotLast, 5, data); + InsertPacket(seq_num + 1, kKeyFrame, kNotFirst, kNotLast, 5, data); + InsertPacket(seq_num + 2, kKeyFrame, kNotFirst, kNotLast, 5, data); + InsertPacket(seq_num + 3, kKeyFrame, kNotFirst, kLast, 5, data); ASSERT_EQ(1UL, frames_from_callback_.size()); EXPECT_EQ(20UL, frames_from_callback_.begin()->second->size); @@ -348,8 +152,7 @@ TEST_F(TestPacketBuffer, ExpandBuffer) { uint16_t seq_num = Rand(); for (int i = 0; i < kStartSize + 1; ++i) { - // seq_num , kf, frst, lst - InsertGeneric(seq_num + i, kT, kT , kT); + InsertPacket(seq_num + i, kKeyFrame, kFirst, kLast); } } @@ -357,58 +160,55 @@ TEST_F(TestPacketBuffer, ExpandBufferOverflow) { uint16_t seq_num = Rand(); for (int i = 0; i < kMaxSize; ++i) { - // seq_num , kf, frst, lst - InsertGeneric(seq_num + i, kT, kT , kT); + InsertPacket(seq_num + i, kKeyFrame, kFirst, kLast); } VCMPacket packet; packet.seqNum = seq_num + kMaxSize + 1; - packet.sizeBytes = 1; EXPECT_FALSE(packet_buffer_->InsertPacket(packet)); } -TEST_F(TestPacketBuffer, GenericOnePacketOneFrame) { - // seq_num, kf, frst, lst - InsertGeneric(Rand() , kT, kT , kT); +TEST_F(TestPacketBuffer, OnePacketOneFrame) { + uint16_t seq_num = Rand(); + InsertPacket(seq_num, kKeyFrame, kFirst, kLast); ASSERT_EQ(1UL, frames_from_callback_.size()); + CheckFrame(seq_num); } -TEST_F(TestPacketBuffer, GenericTwoPacketsTwoFrames) { +TEST_F(TestPacketBuffer, TwoPacketsTwoFrames) { uint16_t seq_num = Rand(); - // seq_num , kf, frst, lst - InsertGeneric(seq_num , kT, kT , kT); - InsertGeneric(seq_num + 1, kT, kT , kT); + InsertPacket(seq_num, kKeyFrame, kFirst, kLast); + InsertPacket(seq_num + 1, kKeyFrame, kFirst, kLast); EXPECT_EQ(2UL, frames_from_callback_.size()); + CheckFrame(seq_num); + CheckFrame(seq_num + 1); } -TEST_F(TestPacketBuffer, GenericTwoPacketsOneFrames) { +TEST_F(TestPacketBuffer, TwoPacketsOneFrames) { uint16_t seq_num = Rand(); - // seq_num , kf, frst, lst - InsertGeneric(seq_num , kT, kT , kF); - InsertGeneric(seq_num + 1, kT, kF , kT); + InsertPacket(seq_num, kKeyFrame, kFirst, kNotLast); + InsertPacket(seq_num + 1, kKeyFrame, kNotFirst, kLast); EXPECT_EQ(1UL, frames_from_callback_.size()); + CheckFrame(seq_num); } -TEST_F(TestPacketBuffer, GenericThreePacketReorderingOneFrame) { +TEST_F(TestPacketBuffer, ThreePacketReorderingOneFrame) { uint16_t seq_num = Rand(); - // seq_num , kf, frst, lst - InsertGeneric(seq_num , kT, kT , kF); - InsertGeneric(seq_num + 2, kT, kF , kT); - InsertGeneric(seq_num + 1, kT, kF , kF); + InsertPacket(seq_num, kKeyFrame, kFirst, kNotLast); + InsertPacket(seq_num + 2, kKeyFrame, kNotFirst, kLast); + InsertPacket(seq_num + 1, kKeyFrame, kNotFirst, kNotLast); EXPECT_EQ(1UL, frames_from_callback_.size()); + CheckFrame(seq_num); } TEST_F(TestPacketBuffer, DiscardOldPacket) { - uint16_t seq_num = Rand(); VCMPacket packet; - packet.dataPtr = dummy_data_.get(); - packet.sizeBytes = kDummyDataSize; packet.seqNum = Rand(); EXPECT_TRUE(packet_buffer_->InsertPacket(packet)); packet.seqNum += 2; @@ -421,15 +221,13 @@ TEST_F(TestPacketBuffer, DiscardOldPacket) { ++packet.seqNum; EXPECT_FALSE(packet_buffer_->InsertPacket(packet)); - packet_buffer_->ClearTo(seq_num + 1); + packet_buffer_->ClearTo(packet.seqNum + 1); EXPECT_TRUE(packet_buffer_->InsertPacket(packet)); } TEST_F(TestPacketBuffer, DiscardMultipleOldPackets) { uint16_t seq_num = Rand(); VCMPacket packet; - packet.dataPtr = dummy_data_.get(); - packet.sizeBytes = kDummyDataSize; packet.seqNum = seq_num; EXPECT_TRUE(packet_buffer_->InsertPacket(packet)); packet.seqNum += 2; @@ -451,36 +249,34 @@ TEST_F(TestPacketBuffer, DiscardMultipleOldPackets) { } } -TEST_F(TestPacketBuffer, GenericFrames) { +TEST_F(TestPacketBuffer, Frames) { uint16_t seq_num = Rand(); - // seq_num , keyf , first, last - InsertGeneric(seq_num , true , true , true); - InsertGeneric(seq_num + 1, false, true , true); - InsertGeneric(seq_num + 2, false, true , true); - InsertGeneric(seq_num + 3, false, true , true); + InsertPacket(seq_num, kKeyFrame, kFirst, kLast); + InsertPacket(seq_num + 1, kDeltaFrame, kFirst, kLast); + InsertPacket(seq_num + 2, kDeltaFrame, kFirst, kLast); + InsertPacket(seq_num + 3, kDeltaFrame, kFirst, kLast); ASSERT_EQ(4UL, frames_from_callback_.size()); - CheckReferencesGeneric(seq_num); - CheckReferencesGeneric(seq_num + 1, seq_num); - CheckReferencesGeneric(seq_num + 2, seq_num + 1); - CheckReferencesGeneric(seq_num + 3, seq_num + 2); + CheckFrame(seq_num); + CheckFrame(seq_num + 1); + CheckFrame(seq_num + 2); + CheckFrame(seq_num + 3); } -TEST_F(TestPacketBuffer, GenericFramesReordered) { +TEST_F(TestPacketBuffer, FramesReordered) { uint16_t seq_num = Rand(); - // seq_num , keyf , first, last - InsertGeneric(seq_num + 1, false, true , true); - InsertGeneric(seq_num , true , true , true); - InsertGeneric(seq_num + 3, false, true , true); - InsertGeneric(seq_num + 2, false, true , true); + InsertPacket(seq_num + 1, kDeltaFrame, kFirst, kLast); + InsertPacket(seq_num, kKeyFrame, kFirst, kLast); + InsertPacket(seq_num + 3, kDeltaFrame, kFirst, kLast); + InsertPacket(seq_num + 2, kDeltaFrame, kFirst, kLast); ASSERT_EQ(4UL, frames_from_callback_.size()); - CheckReferencesGeneric(seq_num); - CheckReferencesGeneric(seq_num + 1, seq_num); - CheckReferencesGeneric(seq_num + 2, seq_num + 1); - CheckReferencesGeneric(seq_num + 3, seq_num + 2); + CheckFrame(seq_num); + CheckFrame(seq_num + 1); + CheckFrame(seq_num + 2); + CheckFrame(seq_num + 3); } TEST_F(TestPacketBuffer, GetBitstreamFromFrame) { @@ -495,63 +291,62 @@ TEST_F(TestPacketBuffer, GetBitstreamFromFrame) { uint16_t seq_num = Rand(); - // seq_num , kf, frst, lst, data_size , data - InsertGeneric(seq_num , kT, kT , kF , sizeof(many) , many); - InsertGeneric(seq_num + 1, kF, kF , kF , sizeof(bitstream), bitstream); - InsertGeneric(seq_num + 2, kF, kF , kF , sizeof(such) , such); - InsertGeneric(seq_num + 3, kF, kF , kT , sizeof(data) , data); + InsertPacket(seq_num, kKeyFrame, kFirst, kNotLast, sizeof(many), many); + InsertPacket(seq_num + 1, kDeltaFrame, kNotFirst, kNotLast, sizeof(bitstream), + bitstream); + InsertPacket(seq_num + 2, kDeltaFrame, kNotFirst, kNotLast, sizeof(such), + such); + InsertPacket(seq_num + 3, kDeltaFrame, kNotFirst, kLast, sizeof(data), data); ASSERT_EQ(1UL, frames_from_callback_.size()); - CheckReferencesVp8(seq_num + 3); - EXPECT_TRUE(frames_from_callback_[std::make_pair(seq_num + 3, 0)]-> - GetBitstream(result)); + CheckFrame(seq_num); + EXPECT_TRUE(frames_from_callback_[seq_num]->GetBitstream(result)); EXPECT_EQ(memcmp(result, "many bitstream, such data", sizeof(result)), 0); } TEST_F(TestPacketBuffer, FreeSlotsOnFrameDestruction) { uint16_t seq_num = Rand(); - // seq_num , kf, frst, lst - InsertGeneric(seq_num , kT, kT , kF); - InsertGeneric(seq_num + 1, kF, kF , kF); - InsertGeneric(seq_num + 2, kF, kF , kT); + InsertPacket(seq_num, kKeyFrame, kFirst, kNotLast); + InsertPacket(seq_num + 1, kDeltaFrame, kNotFirst, kNotLast); + InsertPacket(seq_num + 2, kDeltaFrame, kNotFirst, kLast); EXPECT_EQ(1UL, frames_from_callback_.size()); + CheckFrame(seq_num); frames_from_callback_.clear(); - // seq_num , kf, frst, lst - InsertGeneric(seq_num , kT, kT , kF); - InsertGeneric(seq_num + 1, kF, kF , kF); - InsertGeneric(seq_num + 2, kF, kF , kT); + // Insert frame that fills the whole buffer. + InsertPacket(seq_num + 3, kKeyFrame, kFirst, kNotLast); + for (int i = 0; i < kMaxSize - 2; ++i) + InsertPacket(seq_num + i + 4, kDeltaFrame, kNotFirst, kNotLast); + InsertPacket(seq_num + kMaxSize + 2, kKeyFrame, kNotFirst, kLast); EXPECT_EQ(1UL, frames_from_callback_.size()); + CheckFrame(seq_num + 3); } TEST_F(TestPacketBuffer, Clear) { uint16_t seq_num = Rand(); - // seq_num , kf, frst, lst - InsertGeneric(seq_num , kT, kT , kF); - InsertGeneric(seq_num + 1, kF, kF , kF); - InsertGeneric(seq_num + 2, kF, kF , kT); + InsertPacket(seq_num, kKeyFrame, kFirst, kNotLast); + InsertPacket(seq_num + 1, kDeltaFrame, kNotFirst, kNotLast); + InsertPacket(seq_num + 2, kDeltaFrame, kNotFirst, kLast); EXPECT_EQ(1UL, frames_from_callback_.size()); + CheckFrame(seq_num); packet_buffer_->Clear(); - // seq_num , kf, frst, lst - InsertGeneric(seq_num + kStartSize , kT, kT , kF); - InsertGeneric(seq_num + kStartSize + 1, kF, kF , kF); - InsertGeneric(seq_num + kStartSize + 2, kF, kF , kT); + InsertPacket(seq_num + kStartSize, kKeyFrame, kFirst, kNotLast); + InsertPacket(seq_num + kStartSize + 1, kDeltaFrame, kNotFirst, kNotLast); + InsertPacket(seq_num + kStartSize + 2, kDeltaFrame, kNotFirst, kLast); EXPECT_EQ(2UL, frames_from_callback_.size()); + CheckFrame(seq_num + kStartSize); } TEST_F(TestPacketBuffer, InvalidateFrameByClearing) { VCMPacket packet; - packet.dataPtr = dummy_data_.get(); - packet.sizeBytes = kDummyDataSize; - packet.codec = kVideoCodecGeneric; packet.frameType = kVideoFrameKey; - packet.isFirstPacket = kT; - packet.markerBit = kT; + packet.isFirstPacket = true; + packet.markerBit = true; packet.seqNum = Rand(); EXPECT_TRUE(packet_buffer_->InsertPacket(packet)); ASSERT_EQ(1UL, frames_from_callback_.size()); @@ -560,1051 +355,5 @@ TEST_F(TestPacketBuffer, InvalidateFrameByClearing) { EXPECT_FALSE(frames_from_callback_.begin()->second->GetBitstream(nullptr)); } -TEST_F(TestPacketBuffer, PaddingPackets) { - uint16_t seq_num = Rand(); - - // seq_num , kf, frst, lst - InsertGeneric(seq_num , kT, kT , kT); - InsertGeneric(seq_num + 1, kF, kF , kF, 0, nullptr); - InsertGeneric(seq_num + 3, kF, kT , kT); - EXPECT_EQ(1UL, frames_from_callback_.size()); - InsertGeneric(seq_num + 2, kF, kF , kF, 0, nullptr); - EXPECT_EQ(2UL, frames_from_callback_.size()); -} - -TEST_F(TestPacketBuffer, PaddingPacketsReordered) { - uint16_t seq_num = Rand(); - - // seq_num , kf, frst, lst - InsertGeneric(seq_num , kT, kT , kT); - InsertGeneric(seq_num + 1, kF, kF , kF, 0, nullptr); - InsertGeneric(seq_num + 2, kF, kT , kF); - InsertGeneric(seq_num + 4, kF, kF , kF, 0, nullptr); - InsertGeneric(seq_num + 3, kF, kF , kT); - EXPECT_EQ(2UL, frames_from_callback_.size()); - CheckReferencesGeneric(seq_num); - CheckReferencesGeneric(seq_num + 3, seq_num); -} - -TEST_F(TestPacketBuffer, PaddingPacketsReorderedMultipleKeyframes) { - uint16_t seq_num = Rand(); - - // seq_num , kf, frst, lst - InsertGeneric(seq_num , kT, kT , kT); - InsertGeneric(seq_num + 2, kF, kT , kF); - InsertGeneric(seq_num + 1, kF, kF , kF, 0, nullptr); - InsertGeneric(seq_num + 4, kF, kF , kF, 0, nullptr); - InsertGeneric(seq_num + 5, kT, kT , kT); - InsertGeneric(seq_num + 3, kF, kF , kT); - InsertGeneric(seq_num + 6, kF, kF , kF, 0, nullptr); - InsertGeneric(seq_num + 9, kF, kF , kF, 0, nullptr); - InsertGeneric(seq_num + 8, kF, kF , kT); - InsertGeneric(seq_num + 7, kF, kT , kF); - EXPECT_EQ(4UL, frames_from_callback_.size()); -} - -TEST_F(TestPacketBuffer, Vp8NoPictureId) { - uint16_t seq_num = Rand(); - - // seq_num , kf, frst, lst - InsertVp8(seq_num , kT, kT , kF); - InsertVp8(seq_num + 1 , kF, kF , kF); - InsertVp8(seq_num + 2 , kF, kF , kT); - ASSERT_EQ(1UL, frames_from_callback_.size()); - - InsertVp8(seq_num + 3 , kF, kT , kF); - InsertVp8(seq_num + 4 , kF, kF , kT); - ASSERT_EQ(2UL, frames_from_callback_.size()); - - InsertVp8(seq_num + 5 , kF, kT , kF); - InsertVp8(seq_num + 6 , kF, kF , kF); - InsertVp8(seq_num + 7 , kF, kF , kF); - InsertVp8(seq_num + 8 , kF, kF , kT); - ASSERT_EQ(3UL, frames_from_callback_.size()); - - InsertVp8(seq_num + 9 , kF, kT , kT); - ASSERT_EQ(4UL, frames_from_callback_.size()); - - InsertVp8(seq_num + 10, kF, kT , kF); - InsertVp8(seq_num + 11, kF, kF , kT); - ASSERT_EQ(5UL, frames_from_callback_.size()); - - InsertVp8(seq_num + 12, kT, kT , kT); - ASSERT_EQ(6UL, frames_from_callback_.size()); - - InsertVp8(seq_num + 13, kF, kT , kF); - InsertVp8(seq_num + 14, kF, kF , kF); - InsertVp8(seq_num + 15, kF, kF , kF); - InsertVp8(seq_num + 16, kF, kF , kF); - InsertVp8(seq_num + 17, kF, kF , kT); - ASSERT_EQ(7UL, frames_from_callback_.size()); - - InsertVp8(seq_num + 18, kF, kT , kT); - ASSERT_EQ(8UL, frames_from_callback_.size()); - - InsertVp8(seq_num + 19, kF, kT , kF); - InsertVp8(seq_num + 20, kF, kF , kT); - ASSERT_EQ(9UL, frames_from_callback_.size()); - - InsertVp8(seq_num + 21, kF, kT , kT); - - ASSERT_EQ(10UL, frames_from_callback_.size()); - CheckReferencesVp8(seq_num + 2); - CheckReferencesVp8(seq_num + 4, seq_num + 2); - CheckReferencesVp8(seq_num + 8, seq_num + 4); - CheckReferencesVp8(seq_num + 9, seq_num + 8); - CheckReferencesVp8(seq_num + 11, seq_num + 9); - CheckReferencesVp8(seq_num + 12); - CheckReferencesVp8(seq_num + 17, seq_num + 12); - CheckReferencesVp8(seq_num + 18, seq_num + 17); - CheckReferencesVp8(seq_num + 20, seq_num + 18); - CheckReferencesVp8(seq_num + 21, seq_num + 20); -} - -TEST_F(TestPacketBuffer, Vp8NoPictureIdReordered) { - uint16_t seq_num = 0xfffa; - - // seq_num , kf, frst, lst - InsertVp8(seq_num + 1 , kF, kF , kF); - InsertVp8(seq_num , kT, kT , kF); - InsertVp8(seq_num + 2 , kF, kF , kT); - InsertVp8(seq_num + 4 , kF, kF , kT); - InsertVp8(seq_num + 6 , kF, kF , kF); - InsertVp8(seq_num + 3 , kF, kT , kF); - InsertVp8(seq_num + 7 , kF, kF , kF); - InsertVp8(seq_num + 5 , kF, kT , kF); - InsertVp8(seq_num + 9 , kF, kT , kT); - InsertVp8(seq_num + 10, kF, kT , kF); - InsertVp8(seq_num + 8 , kF, kF , kT); - InsertVp8(seq_num + 13, kF, kT , kF); - InsertVp8(seq_num + 14, kF, kF , kF); - InsertVp8(seq_num + 12, kT, kT , kT); - InsertVp8(seq_num + 11, kF, kF , kT); - InsertVp8(seq_num + 16, kF, kF , kF); - InsertVp8(seq_num + 19, kF, kT , kF); - InsertVp8(seq_num + 15, kF, kF , kF); - InsertVp8(seq_num + 17, kF, kF , kT); - InsertVp8(seq_num + 20, kF, kF , kT); - InsertVp8(seq_num + 21, kF, kT , kT); - InsertVp8(seq_num + 18, kF, kT , kT); - - ASSERT_EQ(10UL, frames_from_callback_.size()); - CheckReferencesVp8(seq_num + 2); - CheckReferencesVp8(seq_num + 4, seq_num + 2); - CheckReferencesVp8(seq_num + 8, seq_num + 4); - CheckReferencesVp8(seq_num + 9, seq_num + 8); - CheckReferencesVp8(seq_num + 11, seq_num + 9); - CheckReferencesVp8(seq_num + 12); - CheckReferencesVp8(seq_num + 17, seq_num + 12); - CheckReferencesVp8(seq_num + 18, seq_num + 17); - CheckReferencesVp8(seq_num + 20, seq_num + 18); - CheckReferencesVp8(seq_num + 21, seq_num + 20); -} - - -TEST_F(TestPacketBuffer, Vp8KeyFrameReferences) { - uint16_t pid = Rand(); - // seq_num, kf, frst, lst, sync, pid, tid, tl0 - InsertVp8(Rand() , kT, kT , kT , kF , pid, 0 , 0); - - ASSERT_EQ(1UL, frames_from_callback_.size()); - CheckReferencesVp8(pid); -} - -// Test with 1 temporal layer. -TEST_F(TestPacketBuffer, Vp8TemporalLayers_0) { - uint16_t pid = Rand(); - uint16_t seq_num = Rand(); - - // seq_num , kf, frst, lst, sync, pid , tid, tl0 - InsertVp8(seq_num , kT, kT , kT , kF , pid , 0 , 1); - InsertVp8(seq_num + 1, kF, kT , kT , kF , pid + 1, 0 , 2); - InsertVp8(seq_num + 2, kF, kT , kT , kF , pid + 2, 0 , 3); - InsertVp8(seq_num + 3, kF, kT , kT , kF , pid + 3, 0 , 4); - - ASSERT_EQ(4UL, frames_from_callback_.size()); - CheckReferencesVp8(pid); - CheckReferencesVp8(pid + 1, pid); - CheckReferencesVp8(pid + 2, pid + 1); - CheckReferencesVp8(pid + 3, pid + 2); -} - -// Test with 1 temporal layer. -TEST_F(TestPacketBuffer, Vp8TemporalLayersReordering_0) { - uint16_t pid = Rand(); - uint16_t seq_num = Rand(); - - // seq_num , kf, frst, lst, sync, pid , tid, tl0 - InsertVp8(seq_num , kT, kT , kT , kF , pid , 0 , 1); - InsertVp8(seq_num + 1, kF, kT , kT , kF , pid + 1, 0 , 2); - InsertVp8(seq_num + 3, kF, kT , kT , kF , pid + 3, 0 , 4); - InsertVp8(seq_num + 2, kF, kT , kT , kF , pid + 2, 0 , 3); - InsertVp8(seq_num + 5, kF, kT , kT , kF , pid + 5, 0 , 6); - InsertVp8(seq_num + 6, kF, kT , kT , kF , pid + 6, 0 , 7); - InsertVp8(seq_num + 4, kF, kT , kT , kF , pid + 4, 0 , 5); - - ASSERT_EQ(7UL, frames_from_callback_.size()); - CheckReferencesVp8(pid); - CheckReferencesVp8(pid + 1, pid); - CheckReferencesVp8(pid + 2, pid + 1); - CheckReferencesVp8(pid + 3, pid + 2); - CheckReferencesVp8(pid + 4, pid + 3); - CheckReferencesVp8(pid + 5, pid + 4); - CheckReferencesVp8(pid + 6, pid + 5); -} - -// Test with 2 temporal layers in a 01 pattern. -TEST_F(TestPacketBuffer, Vp8TemporalLayers_01) { - uint16_t pid = Rand(); - uint16_t seq_num = Rand(); - - // seq_num , kf, frst, lst, sync, pid , tid, tl0 - InsertVp8(seq_num , kT, kT , kT , kF , pid , 0, 255); - InsertVp8(seq_num + 1, kF, kT , kT , kT , pid + 1, 1, 255); - InsertVp8(seq_num + 2, kF, kT , kT , kF , pid + 2, 0, 0); - InsertVp8(seq_num + 3, kF, kT , kT , kF , pid + 3, 1, 0); - - ASSERT_EQ(4UL, frames_from_callback_.size()); - CheckReferencesVp8(pid); - CheckReferencesVp8(pid + 1, pid); - CheckReferencesVp8(pid + 2, pid); - CheckReferencesVp8(pid + 3, pid + 1, pid + 2); -} - -// Test with 2 temporal layers in a 01 pattern. -TEST_F(TestPacketBuffer, Vp8TemporalLayersReordering_01) { - uint16_t pid = Rand(); - uint16_t seq_num = Rand(); - - // seq_num , kf, frst, lst, sync, pid , tid, tl0 - InsertVp8(seq_num + 1, kF, kT , kT , kT , pid + 1, 1 , 255); - InsertVp8(seq_num , kT, kT , kT , kF , pid , 0 , 255); - InsertVp8(seq_num + 3, kF, kT , kT , kF , pid + 3, 1 , 0); - InsertVp8(seq_num + 5, kF, kT , kT , kF , pid + 5, 1 , 1); - InsertVp8(seq_num + 2, kF, kT , kT , kF , pid + 2, 0 , 0); - InsertVp8(seq_num + 4, kF, kT , kT , kF , pid + 4, 0 , 1); - InsertVp8(seq_num + 6, kF, kT , kT , kF , pid + 6, 0 , 2); - InsertVp8(seq_num + 7, kF, kT , kT , kF , pid + 7, 1 , 2); - - ASSERT_EQ(8UL, frames_from_callback_.size()); - CheckReferencesVp8(pid); - CheckReferencesVp8(pid + 1, pid); - CheckReferencesVp8(pid + 2, pid); - CheckReferencesVp8(pid + 3, pid + 1, pid + 2); - CheckReferencesVp8(pid + 4, pid + 2); - CheckReferencesVp8(pid + 5, pid + 3, pid + 4); - CheckReferencesVp8(pid + 6, pid + 4); - CheckReferencesVp8(pid + 7, pid + 5, pid + 6); -} - -// Test with 3 temporal layers in a 0212 pattern. -TEST_F(TestPacketBuffer, Vp8TemporalLayers_0212) { - uint16_t pid = Rand(); - uint16_t seq_num = Rand(); - - // seq_num , kf, frst, lst, sync, pid , tid, tl0 - InsertVp8(seq_num , kT, kT , kT , kF , pid , 0 , 55); - InsertVp8(seq_num + 1 , kF, kT , kT , kT , pid + 1 , 2 , 55); - InsertVp8(seq_num + 2 , kF, kT , kT , kT , pid + 2 , 1 , 55); - InsertVp8(seq_num + 3 , kF, kT , kT , kF , pid + 3 , 2 , 55); - InsertVp8(seq_num + 4 , kF, kT , kT , kF , pid + 4 , 0 , 56); - InsertVp8(seq_num + 5 , kF, kT , kT , kF , pid + 5 , 2 , 56); - InsertVp8(seq_num + 6 , kF, kT , kT , kF , pid + 6 , 1 , 56); - InsertVp8(seq_num + 7 , kF, kT , kT , kF , pid + 7 , 2 , 56); - InsertVp8(seq_num + 8 , kF, kT , kT , kF , pid + 8 , 0 , 57); - InsertVp8(seq_num + 9 , kF, kT , kT , kT , pid + 9 , 2 , 57); - InsertVp8(seq_num + 10, kF, kT , kT , kT , pid + 10, 1 , 57); - InsertVp8(seq_num + 11, kF, kT , kT , kF , pid + 11, 2 , 57); - - ASSERT_EQ(12UL, frames_from_callback_.size()); - CheckReferencesVp8(pid); - CheckReferencesVp8(pid + 1 , pid); - CheckReferencesVp8(pid + 2 , pid); - CheckReferencesVp8(pid + 3 , pid, pid + 1, pid + 2); - CheckReferencesVp8(pid + 4 , pid); - CheckReferencesVp8(pid + 5 , pid + 2, pid + 3, pid + 4); - CheckReferencesVp8(pid + 6 , pid + 2, pid + 4); - CheckReferencesVp8(pid + 7 , pid + 4, pid + 5, pid + 6); - CheckReferencesVp8(pid + 8 , pid + 4); - CheckReferencesVp8(pid + 9 , pid + 8); - CheckReferencesVp8(pid + 10, pid + 8); - CheckReferencesVp8(pid + 11, pid + 8, pid + 9, pid + 10); -} - -// Test with 3 temporal layers in a 0212 pattern. -TEST_F(TestPacketBuffer, Vp8TemporalLayersReordering_0212) { - uint16_t pid = 126; - uint16_t seq_num = Rand(); - - // seq_num , kf, frst, lst, sync, pid , tid, tl0 - InsertVp8(seq_num + 1 , kF, kT , kT , kT , pid + 1 , 2 , 55); - InsertVp8(seq_num , kT, kT , kT , kF , pid , 0 , 55); - InsertVp8(seq_num + 2 , kF, kT , kT , kT , pid + 2 , 1 , 55); - InsertVp8(seq_num + 4 , kF, kT , kT , kF , pid + 4 , 0 , 56); - InsertVp8(seq_num + 5 , kF, kT , kT , kF , pid + 5 , 2 , 56); - InsertVp8(seq_num + 3 , kF, kT , kT , kF , pid + 3 , 2 , 55); - InsertVp8(seq_num + 7 , kF, kT , kT , kF , pid + 7 , 2 , 56); - InsertVp8(seq_num + 9 , kF, kT , kT , kT , pid + 9 , 2 , 57); - InsertVp8(seq_num + 6 , kF, kT , kT , kF , pid + 6 , 1 , 56); - InsertVp8(seq_num + 8 , kF, kT , kT , kF , pid + 8 , 0 , 57); - InsertVp8(seq_num + 11, kF, kT , kT , kF , pid + 11, 2 , 57); - InsertVp8(seq_num + 10, kF, kT , kT , kT , pid + 10, 1 , 57); - - ASSERT_EQ(12UL, frames_from_callback_.size()); - CheckReferencesVp8(pid); - CheckReferencesVp8(pid + 1 , pid); - CheckReferencesVp8(pid + 2 , pid); - CheckReferencesVp8(pid + 3 , pid, pid + 1, pid + 2); - CheckReferencesVp8(pid + 4 , pid); - CheckReferencesVp8(pid + 5 , pid + 2, pid + 3, pid + 4); - CheckReferencesVp8(pid + 6 , pid + 2, pid + 4); - CheckReferencesVp8(pid + 7 , pid + 4, pid + 5, pid + 6); - CheckReferencesVp8(pid + 8 , pid + 4); - CheckReferencesVp8(pid + 9 , pid + 8); - CheckReferencesVp8(pid + 10, pid + 8); - CheckReferencesVp8(pid + 11, pid + 8, pid + 9, pid + 10); -} - -TEST_F(TestPacketBuffer, Vp8InsertManyFrames_0212) { - uint16_t pid = Rand(); - uint16_t seq_num = Rand(); - - const int keyframes_to_insert = 50; - const int frames_per_keyframe = 120; // Should be a multiple of 4. - uint8_t tl0 = 128; - - for (int k = 0; k < keyframes_to_insert; ++k) { - // seq_num , keyf, frst, lst, sync, pid , tid, tl0 - InsertVp8(seq_num , kT , kT , kT , kF , pid , 0 , tl0); - InsertVp8(seq_num + 1, kF , kT , kT , kT , pid + 1, 2 , tl0); - InsertVp8(seq_num + 2, kF , kT , kT , kT , pid + 2, 1 , tl0); - InsertVp8(seq_num + 3, kF , kT , kT , kF , pid + 3, 2 , tl0); - CheckReferencesVp8(pid); - CheckReferencesVp8(pid + 1, pid); - CheckReferencesVp8(pid + 2, pid); - CheckReferencesVp8(pid + 3, pid, pid + 1, pid + 2); - frames_from_callback_.clear(); - ++tl0; - - for (int f = 4; f < frames_per_keyframe; f += 4) { - uint16_t sf = seq_num + f; - uint16_t pidf = pid + f; - - // seq_num, keyf, frst, lst, sync, pid , tid, tl0 - InsertVp8(sf , kF , kT , kT , kF , pidf , 0 , tl0); - InsertVp8(sf + 1 , kF , kT , kT , kF , pidf + 1, 2 , tl0); - InsertVp8(sf + 2 , kF , kT , kT , kF , pidf + 2, 1 , tl0); - InsertVp8(sf + 3 , kF , kT , kT , kF , pidf + 3, 2 , tl0); - CheckReferencesVp8(pidf, pidf - 4); - CheckReferencesVp8(pidf + 1, pidf, pidf - 1, pidf - 2); - CheckReferencesVp8(pidf + 2, pidf, pidf - 2); - CheckReferencesVp8(pidf + 3, pidf, pidf + 1, pidf + 2); - frames_from_callback_.clear(); - ++tl0; - } - - pid += frames_per_keyframe; - seq_num += frames_per_keyframe; - } -} - -TEST_F(TestPacketBuffer, Vp8LayerSync) { - uint16_t pid = Rand(); - uint16_t seq_num = Rand(); - - // seq_num , keyf, frst, lst, sync, pid , tid, tl0 - InsertVp8(seq_num , kT , kT , kT , kF , pid , 0 , 0); - InsertVp8(seq_num + 1 , kF , kT , kT , kT , pid + 1 , 1 , 0); - InsertVp8(seq_num + 2 , kF , kT , kT , kF , pid + 2 , 0 , 1); - ASSERT_EQ(3UL, frames_from_callback_.size()); - - InsertVp8(seq_num + 4 , kF , kT , kT , kF , pid + 4 , 0 , 2); - InsertVp8(seq_num + 5 , kF , kT , kT , kT , pid + 5 , 1 , 2); - InsertVp8(seq_num + 6 , kF , kT , kT , kF , pid + 6 , 0 , 3); - InsertVp8(seq_num + 7 , kF , kT , kT , kF , pid + 7 , 1 , 3); - - ASSERT_EQ(7UL, frames_from_callback_.size()); - CheckReferencesVp8(pid); - CheckReferencesVp8(pid + 1, pid); - CheckReferencesVp8(pid + 2, pid); - CheckReferencesVp8(pid + 4, pid + 2); - CheckReferencesVp8(pid + 5, pid + 4); - CheckReferencesVp8(pid + 6, pid + 4); - CheckReferencesVp8(pid + 7, pid + 6, pid + 5); -} - -TEST_F(TestPacketBuffer, Vp8InsertLargeFrames) { - packet_buffer_.reset(new PacketBuffer(clock_.get(), 1 << 3, 1 << 12, this)); - uint16_t pid = Rand(); - uint16_t seq_num = Rand(); - - const uint16_t packets_per_frame = 1000; - uint16_t current = seq_num; - uint16_t end = current + packets_per_frame; - - // seq_num , keyf, frst, lst, sync, pid, tid, tl0 - InsertVp8(current++, kT , kT , kF , kF , pid, 0 , 0); - while (current != end) - InsertVp8(current++, kF , kF , kF , kF , pid, 0 , 0); - InsertVp8(current++, kF , kF , kT , kF , pid, 0 , 0); - end = current + packets_per_frame; - - for (int f = 1; f < 4; ++f) { - InsertVp8(current++, kF , kT , kF , kF , pid + f, 0, f); - while (current != end) - InsertVp8(current++, kF , kF , kF , kF , pid + f, 0, f); - InsertVp8(current++, kF , kF , kT , kF , pid + f, 0, f); - end = current + packets_per_frame; - } - - ASSERT_EQ(4UL, frames_from_callback_.size()); - CheckReferencesVp8(pid); - CheckReferencesVp8(pid + 1, pid); - CheckReferencesVp8(pid + 2, pid + 1); - CheckReferencesVp8(pid + 3, pid + 2); -} - -TEST_F(TestPacketBuffer, Vp9GofInsertOneFrame) { - uint16_t pid = Rand(); - uint16_t seq_num = Rand(); - GofInfoVP9 ss; - ss.SetGofInfoVP9(kTemporalStructureMode1); - - // seq_num, keyf, frst, lst, up, pid, sid, tid, tl0, ss - InsertVp9Gof(seq_num, kT , kT , kT , kF, pid, 0 , 0 , 0 , &ss); - - CheckReferencesVp9(pid, 0); -} - -TEST_F(TestPacketBuffer, Vp9NoPictureIdReordered) { - uint16_t sn = 0xfffa; - - // sn , kf, frst, lst - InsertVp9Gof(sn + 1 , kF, kF , kF); - InsertVp9Gof(sn , kT, kT , kF); - InsertVp9Gof(sn + 2 , kF, kF , kT); - InsertVp9Gof(sn + 4 , kF, kF , kT); - InsertVp9Gof(sn + 6 , kF, kF , kF); - InsertVp9Gof(sn + 3 , kF, kT , kF); - InsertVp9Gof(sn + 7 , kF, kF , kF); - InsertVp9Gof(sn + 5 , kF, kT , kF); - InsertVp9Gof(sn + 9 , kF, kT , kT); - InsertVp9Gof(sn + 10, kF, kT , kF); - InsertVp9Gof(sn + 8 , kF, kF , kT); - InsertVp9Gof(sn + 13, kF, kT , kF); - InsertVp9Gof(sn + 14, kF, kF , kF); - InsertVp9Gof(sn + 12, kT, kT , kT); - InsertVp9Gof(sn + 11, kF, kF , kT); - InsertVp9Gof(sn + 16, kF, kF , kF); - InsertVp9Gof(sn + 19, kF, kT , kF); - InsertVp9Gof(sn + 15, kF, kF , kF); - InsertVp9Gof(sn + 17, kF, kF , kT); - InsertVp9Gof(sn + 20, kF, kF , kT); - InsertVp9Gof(sn + 21, kF, kT , kT); - InsertVp9Gof(sn + 18, kF, kT , kT); - - ASSERT_EQ(10UL, frames_from_callback_.size()); - CheckReferencesVp9(sn + 2 , 0); - CheckReferencesVp9(sn + 4 , 0, sn + 2); - CheckReferencesVp9(sn + 8 , 0, sn + 4); - CheckReferencesVp9(sn + 9 , 0, sn + 8); - CheckReferencesVp9(sn + 11, 0, sn + 9); - CheckReferencesVp9(sn + 12, 0); - CheckReferencesVp9(sn + 17, 0, sn + 12); - CheckReferencesVp9(sn + 18, 0, sn + 17); - CheckReferencesVp9(sn + 20, 0, sn + 18); - CheckReferencesVp9(sn + 21, 0, sn + 20); -} - -TEST_F(TestPacketBuffer, Vp9GofTemporalLayers_0) { - uint16_t pid = Rand(); - uint16_t sn = Rand(); - GofInfoVP9 ss; - ss.SetGofInfoVP9(kTemporalStructureMode1); // Only 1 spatial layer. - - // sn , kf, frst, lst, up, pid , sid, tid, tl0, ss - InsertVp9Gof(sn , kT, kT , kT , kF, pid , 0 , 0 , 0 , &ss); - InsertVp9Gof(sn + 1 , kF, kT , kT , kF, pid + 1 , 0 , 0 , 1); - InsertVp9Gof(sn + 2 , kF, kT , kT , kF, pid + 2 , 0 , 0 , 2); - InsertVp9Gof(sn + 3 , kF, kT , kT , kF, pid + 3 , 0 , 0 , 3); - InsertVp9Gof(sn + 4 , kF, kT , kT , kF, pid + 4 , 0 , 0 , 4); - InsertVp9Gof(sn + 5 , kF, kT , kT , kF, pid + 5 , 0 , 0 , 5); - InsertVp9Gof(sn + 6 , kF, kT , kT , kF, pid + 6 , 0 , 0 , 6); - InsertVp9Gof(sn + 7 , kF, kT , kT , kF, pid + 7 , 0 , 0 , 7); - InsertVp9Gof(sn + 8 , kF, kT , kT , kF, pid + 8 , 0 , 0 , 8); - InsertVp9Gof(sn + 9 , kF, kT , kT , kF, pid + 9 , 0 , 0 , 9); - InsertVp9Gof(sn + 10, kF, kT , kT , kF, pid + 10, 0 , 0 , 10); - InsertVp9Gof(sn + 11, kF, kT , kT , kF, pid + 11, 0 , 0 , 11); - InsertVp9Gof(sn + 12, kF, kT , kT , kF, pid + 12, 0 , 0 , 12); - InsertVp9Gof(sn + 13, kF, kT , kT , kF, pid + 13, 0 , 0 , 13); - InsertVp9Gof(sn + 14, kF, kT , kT , kF, pid + 14, 0 , 0 , 14); - InsertVp9Gof(sn + 15, kF, kT , kT , kF, pid + 15, 0 , 0 , 15); - InsertVp9Gof(sn + 16, kF, kT , kT , kF, pid + 16, 0 , 0 , 16); - InsertVp9Gof(sn + 17, kF, kT , kT , kF, pid + 17, 0 , 0 , 17); - InsertVp9Gof(sn + 18, kF, kT , kT , kF, pid + 18, 0 , 0 , 18); - InsertVp9Gof(sn + 19, kF, kT , kT , kF, pid + 19, 0 , 0 , 19); - - ASSERT_EQ(20UL, frames_from_callback_.size()); - CheckReferencesVp9(pid, 0); - CheckReferencesVp9(pid + 1 , 0, pid); - CheckReferencesVp9(pid + 2 , 0, pid + 1); - CheckReferencesVp9(pid + 3 , 0, pid + 2); - CheckReferencesVp9(pid + 4 , 0, pid + 3); - CheckReferencesVp9(pid + 5 , 0, pid + 4); - CheckReferencesVp9(pid + 6 , 0, pid + 5); - CheckReferencesVp9(pid + 7 , 0, pid + 6); - CheckReferencesVp9(pid + 8 , 0, pid + 7); - CheckReferencesVp9(pid + 9 , 0, pid + 8); - CheckReferencesVp9(pid + 10, 0, pid + 9); - CheckReferencesVp9(pid + 11, 0, pid + 10); - CheckReferencesVp9(pid + 12, 0, pid + 11); - CheckReferencesVp9(pid + 13, 0, pid + 12); - CheckReferencesVp9(pid + 14, 0, pid + 13); - CheckReferencesVp9(pid + 15, 0, pid + 14); - CheckReferencesVp9(pid + 16, 0, pid + 15); - CheckReferencesVp9(pid + 17, 0, pid + 16); - CheckReferencesVp9(pid + 18, 0, pid + 17); - CheckReferencesVp9(pid + 19, 0, pid + 18); -} - -TEST_F(TestPacketBuffer, Vp9GofTemporalLayersReordered_0) { - uint16_t pid = Rand(); - uint16_t sn = Rand(); - GofInfoVP9 ss; - ss.SetGofInfoVP9(kTemporalStructureMode1); // Only 1 spatial layer. - - // sn , kf, frst, lst, up, pid , sid, tid, tl0, ss - InsertVp9Gof(sn + 2 , kF, kT , kT , kF, pid + 2 , 0 , 0 , 2); - InsertVp9Gof(sn + 1 , kF, kT , kT , kF, pid + 1 , 0 , 0 , 1); - InsertVp9Gof(sn , kT, kT , kT , kF, pid , 0 , 0 , 0 , &ss); - InsertVp9Gof(sn + 4 , kF, kT , kT , kF, pid + 4 , 0 , 0 , 4); - InsertVp9Gof(sn + 3 , kF, kT , kT , kF, pid + 3 , 0 , 0 , 3); - InsertVp9Gof(sn + 5 , kF, kT , kT , kF, pid + 5 , 0 , 0 , 5); - InsertVp9Gof(sn + 7 , kF, kT , kT , kF, pid + 7 , 0 , 0 , 7); - InsertVp9Gof(sn + 6 , kF, kT , kT , kF, pid + 6 , 0 , 0 , 6); - InsertVp9Gof(sn + 8 , kF, kT , kT , kF, pid + 8 , 0 , 0 , 8); - InsertVp9Gof(sn + 10, kF, kT , kT , kF, pid + 10, 0 , 0 , 10); - InsertVp9Gof(sn + 13, kF, kT , kT , kF, pid + 13, 0 , 0 , 13); - InsertVp9Gof(sn + 11, kF, kT , kT , kF, pid + 11, 0 , 0 , 11); - InsertVp9Gof(sn + 9 , kF, kT , kT , kF, pid + 9 , 0 , 0 , 9); - InsertVp9Gof(sn + 16, kF, kT , kT , kF, pid + 16, 0 , 0 , 16); - InsertVp9Gof(sn + 14, kF, kT , kT , kF, pid + 14, 0 , 0 , 14); - InsertVp9Gof(sn + 15, kF, kT , kT , kF, pid + 15, 0 , 0 , 15); - InsertVp9Gof(sn + 12, kF, kT , kT , kF, pid + 12, 0 , 0 , 12); - InsertVp9Gof(sn + 17, kF, kT , kT , kF, pid + 17, 0 , 0 , 17); - InsertVp9Gof(sn + 19, kF, kT , kT , kF, pid + 19, 0 , 0 , 19); - InsertVp9Gof(sn + 18, kF, kT , kT , kF, pid + 18, 0 , 0 , 18); - - ASSERT_EQ(20UL, frames_from_callback_.size()); - CheckReferencesVp9(pid, 0); - CheckReferencesVp9(pid + 1 , 0, pid); - CheckReferencesVp9(pid + 2 , 0, pid + 1); - CheckReferencesVp9(pid + 3 , 0, pid + 2); - CheckReferencesVp9(pid + 4 , 0, pid + 3); - CheckReferencesVp9(pid + 5 , 0, pid + 4); - CheckReferencesVp9(pid + 6 , 0, pid + 5); - CheckReferencesVp9(pid + 7 , 0, pid + 6); - CheckReferencesVp9(pid + 8 , 0, pid + 7); - CheckReferencesVp9(pid + 9 , 0, pid + 8); - CheckReferencesVp9(pid + 10, 0, pid + 9); - CheckReferencesVp9(pid + 11, 0, pid + 10); - CheckReferencesVp9(pid + 12, 0, pid + 11); - CheckReferencesVp9(pid + 13, 0, pid + 12); - CheckReferencesVp9(pid + 14, 0, pid + 13); - CheckReferencesVp9(pid + 15, 0, pid + 14); - CheckReferencesVp9(pid + 16, 0, pid + 15); - CheckReferencesVp9(pid + 17, 0, pid + 16); - CheckReferencesVp9(pid + 18, 0, pid + 17); - CheckReferencesVp9(pid + 19, 0, pid + 18); -} - -TEST_F(TestPacketBuffer, Vp9GofSkipFramesTemporalLayers_01) { - uint16_t pid = Rand(); - uint16_t sn = Rand(); - GofInfoVP9 ss; - ss.SetGofInfoVP9(kTemporalStructureMode2); // 0101 pattern - - // sn , kf, frst, lst, up, pid , sid, tid, tl0, ss - InsertVp9Gof(sn , kT, kT , kT , kF, pid , 0 , 0 , 0 , &ss); - InsertVp9Gof(sn + 1 , kF, kT , kT , kF, pid + 1 , 0 , 1 , 0); - // Skip GOF with tl0 1 - InsertVp9Gof(sn + 4 , kT, kT , kT , kF, pid + 4 , 0 , 0 , 2 , &ss); - InsertVp9Gof(sn + 5 , kF, kT , kT , kF, pid + 5 , 0 , 1 , 2); - // Skip GOF with tl0 3 - // Skip GOF with tl0 4 - InsertVp9Gof(sn + 10, kF, kT , kT , kF, pid + 10, 0 , 0 , 5 , &ss); - InsertVp9Gof(sn + 11, kF, kT , kT , kF, pid + 11, 0 , 1 , 5); - - ASSERT_EQ(6UL, frames_from_callback_.size()); - CheckReferencesVp9(pid, 0); - CheckReferencesVp9(pid + 1 , 0, pid); - CheckReferencesVp9(pid + 4 , 0); - CheckReferencesVp9(pid + 5 , 0, pid + 4); - CheckReferencesVp9(pid + 10, 0, pid + 8); - CheckReferencesVp9(pid + 11, 0, pid + 10); -} - -TEST_F(TestPacketBuffer, Vp9GofSkipFramesTemporalLayers_0212) { - uint16_t pid = Rand(); - uint16_t sn = Rand(); - GofInfoVP9 ss; - ss.SetGofInfoVP9(kTemporalStructureMode3); // 02120212 pattern - - // sn , kf, frst, lst, up, pid , sid, tid, tl0, ss - InsertVp9Gof(sn , kT, kT , kT , kF, pid , 0 , 0 , 0 , &ss); - InsertVp9Gof(sn + 1 , kF, kT , kT , kF, pid + 1 , 0 , 2 , 0); - InsertVp9Gof(sn + 2 , kF, kT , kT , kF, pid + 2 , 0 , 1 , 0); - InsertVp9Gof(sn + 3 , kF, kT , kT , kF, pid + 3 , 0 , 2 , 0); - - ASSERT_EQ(4UL, frames_from_callback_.size()); - CheckReferencesVp9(pid, 0); - CheckReferencesVp9(pid + 1 , 0, pid); - CheckReferencesVp9(pid + 2 , 0, pid); - CheckReferencesVp9(pid + 3 , 0, pid + 1, pid + 2); - - // Skip frames with tl0 = 1 - - // sn , kf, frst, lst, up, pid , sid, tid, tl0, ss - InsertVp9Gof(sn + 8 , kT, kT , kT , kF, pid + 8 , 0 , 0 , 2 , &ss); - InsertVp9Gof(sn + 9 , kF, kT , kT , kF, pid + 9 , 0 , 2 , 2); - InsertVp9Gof(sn + 10, kF, kT , kT , kF, pid + 10, 0 , 1 , 2); - InsertVp9Gof(sn + 11, kF, kT , kT , kF, pid + 11, 0 , 2 , 2); - - ASSERT_EQ(8UL, frames_from_callback_.size()); - CheckReferencesVp9(pid + 8, 0); - CheckReferencesVp9(pid + 9 , 0, pid + 8); - CheckReferencesVp9(pid + 10, 0, pid + 8); - CheckReferencesVp9(pid + 11, 0, pid + 9, pid + 10); - - // Now insert frames with tl0 = 1 - // sn , kf, frst, lst, up, pid , sid, tid, tl0, ss - InsertVp9Gof(sn + 4 , kT, kT , kT , kF, pid + 4 , 0 , 0 , 1 , &ss); - InsertVp9Gof(sn + 7 , kF, kT , kT , kF, pid + 7 , 0 , 2 , 1); - - ASSERT_EQ(9UL, frames_from_callback_.size()); - CheckReferencesVp9(pid + 4, 0); - - // Rest of frames belonging to tl0 = 1 - // sn , kf, frst, lst, up, pid , sid, tid, tl0, ss - InsertVp9Gof(sn + 5 , kF, kT , kT , kF, pid + 5 , 0 , 2 , 1); - InsertVp9Gof(sn + 6 , kF, kT , kT , kT, pid + 6 , 0 , 1 , 1); // up-switch - - ASSERT_EQ(12UL, frames_from_callback_.size()); - CheckReferencesVp9(pid + 5 , 0, pid + 4); - CheckReferencesVp9(pid + 6 , 0, pid + 4); - CheckReferencesVp9(pid + 7 , 0, pid + 6); -} - -TEST_F(TestPacketBuffer, Vp9GofTemporalLayers_01) { - uint16_t pid = Rand(); - uint16_t sn = Rand(); - GofInfoVP9 ss; - ss.SetGofInfoVP9(kTemporalStructureMode2); // 0101 pattern - - // sn , kf, frst, lst, up, pid , sid, tid, tl0, ss - InsertVp9Gof(sn , kT, kT , kT , kF, pid , 0 , 0 , 0 , &ss); - InsertVp9Gof(sn + 1 , kF, kT , kT , kF, pid + 1 , 0 , 1 , 0); - InsertVp9Gof(sn + 2 , kF, kT , kT , kF, pid + 2 , 0 , 0 , 1); - InsertVp9Gof(sn + 3 , kF, kT , kT , kF, pid + 3 , 0 , 1 , 1); - InsertVp9Gof(sn + 4 , kF, kT , kT , kF, pid + 4 , 0 , 0 , 2); - InsertVp9Gof(sn + 5 , kF, kT , kT , kF, pid + 5 , 0 , 1 , 2); - InsertVp9Gof(sn + 6 , kF, kT , kT , kF, pid + 6 , 0 , 0 , 3); - InsertVp9Gof(sn + 7 , kF, kT , kT , kF, pid + 7 , 0 , 1 , 3); - InsertVp9Gof(sn + 8 , kF, kT , kT , kF, pid + 8 , 0 , 0 , 4); - InsertVp9Gof(sn + 9 , kF, kT , kT , kF, pid + 9 , 0 , 1 , 4); - InsertVp9Gof(sn + 10, kF, kT , kT , kF, pid + 10, 0 , 0 , 5); - InsertVp9Gof(sn + 11, kF, kT , kT , kF, pid + 11, 0 , 1 , 5); - InsertVp9Gof(sn + 12, kF, kT , kT , kF, pid + 12, 0 , 0 , 6); - InsertVp9Gof(sn + 13, kF, kT , kT , kF, pid + 13, 0 , 1 , 6); - InsertVp9Gof(sn + 14, kF, kT , kT , kF, pid + 14, 0 , 0 , 7); - InsertVp9Gof(sn + 15, kF, kT , kT , kF, pid + 15, 0 , 1 , 7); - InsertVp9Gof(sn + 16, kF, kT , kT , kF, pid + 16, 0 , 0 , 8); - InsertVp9Gof(sn + 17, kF, kT , kT , kF, pid + 17, 0 , 1 , 8); - InsertVp9Gof(sn + 18, kF, kT , kT , kF, pid + 18, 0 , 0 , 9); - InsertVp9Gof(sn + 19, kF, kT , kT , kF, pid + 19, 0 , 1 , 9); - - ASSERT_EQ(20UL, frames_from_callback_.size()); - CheckReferencesVp9(pid, 0); - CheckReferencesVp9(pid + 1 , 0, pid); - CheckReferencesVp9(pid + 2 , 0, pid); - CheckReferencesVp9(pid + 3 , 0, pid + 2); - CheckReferencesVp9(pid + 4 , 0, pid + 2); - CheckReferencesVp9(pid + 5 , 0, pid + 4); - CheckReferencesVp9(pid + 6 , 0, pid + 4); - CheckReferencesVp9(pid + 7 , 0, pid + 6); - CheckReferencesVp9(pid + 8 , 0, pid + 6); - CheckReferencesVp9(pid + 9 , 0, pid + 8); - CheckReferencesVp9(pid + 10, 0, pid + 8); - CheckReferencesVp9(pid + 11, 0, pid + 10); - CheckReferencesVp9(pid + 12, 0, pid + 10); - CheckReferencesVp9(pid + 13, 0, pid + 12); - CheckReferencesVp9(pid + 14, 0, pid + 12); - CheckReferencesVp9(pid + 15, 0, pid + 14); - CheckReferencesVp9(pid + 16, 0, pid + 14); - CheckReferencesVp9(pid + 17, 0, pid + 16); - CheckReferencesVp9(pid + 18, 0, pid + 16); - CheckReferencesVp9(pid + 19, 0, pid + 18); -} - -TEST_F(TestPacketBuffer, Vp9GofTemporalLayersReordered_01) { - uint16_t pid = Rand(); - uint16_t sn = Rand(); - GofInfoVP9 ss; - ss.SetGofInfoVP9(kTemporalStructureMode2); // 01 pattern - - // sn , kf, frst, lst, up, pid , sid, tid, tl0, ss - InsertVp9Gof(sn + 1 , kF, kT , kT , kF, pid + 1 , 0 , 1 , 0); - InsertVp9Gof(sn , kT, kT , kT , kF, pid , 0 , 0 , 0 , &ss); - InsertVp9Gof(sn + 2 , kF, kT , kT , kF, pid + 2 , 0 , 0 , 1); - InsertVp9Gof(sn + 4 , kF, kT , kT , kF, pid + 4 , 0 , 0 , 2); - InsertVp9Gof(sn + 3 , kF, kT , kT , kF, pid + 3 , 0 , 1 , 1); - InsertVp9Gof(sn + 5 , kF, kT , kT , kF, pid + 5 , 0 , 1 , 2); - InsertVp9Gof(sn + 7 , kF, kT , kT , kF, pid + 7 , 0 , 1 , 3); - InsertVp9Gof(sn + 6 , kF, kT , kT , kF, pid + 6 , 0 , 0 , 3); - InsertVp9Gof(sn + 10, kF, kT , kT , kF, pid + 10, 0 , 0 , 5); - InsertVp9Gof(sn + 8 , kF, kT , kT , kF, pid + 8 , 0 , 0 , 4); - InsertVp9Gof(sn + 9 , kF, kT , kT , kF, pid + 9 , 0 , 1 , 4); - InsertVp9Gof(sn + 11, kF, kT , kT , kF, pid + 11, 0 , 1 , 5); - InsertVp9Gof(sn + 13, kF, kT , kT , kF, pid + 13, 0 , 1 , 6); - InsertVp9Gof(sn + 16, kF, kT , kT , kF, pid + 16, 0 , 0 , 8); - InsertVp9Gof(sn + 12, kF, kT , kT , kF, pid + 12, 0 , 0 , 6); - InsertVp9Gof(sn + 14, kF, kT , kT , kF, pid + 14, 0 , 0 , 7); - InsertVp9Gof(sn + 17, kF, kT , kT , kF, pid + 17, 0 , 1 , 8); - InsertVp9Gof(sn + 19, kF, kT , kT , kF, pid + 19, 0 , 1 , 9); - InsertVp9Gof(sn + 15, kF, kT , kT , kF, pid + 15, 0 , 1 , 7); - InsertVp9Gof(sn + 18, kF, kT , kT , kF, pid + 18, 0 , 0 , 9); - - ASSERT_EQ(20UL, frames_from_callback_.size()); - CheckReferencesVp9(pid, 0); - CheckReferencesVp9(pid + 1 , 0, pid); - CheckReferencesVp9(pid + 2 , 0, pid); - CheckReferencesVp9(pid + 3 , 0, pid + 2); - CheckReferencesVp9(pid + 4 , 0, pid + 2); - CheckReferencesVp9(pid + 5 , 0, pid + 4); - CheckReferencesVp9(pid + 6 , 0, pid + 4); - CheckReferencesVp9(pid + 7 , 0, pid + 6); - CheckReferencesVp9(pid + 8 , 0, pid + 6); - CheckReferencesVp9(pid + 9 , 0, pid + 8); - CheckReferencesVp9(pid + 10, 0, pid + 8); - CheckReferencesVp9(pid + 11, 0, pid + 10); - CheckReferencesVp9(pid + 12, 0, pid + 10); - CheckReferencesVp9(pid + 13, 0, pid + 12); - CheckReferencesVp9(pid + 14, 0, pid + 12); - CheckReferencesVp9(pid + 15, 0, pid + 14); - CheckReferencesVp9(pid + 16, 0, pid + 14); - CheckReferencesVp9(pid + 17, 0, pid + 16); - CheckReferencesVp9(pid + 18, 0, pid + 16); - CheckReferencesVp9(pid + 19, 0, pid + 18); -} - -TEST_F(TestPacketBuffer, Vp9GofTemporalLayers_0212) { - uint16_t pid = Rand(); - uint16_t sn = Rand(); - GofInfoVP9 ss; - ss.SetGofInfoVP9(kTemporalStructureMode3); // 0212 pattern - - // sn , kf, frst, lst, up, pid , sid, tid, tl0, ss - InsertVp9Gof(sn , kT, kT , kT , kF, pid , 0 , 0 , 0 , &ss); - InsertVp9Gof(sn + 1 , kF, kT , kT , kF, pid + 1 , 0 , 2 , 0); - InsertVp9Gof(sn + 2 , kF, kT , kT , kF, pid + 2 , 0 , 1 , 0); - InsertVp9Gof(sn + 3 , kF, kT , kT , kF, pid + 3 , 0 , 2 , 0); - InsertVp9Gof(sn + 4 , kF, kT , kT , kF, pid + 4 , 0 , 0 , 1); - InsertVp9Gof(sn + 5 , kF, kT , kT , kF, pid + 5 , 0 , 2 , 1); - InsertVp9Gof(sn + 6 , kF, kT , kT , kF, pid + 6 , 0 , 1 , 1); - InsertVp9Gof(sn + 7 , kF, kT , kT , kF, pid + 7 , 0 , 2 , 1); - InsertVp9Gof(sn + 8 , kF, kT , kT , kF, pid + 8 , 0 , 0 , 2); - InsertVp9Gof(sn + 9 , kF, kT , kT , kF, pid + 9 , 0 , 2 , 2); - InsertVp9Gof(sn + 10, kF, kT , kT , kF, pid + 10, 0 , 1 , 2); - InsertVp9Gof(sn + 11, kF, kT , kT , kF, pid + 11, 0 , 2 , 2); - InsertVp9Gof(sn + 12, kF, kT , kT , kF, pid + 12, 0 , 0 , 3); - InsertVp9Gof(sn + 13, kF, kT , kT , kF, pid + 13, 0 , 2 , 3); - InsertVp9Gof(sn + 14, kF, kT , kT , kF, pid + 14, 0 , 1 , 3); - InsertVp9Gof(sn + 15, kF, kT , kT , kF, pid + 15, 0 , 2 , 3); - InsertVp9Gof(sn + 16, kF, kT , kT , kF, pid + 16, 0 , 0 , 4); - InsertVp9Gof(sn + 17, kF, kT , kT , kF, pid + 17, 0 , 2 , 4); - InsertVp9Gof(sn + 18, kF, kT , kT , kF, pid + 18, 0 , 1 , 4); - InsertVp9Gof(sn + 19, kF, kT , kT , kF, pid + 19, 0 , 2 , 4); - - ASSERT_EQ(20UL, frames_from_callback_.size()); - CheckReferencesVp9(pid, 0); - CheckReferencesVp9(pid + 1 , 0, pid); - CheckReferencesVp9(pid + 2 , 0, pid); - CheckReferencesVp9(pid + 3 , 0, pid + 1, pid + 2); - CheckReferencesVp9(pid + 4 , 0, pid); - CheckReferencesVp9(pid + 5 , 0, pid + 4); - CheckReferencesVp9(pid + 6 , 0, pid + 4); - CheckReferencesVp9(pid + 7 , 0, pid + 5, pid + 6); - CheckReferencesVp9(pid + 8 , 0, pid + 4); - CheckReferencesVp9(pid + 9 , 0, pid + 8); - CheckReferencesVp9(pid + 10, 0, pid + 8); - CheckReferencesVp9(pid + 11, 0, pid + 9, pid + 10); - CheckReferencesVp9(pid + 12, 0, pid + 8); - CheckReferencesVp9(pid + 13, 0, pid + 12); - CheckReferencesVp9(pid + 14, 0, pid + 12); - CheckReferencesVp9(pid + 15, 0, pid + 13, pid + 14); - CheckReferencesVp9(pid + 16, 0, pid + 12); - CheckReferencesVp9(pid + 17, 0, pid + 16); - CheckReferencesVp9(pid + 18, 0, pid + 16); - CheckReferencesVp9(pid + 19, 0, pid + 17, pid + 18); -} - -TEST_F(TestPacketBuffer, Vp9GofTemporalLayersReordered_0212) { - uint16_t pid = Rand(); - uint16_t sn = Rand(); - GofInfoVP9 ss; - ss.SetGofInfoVP9(kTemporalStructureMode3); // 0212 pattern - - // sn , kf, frst, lst, up, pid , sid, tid, tl0, ss - InsertVp9Gof(sn + 2 , kF, kT , kT , kF, pid + 2 , 0 , 1 , 0); - InsertVp9Gof(sn + 1 , kF, kT , kT , kF, pid + 1 , 0 , 2 , 0); - InsertVp9Gof(sn , kT, kT , kT , kF, pid , 0 , 0 , 0 , &ss); - InsertVp9Gof(sn + 3 , kF, kT , kT , kF, pid + 3 , 0 , 2 , 0); - InsertVp9Gof(sn + 6 , kF, kT , kT , kF, pid + 6 , 0 , 1 , 1); - InsertVp9Gof(sn + 5 , kF, kT , kT , kF, pid + 5 , 0 , 2 , 1); - InsertVp9Gof(sn + 4 , kF, kT , kT , kF, pid + 4 , 0 , 0 , 1); - InsertVp9Gof(sn + 9 , kF, kT , kT , kF, pid + 9 , 0 , 2 , 2); - InsertVp9Gof(sn + 7 , kF, kT , kT , kF, pid + 7 , 0 , 2 , 1); - InsertVp9Gof(sn + 8 , kF, kT , kT , kF, pid + 8 , 0 , 0 , 2); - InsertVp9Gof(sn + 11, kF, kT , kT , kF, pid + 11, 0 , 2 , 2); - InsertVp9Gof(sn + 10, kF, kT , kT , kF, pid + 10, 0 , 1 , 2); - InsertVp9Gof(sn + 13, kF, kT , kT , kF, pid + 13, 0 , 2 , 3); - InsertVp9Gof(sn + 12, kF, kT , kT , kF, pid + 12, 0 , 0 , 3); - InsertVp9Gof(sn + 14, kF, kT , kT , kF, pid + 14, 0 , 1 , 3); - InsertVp9Gof(sn + 16, kF, kT , kT , kF, pid + 16, 0 , 0 , 4); - InsertVp9Gof(sn + 15, kF, kT , kT , kF, pid + 15, 0 , 2 , 3); - InsertVp9Gof(sn + 17, kF, kT , kT , kF, pid + 17, 0 , 2 , 4); - InsertVp9Gof(sn + 19, kF, kT , kT , kF, pid + 19, 0 , 2 , 4); - InsertVp9Gof(sn + 18, kF, kT , kT , kF, pid + 18, 0 , 1 , 4); - - ASSERT_EQ(20UL, frames_from_callback_.size()); - CheckReferencesVp9(pid, 0); - CheckReferencesVp9(pid + 1 , 0, pid); - CheckReferencesVp9(pid + 2 , 0, pid); - CheckReferencesVp9(pid + 3 , 0, pid + 1, pid + 2); - CheckReferencesVp9(pid + 4 , 0, pid); - CheckReferencesVp9(pid + 5 , 0, pid + 4); - CheckReferencesVp9(pid + 6 , 0, pid + 4); - CheckReferencesVp9(pid + 7 , 0, pid + 5, pid + 6); - CheckReferencesVp9(pid + 8 , 0, pid + 4); - CheckReferencesVp9(pid + 9 , 0, pid + 8); - CheckReferencesVp9(pid + 10, 0, pid + 8); - CheckReferencesVp9(pid + 11, 0, pid + 9, pid + 10); - CheckReferencesVp9(pid + 12, 0, pid + 8); - CheckReferencesVp9(pid + 13, 0, pid + 12); - CheckReferencesVp9(pid + 14, 0, pid + 12); - CheckReferencesVp9(pid + 15, 0, pid + 13, pid + 14); - CheckReferencesVp9(pid + 16, 0, pid + 12); - CheckReferencesVp9(pid + 17, 0, pid + 16); - CheckReferencesVp9(pid + 18, 0, pid + 16); - CheckReferencesVp9(pid + 19, 0, pid + 17, pid + 18); -} - -TEST_F(TestPacketBuffer, Vp9GofTemporalLayersUpSwitch_02120212) { - uint16_t pid = Rand(); - uint16_t sn = Rand(); - GofInfoVP9 ss; - ss.SetGofInfoVP9(kTemporalStructureMode4); // 02120212 pattern - - // sn , kf, frst, lst, up, pid , sid, tid, tl0, ss - InsertVp9Gof(sn , kT, kT , kT , kF, pid , 0 , 0 , 0 , &ss); - InsertVp9Gof(sn + 1 , kF, kT , kT , kF, pid + 1 , 0 , 2 , 0); - InsertVp9Gof(sn + 2 , kF, kT , kT , kF, pid + 2 , 0 , 1 , 0); - InsertVp9Gof(sn + 3 , kF, kT , kT , kF, pid + 3 , 0 , 2 , 0); - InsertVp9Gof(sn + 4 , kF, kT , kT , kF, pid + 4 , 0 , 0 , 1); - InsertVp9Gof(sn + 5 , kF, kT , kT , kF, pid + 5 , 0 , 2 , 1); - InsertVp9Gof(sn + 6 , kF, kT , kT , kT, pid + 6 , 0 , 1 , 1); - InsertVp9Gof(sn + 7 , kF, kT , kT , kF, pid + 7 , 0 , 2 , 1); - InsertVp9Gof(sn + 8 , kF, kT , kT , kT, pid + 8 , 0 , 0 , 2); - InsertVp9Gof(sn + 9 , kF, kT , kT , kF, pid + 9 , 0 , 2 , 2); - InsertVp9Gof(sn + 10, kF, kT , kT , kF, pid + 10, 0 , 1 , 2); - InsertVp9Gof(sn + 11, kF, kT , kT , kT, pid + 11, 0 , 2 , 2); - InsertVp9Gof(sn + 12, kF, kT , kT , kF, pid + 12, 0 , 0 , 3); - InsertVp9Gof(sn + 13, kF, kT , kT , kF, pid + 13, 0 , 2 , 3); - InsertVp9Gof(sn + 14, kF, kT , kT , kF, pid + 14, 0 , 1 , 3); - InsertVp9Gof(sn + 15, kF, kT , kT , kF, pid + 15, 0 , 2 , 3); - - ASSERT_EQ(16UL, frames_from_callback_.size()); - CheckReferencesVp9(pid, 0); - CheckReferencesVp9(pid + 1 , 0, pid); - CheckReferencesVp9(pid + 2 , 0, pid); - CheckReferencesVp9(pid + 3 , 0, pid + 1, pid + 2); - CheckReferencesVp9(pid + 4 , 0, pid); - CheckReferencesVp9(pid + 5 , 0, pid + 3, pid + 4); - CheckReferencesVp9(pid + 6 , 0, pid + 2, pid + 4); - CheckReferencesVp9(pid + 7 , 0, pid + 6); - CheckReferencesVp9(pid + 8 , 0, pid + 4); - CheckReferencesVp9(pid + 9 , 0, pid + 8); - CheckReferencesVp9(pid + 10, 0, pid + 8); - CheckReferencesVp9(pid + 11, 0, pid + 9, pid + 10); - CheckReferencesVp9(pid + 12, 0, pid + 8); - CheckReferencesVp9(pid + 13, 0, pid + 11, pid + 12); - CheckReferencesVp9(pid + 14, 0, pid + 10, pid + 12); - CheckReferencesVp9(pid + 15, 0, pid + 13, pid + 14); -} - -TEST_F(TestPacketBuffer, Vp9GofTemporalLayersUpSwitchReordered_02120212) { - uint16_t pid = Rand(); - uint16_t sn = Rand(); - GofInfoVP9 ss; - ss.SetGofInfoVP9(kTemporalStructureMode4); // 02120212 pattern - - // sn , kf, frst, lst, up, pid , sid, tid, tl0, ss - InsertVp9Gof(sn + 1 , kF, kT , kT , kF, pid + 1 , 0 , 2 , 0); - InsertVp9Gof(sn , kT, kT , kT , kF, pid , 0 , 0 , 0 , &ss); - InsertVp9Gof(sn + 4 , kF, kT , kT , kF, pid + 4 , 0 , 0 , 1); - InsertVp9Gof(sn + 2 , kF, kT , kT , kF, pid + 2 , 0 , 1 , 0); - InsertVp9Gof(sn + 5 , kF, kT , kT , kF, pid + 5 , 0 , 2 , 1); - InsertVp9Gof(sn + 3 , kF, kT , kT , kF, pid + 3 , 0 , 2 , 0); - InsertVp9Gof(sn + 7 , kF, kT , kT , kF, pid + 7 , 0 , 2 , 1); - InsertVp9Gof(sn + 9 , kF, kT , kT , kF, pid + 9 , 0 , 2 , 2); - InsertVp9Gof(sn + 6 , kF, kT , kT , kT, pid + 6 , 0 , 1 , 1); - InsertVp9Gof(sn + 12, kF, kT , kT , kF, pid + 12, 0 , 0 , 3); - InsertVp9Gof(sn + 10, kF, kT , kT , kF, pid + 10, 0 , 1 , 2); - InsertVp9Gof(sn + 8 , kF, kT , kT , kT, pid + 8 , 0 , 0 , 2); - InsertVp9Gof(sn + 11, kF, kT , kT , kT, pid + 11, 0 , 2 , 2); - InsertVp9Gof(sn + 13, kF, kT , kT , kF, pid + 13, 0 , 2 , 3); - InsertVp9Gof(sn + 15, kF, kT , kT , kF, pid + 15, 0 , 2 , 3); - InsertVp9Gof(sn + 14, kF, kT , kT , kF, pid + 14, 0 , 1 , 3); - - ASSERT_EQ(16UL, frames_from_callback_.size()); - CheckReferencesVp9(pid, 0); - CheckReferencesVp9(pid + 1 , 0, pid); - CheckReferencesVp9(pid + 2 , 0, pid); - CheckReferencesVp9(pid + 3 , 0, pid + 1, pid + 2); - CheckReferencesVp9(pid + 4 , 0, pid); - CheckReferencesVp9(pid + 5 , 0, pid + 3, pid + 4); - CheckReferencesVp9(pid + 6 , 0, pid + 2, pid + 4); - CheckReferencesVp9(pid + 7 , 0, pid + 6); - CheckReferencesVp9(pid + 8 , 0, pid + 4); - CheckReferencesVp9(pid + 9 , 0, pid + 8); - CheckReferencesVp9(pid + 10, 0, pid + 8); - CheckReferencesVp9(pid + 11, 0, pid + 9, pid + 10); - CheckReferencesVp9(pid + 12, 0, pid + 8); - CheckReferencesVp9(pid + 13, 0, pid + 11, pid + 12); - CheckReferencesVp9(pid + 14, 0, pid + 10, pid + 12); - CheckReferencesVp9(pid + 15, 0, pid + 13, pid + 14); -} - -TEST_F(TestPacketBuffer, Vp9GofTemporalLayersReordered_01_0212) { - uint16_t pid = Rand(); - uint16_t sn = Rand(); - GofInfoVP9 ss; - ss.SetGofInfoVP9(kTemporalStructureMode2); // 01 pattern - - // sn , kf, frst, lst, up, pid , sid, tid, tl0, ss - InsertVp9Gof(sn + 1 , kF, kT , kT , kF, pid + 1 , 0 , 1 , 0); - InsertVp9Gof(sn , kT, kT , kT , kF, pid , 0 , 0 , 0 , &ss); - InsertVp9Gof(sn + 3 , kF, kT , kT , kF, pid + 3 , 0 , 1 , 1); - InsertVp9Gof(sn + 6 , kF, kT , kT , kF, pid + 6 , 0 , 1 , 2); - ss.SetGofInfoVP9(kTemporalStructureMode3); // 0212 pattern - InsertVp9Gof(sn + 4 , kF, kT , kT , kF, pid + 4 , 0 , 0 , 2 , &ss); - InsertVp9Gof(sn + 2 , kF, kT , kT , kF, pid + 2 , 0 , 0 , 1); - InsertVp9Gof(sn + 5 , kF, kT , kT , kF, pid + 5 , 0 , 2 , 2); - InsertVp9Gof(sn + 8 , kF, kT , kT , kF, pid + 8 , 0 , 0 , 3); - InsertVp9Gof(sn + 10, kF, kT , kT , kF, pid + 10, 0 , 1 , 3); - InsertVp9Gof(sn + 7 , kF, kT , kT , kF, pid + 7 , 0 , 2 , 2); - InsertVp9Gof(sn + 11, kF, kT , kT , kF, pid + 11, 0 , 2 , 3); - InsertVp9Gof(sn + 9 , kF, kT , kT , kF, pid + 9 , 0 , 2 , 3); - - ASSERT_EQ(12UL, frames_from_callback_.size()); - CheckReferencesVp9(pid, 0); - CheckReferencesVp9(pid + 1 , 0, pid); - CheckReferencesVp9(pid + 2 , 0, pid); - CheckReferencesVp9(pid + 3 , 0, pid + 2); - CheckReferencesVp9(pid + 4 , 0, pid); - CheckReferencesVp9(pid + 5 , 0, pid + 4); - CheckReferencesVp9(pid + 6 , 0, pid + 4); - CheckReferencesVp9(pid + 7 , 0, pid + 5, pid + 6); - CheckReferencesVp9(pid + 8 , 0, pid + 4); - CheckReferencesVp9(pid + 9 , 0, pid + 8); - CheckReferencesVp9(pid + 10, 0, pid + 8); - CheckReferencesVp9(pid + 11, 0, pid + 9, pid + 10); -} - -TEST_F(TestPacketBuffer, Vp9FlexibleModeOneFrame) { - uint16_t pid = Rand(); - uint16_t sn = Rand(); - - // sn, kf, frst, lst, intr, pid, sid, tid, tl0 - InsertVp9Flex(sn, kT, kT , kT , kF , pid, 0 , 0 , 0); - - ASSERT_EQ(1UL, frames_from_callback_.size()); - CheckReferencesVp9(pid, 0); -} - -TEST_F(TestPacketBuffer, Vp9FlexibleModeTwoSpatialLayers) { - uint16_t pid = Rand(); - uint16_t sn = Rand(); - - // sn , kf, frst, lst, intr, pid , sid, tid, tl0, refs - InsertVp9Flex(sn , kT, kT , kT , kF , pid , 0 , 0 , 0); - InsertVp9Flex(sn + 1 , kT, kT , kT , kT , pid , 1 , 0 , 0); - InsertVp9Flex(sn + 2 , kF, kT , kT , kF , pid + 1, 1 , 0 , 0 , {1}); - InsertVp9Flex(sn + 3 , kF, kT , kT , kF , pid + 2, 0 , 0 , 1 , {2}); - InsertVp9Flex(sn + 4 , kF, kT , kT , kF , pid + 2, 1 , 0 , 1 , {1}); - InsertVp9Flex(sn + 5 , kF, kT , kT , kF , pid + 3, 1 , 0 , 1 , {1}); - InsertVp9Flex(sn + 6 , kF, kT , kT , kF , pid + 4, 0 , 0 , 2 , {2}); - InsertVp9Flex(sn + 7 , kF, kT , kT , kF , pid + 4, 1 , 0 , 2 , {1}); - InsertVp9Flex(sn + 8 , kF, kT , kT , kF , pid + 5, 1 , 0 , 2 , {1}); - InsertVp9Flex(sn + 9 , kF, kT , kT , kF , pid + 6, 0 , 0 , 3 , {2}); - InsertVp9Flex(sn + 10, kF, kT , kT , kF , pid + 6, 1 , 0 , 3 , {1}); - InsertVp9Flex(sn + 11, kF, kT , kT , kF , pid + 7, 1 , 0 , 3 , {1}); - InsertVp9Flex(sn + 12, kF, kT , kT , kF , pid + 8, 0 , 0 , 4 , {2}); - InsertVp9Flex(sn + 13, kF, kT , kT , kF , pid + 8, 1 , 0 , 4 , {1}); - - ASSERT_EQ(14UL, frames_from_callback_.size()); - CheckReferencesVp9(pid , 0); - CheckReferencesVp9(pid , 1); - CheckReferencesVp9(pid + 1, 1, pid); - CheckReferencesVp9(pid + 2, 0, pid); - CheckReferencesVp9(pid + 2, 1, pid + 1); - CheckReferencesVp9(pid + 3, 1, pid + 2); - CheckReferencesVp9(pid + 4, 0, pid + 2); - CheckReferencesVp9(pid + 4, 1, pid + 3); - CheckReferencesVp9(pid + 5, 1, pid + 4); - CheckReferencesVp9(pid + 6, 0, pid + 4); - CheckReferencesVp9(pid + 6, 1, pid + 5); - CheckReferencesVp9(pid + 7, 1, pid + 6); - CheckReferencesVp9(pid + 8, 0, pid + 6); - CheckReferencesVp9(pid + 8, 1, pid + 7); -} - -TEST_F(TestPacketBuffer, Vp9FlexibleModeTwoSpatialLayersReordered) { - uint16_t pid = Rand(); - uint16_t sn = Rand(); - - // sn , kf, frst, lst, intr, pid , sid, tid, tl0, refs - InsertVp9Flex(sn + 1 , kT, kT , kT , kT , pid , 1 , 0 , 0); - InsertVp9Flex(sn + 2 , kF, kT , kT , kF , pid + 1, 1 , 0 , 0 , {1}); - InsertVp9Flex(sn , kT, kT , kT , kF , pid , 0 , 0 , 0); - InsertVp9Flex(sn + 4 , kF, kT , kT , kF , pid + 2, 1 , 0 , 1 , {1}); - InsertVp9Flex(sn + 5 , kF, kT , kT , kF , pid + 3, 1 , 0 , 1 , {1}); - InsertVp9Flex(sn + 3 , kF, kT , kT , kF , pid + 2, 0 , 0 , 1 , {2}); - InsertVp9Flex(sn + 7 , kF, kT , kT , kF , pid + 4, 1 , 0 , 2 , {1}); - InsertVp9Flex(sn + 6 , kF, kT , kT , kF , pid + 4, 0 , 0 , 2 , {2}); - InsertVp9Flex(sn + 8 , kF, kT , kT , kF , pid + 5, 1 , 0 , 2 , {1}); - InsertVp9Flex(sn + 9 , kF, kT , kT , kF , pid + 6, 0 , 0 , 3 , {2}); - InsertVp9Flex(sn + 11, kF, kT , kT , kF , pid + 7, 1 , 0 , 3 , {1}); - InsertVp9Flex(sn + 10, kF, kT , kT , kF , pid + 6, 1 , 0 , 3 , {1}); - InsertVp9Flex(sn + 13, kF, kT , kT , kF , pid + 8, 1 , 0 , 4 , {1}); - InsertVp9Flex(sn + 12, kF, kT , kT , kF , pid + 8, 0 , 0 , 4 , {2}); - - ASSERT_EQ(14UL, frames_from_callback_.size()); - CheckReferencesVp9(pid , 0); - CheckReferencesVp9(pid , 1); - CheckReferencesVp9(pid + 1, 1, pid); - CheckReferencesVp9(pid + 2, 0, pid); - CheckReferencesVp9(pid + 2, 1, pid + 1); - CheckReferencesVp9(pid + 3, 1, pid + 2); - CheckReferencesVp9(pid + 4, 0, pid + 2); - CheckReferencesVp9(pid + 4, 1, pid + 3); - CheckReferencesVp9(pid + 5, 1, pid + 4); - CheckReferencesVp9(pid + 6, 0, pid + 4); - CheckReferencesVp9(pid + 6, 1, pid + 5); - CheckReferencesVp9(pid + 7, 1, pid + 6); - CheckReferencesVp9(pid + 8, 0, pid + 6); - CheckReferencesVp9(pid + 8, 1, pid + 7); -} - } // namespace video_coding } // namespace webrtc