diff options
Diffstat (limited to 'third_party/libwebrtc/modules/video_coding')
14 files changed, 130 insertions, 225 deletions
diff --git a/third_party/libwebrtc/modules/video_coding/BUILD.gn b/third_party/libwebrtc/modules/video_coding/BUILD.gn index d9e614ff81..0457b818c3 100644 --- a/third_party/libwebrtc/modules/video_coding/BUILD.gn +++ b/third_party/libwebrtc/modules/video_coding/BUILD.gn @@ -218,6 +218,7 @@ rtc_library("video_coding") { "../../api:rtp_packet_info", "../../api:scoped_refptr", "../../api:sequence_checker", + "../../api/environment", "../../api/task_queue", "../../api/units:data_rate", "../../api/units:data_size", @@ -258,7 +259,6 @@ rtc_library("video_coding") { "../../rtc_base/task_utils:repeating_task", "../../rtc_base/third_party/base64", "../../system_wrappers", - "../../system_wrappers:field_trial", "../../system_wrappers:metrics", "../../video/config:encoder_config", "../rtp_rtcp", @@ -1217,6 +1217,7 @@ if (rtc_include_tests) { "../../api:scoped_refptr", "../../api:simulcast_test_fixture_api", "../../api:videocodec_test_fixture_api", + "../../api/environment:environment_factory", "../../api/task_queue", "../../api/task_queue:default_task_queue_factory", "../../api/test/video:function_video_factory", diff --git a/third_party/libwebrtc/modules/video_coding/codecs/av1/dav1d_decoder.cc b/third_party/libwebrtc/modules/video_coding/codecs/av1/dav1d_decoder.cc index 6a787ff935..d658e401e8 100644 --- a/third_party/libwebrtc/modules/video_coding/codecs/av1/dav1d_decoder.cc +++ b/third_party/libwebrtc/modules/video_coding/codecs/av1/dav1d_decoder.cc @@ -87,6 +87,8 @@ bool Dav1dDecoder::Configure(const Settings& settings) { s.n_threads = std::max(2, settings.number_of_cores()); s.max_frame_delay = 1; // For low latency decoding. s.all_layers = 0; // Don't output a frame for every spatial layer. + // Limit max frame size to avoid OOM'ing fuzzers. crbug.com/325284120. + s.frame_size_limit = 16384 * 16384; s.operating_point = 31; // Decode all operating points. return dav1d_open(&context_, &s) == 0; diff --git a/third_party/libwebrtc/modules/video_coding/codecs/av1/libaom_av1_unittest.cc b/third_party/libwebrtc/modules/video_coding/codecs/av1/libaom_av1_unittest.cc index 766b7660e4..d486c1d062 100644 --- a/third_party/libwebrtc/modules/video_coding/codecs/av1/libaom_av1_unittest.cc +++ b/third_party/libwebrtc/modules/video_coding/codecs/av1/libaom_av1_unittest.cc @@ -350,7 +350,8 @@ INSTANTIATE_TEST_SUITE_P( SvcTestParam{"L3T1", /*num_frames_to_generate=*/3}, SvcTestParam{"L3T3", /*num_frames_to_generate=*/8}, SvcTestParam{"S2T1", /*num_frames_to_generate=*/3}, - SvcTestParam{"S3T3", /*num_frames_to_generate=*/8}, + // TODO: bugs.webrtc.org/15715 - Re-enable once AV1 is fixed. + // SvcTestParam{"S3T3", /*num_frames_to_generate=*/8}, SvcTestParam{"L2T2", /*num_frames_to_generate=*/4}, SvcTestParam{"L2T2_KEY", /*num_frames_to_generate=*/4}, SvcTestParam{"L2T2_KEY_SHIFT", diff --git a/third_party/libwebrtc/modules/video_coding/codecs/h264/h264_decoder_impl.cc b/third_party/libwebrtc/modules/video_coding/codecs/h264/h264_decoder_impl.cc index a9e9926c4f..c6446c25ce 100644 --- a/third_party/libwebrtc/modules/video_coding/codecs/h264/h264_decoder_impl.cc +++ b/third_party/libwebrtc/modules/video_coding/codecs/h264/h264_decoder_impl.cc @@ -80,7 +80,11 @@ int H264DecoderImpl::AVGetBuffer2(AVCodecContext* context, kPixelFormatsSupported.begin(), kPixelFormatsSupported.end(), [context](AVPixelFormat format) { return context->pix_fmt == format; }); - RTC_CHECK(pixelFormatSupported != kPixelFormatsSupported.end()); + if (pixelFormatSupported == kPixelFormatsSupported.end()) { + RTC_LOG(LS_ERROR) << "Unsupported pixel format: " << context->pix_fmt; + decoder->ReportError(); + return -1; + } // `av_frame->width` and `av_frame->height` are set by FFmpeg. These are the // actual image's dimensions and may be different from `context->width` and diff --git a/third_party/libwebrtc/modules/video_coding/codecs/test/video_codec_test.cc b/third_party/libwebrtc/modules/video_coding/codecs/test/video_codec_test.cc index 60c2fcbb6e..2ab1106a59 100644 --- a/third_party/libwebrtc/modules/video_coding/codecs/test/video_codec_test.cc +++ b/third_party/libwebrtc/modules/video_coding/codecs/test/video_codec_test.cc @@ -178,7 +178,8 @@ std::string TestOutputPath() { } // namespace std::unique_ptr<VideoCodecStats> RunEncodeDecodeTest( - std::string codec_impl, + std::string encoder_impl, + std::string decoder_impl, const VideoInfo& video_info, const std::map<uint32_t, EncodingSettings>& encoding_settings) { VideoSourceSettings source_settings{ @@ -190,28 +191,34 @@ std::unique_ptr<VideoCodecStats> RunEncodeDecodeTest( encoding_settings.begin()->second.sdp_video_format; std::unique_ptr<VideoEncoderFactory> encoder_factory = - CreateEncoderFactory(codec_impl); + CreateEncoderFactory(encoder_impl); if (!encoder_factory ->QueryCodecSupport(sdp_video_format, /*scalability_mode=*/absl::nullopt) .is_supported) { - RTC_LOG(LS_WARNING) << "No encoder for video format " + RTC_LOG(LS_WARNING) << "No " << encoder_impl << " encoder for video format " << sdp_video_format.ToString(); return nullptr; } std::unique_ptr<VideoDecoderFactory> decoder_factory = - CreateDecoderFactory(codec_impl); + CreateDecoderFactory(decoder_impl); if (!decoder_factory ->QueryCodecSupport(sdp_video_format, /*reference_scaling=*/false) .is_supported) { + RTC_LOG(LS_WARNING) << "No " << decoder_impl << " decoder for video format " + << sdp_video_format.ToString() + << ". Trying built-in decoder."; + // TODO(ssilkin): No H264 support in ffmpeg on ARM. Consider trying HW + // decoder. decoder_factory = CreateDecoderFactory("builtin"); if (!decoder_factory ->QueryCodecSupport(sdp_video_format, /*reference_scaling=*/false) .is_supported) { - RTC_LOG(LS_WARNING) << "No decoder for video format " + RTC_LOG(LS_WARNING) << "No " << decoder_impl + << " decoder for video format " << sdp_video_format.ToString(); return nullptr; } @@ -221,7 +228,7 @@ std::unique_ptr<VideoCodecStats> RunEncodeDecodeTest( VideoCodecTester::EncoderSettings encoder_settings; encoder_settings.pacing_settings.mode = - codec_impl == "builtin" ? PacingMode::kNoPacing : PacingMode::kRealTime; + encoder_impl == "builtin" ? PacingMode::kNoPacing : PacingMode::kRealTime; if (absl::GetFlag(FLAGS_dump_encoder_input)) { encoder_settings.encoder_input_base_path = output_path + "_enc_input"; } @@ -231,7 +238,7 @@ std::unique_ptr<VideoCodecStats> RunEncodeDecodeTest( VideoCodecTester::DecoderSettings decoder_settings; decoder_settings.pacing_settings.mode = - codec_impl == "builtin" ? PacingMode::kNoPacing : PacingMode::kRealTime; + decoder_impl == "builtin" ? PacingMode::kNoPacing : PacingMode::kRealTime; if (absl::GetFlag(FLAGS_dump_decoder_input)) { decoder_settings.decoder_input_base_path = output_path + "_dec_input"; } @@ -318,7 +325,7 @@ TEST_P(SpatialQualityTest, SpatialQuality) { {bitrate_kbps}, framerate_fps, num_frames); std::unique_ptr<VideoCodecStats> stats = - RunEncodeDecodeTest(codec_impl, video_info, frames_settings); + RunEncodeDecodeTest(codec_impl, codec_impl, video_info, frames_settings); VideoCodecStats::Stream stream; if (stats != nullptr) { @@ -348,15 +355,15 @@ INSTANTIATE_TEST_SUITE_P( Values("builtin"), #endif Values(kRawVideos.at("FourPeople_1280x720_30")), - Values(std::make_tuple(320, 180, 30, 32, 28), - std::make_tuple(320, 180, 30, 64, 30), - std::make_tuple(320, 180, 30, 128, 33), + Values(std::make_tuple(320, 180, 30, 32, 26), + std::make_tuple(320, 180, 30, 64, 29), + std::make_tuple(320, 180, 30, 128, 32), std::make_tuple(320, 180, 30, 256, 36), - std::make_tuple(640, 360, 30, 128, 31), + std::make_tuple(640, 360, 30, 128, 29), std::make_tuple(640, 360, 30, 256, 33), std::make_tuple(640, 360, 30, 384, 35), std::make_tuple(640, 360, 30, 512, 36), - std::make_tuple(1280, 720, 30, 256, 32), + std::make_tuple(1280, 720, 30, 256, 30), std::make_tuple(1280, 720, 30, 512, 34), std::make_tuple(1280, 720, 30, 1024, 37), std::make_tuple(1280, 720, 30, 2048, 39))), @@ -538,6 +545,7 @@ TEST(VideoCodecTest, DISABLED_EncodeDecode) { // Sync with changes in Stream::LogMetrics (see TODOs there). std::unique_ptr<VideoCodecStats> stats = RunEncodeDecodeTest( CodecNameToCodecImpl(absl::GetFlag(FLAGS_encoder)), + CodecNameToCodecImpl(absl::GetFlag(FLAGS_decoder)), kRawVideos.at(absl::GetFlag(FLAGS_video_name)), frames_settings); ASSERT_NE(nullptr, stats); diff --git a/third_party/libwebrtc/modules/video_coding/codecs/test/videocodec_test_fixture_impl.cc b/third_party/libwebrtc/modules/video_coding/codecs/test/videocodec_test_fixture_impl.cc index eb264e5285..35355d4387 100644 --- a/third_party/libwebrtc/modules/video_coding/codecs/test/videocodec_test_fixture_impl.cc +++ b/third_party/libwebrtc/modules/video_coding/codecs/test/videocodec_test_fixture_impl.cc @@ -167,7 +167,7 @@ SdpVideoFormat CreateSdpVideoFormat( H264PacketizationMode::NonInterleaved ? "1" : "0"; - SdpVideoFormat::Parameters codec_params = { + CodecParameterMap codec_params = { {cricket::kH264FmtpProfileLevelId, *H264ProfileLevelIdToString(H264ProfileLevelId( config.h264_codec_settings.profile, H264Level::kLevel3_1))}, diff --git a/third_party/libwebrtc/modules/video_coding/fec_controller_default.cc b/third_party/libwebrtc/modules/video_coding/fec_controller_default.cc index f204b01c7c..d548d6580c 100644 --- a/third_party/libwebrtc/modules/video_coding/fec_controller_default.cc +++ b/third_party/libwebrtc/modules/video_coding/fec_controller_default.cc @@ -15,30 +15,28 @@ #include <algorithm> #include <string> +#include "api/environment/environment.h" +#include "api/field_trials_view.h" #include "modules/include/module_fec_types.h" #include "rtc_base/logging.h" -#include "system_wrappers/include/field_trial.h" +#include "system_wrappers/include/clock.h" namespace webrtc { const float kProtectionOverheadRateThreshold = 0.5; FecControllerDefault::FecControllerDefault( - Clock* clock, + const Environment& env, VCMProtectionCallback* protection_callback) - : clock_(clock), + : env_(env), protection_callback_(protection_callback), loss_prot_logic_(new media_optimization::VCMLossProtectionLogic( - clock_->TimeInMilliseconds())), + env_.clock().TimeInMilliseconds())), max_payload_size_(1460), overhead_threshold_(GetProtectionOverheadRateThreshold()) {} -FecControllerDefault::FecControllerDefault(Clock* clock) - : clock_(clock), - loss_prot_logic_(new media_optimization::VCMLossProtectionLogic( - clock_->TimeInMilliseconds())), - max_payload_size_(1460), - overhead_threshold_(GetProtectionOverheadRateThreshold()) {} +FecControllerDefault::FecControllerDefault(const Environment& env) + : FecControllerDefault(env, nullptr) {} FecControllerDefault::~FecControllerDefault(void) { loss_prot_logic_->Release(); @@ -61,8 +59,8 @@ void FecControllerDefault::SetEncodingData(size_t width, float FecControllerDefault::GetProtectionOverheadRateThreshold() { float overhead_threshold = - strtof(webrtc::field_trial::FindFullName( - "WebRTC-ProtectionOverheadRateThreshold") + strtof(env_.field_trials() + .Lookup("WebRTC-ProtectionOverheadRateThreshold") .c_str(), nullptr); if (overhead_threshold > 0 && overhead_threshold <= 1) { @@ -107,7 +105,7 @@ uint32_t FecControllerDefault::UpdateFecRates( media_optimization::FilterPacketLossMode filter_mode = media_optimization::kMaxFilter; uint8_t packet_loss_enc = loss_prot_logic_->FilteredLoss( - clock_->TimeInMilliseconds(), filter_mode, fraction_lost); + env_.clock().TimeInMilliseconds(), filter_mode, fraction_lost); // For now use the filtered loss for computing the robustness settings. loss_prot_logic_->UpdateFilteredLossPr(packet_loss_enc); if (loss_prot_logic_->SelectedType() == media_optimization::kNone) { @@ -191,11 +189,11 @@ void FecControllerDefault::UpdateWithEncodedData( const float min_packets_per_frame = encoded_length / static_cast<float>(max_payload_size_); if (delta_frame) { - loss_prot_logic_->UpdatePacketsPerFrame(min_packets_per_frame, - clock_->TimeInMilliseconds()); + loss_prot_logic_->UpdatePacketsPerFrame( + min_packets_per_frame, env_.clock().TimeInMilliseconds()); } else { loss_prot_logic_->UpdatePacketsPerFrameKey( - min_packets_per_frame, clock_->TimeInMilliseconds()); + min_packets_per_frame, env_.clock().TimeInMilliseconds()); } } if (!delta_frame && encoded_length > 0) { diff --git a/third_party/libwebrtc/modules/video_coding/fec_controller_default.h b/third_party/libwebrtc/modules/video_coding/fec_controller_default.h index a97dea011b..f60302b2d8 100644 --- a/third_party/libwebrtc/modules/video_coding/fec_controller_default.h +++ b/third_party/libwebrtc/modules/video_coding/fec_controller_default.h @@ -17,24 +17,25 @@ #include <memory> #include <vector> +#include "api/environment/environment.h" #include "api/fec_controller.h" #include "modules/video_coding/media_opt_util.h" #include "rtc_base/synchronization/mutex.h" #include "rtc_base/thread_annotations.h" -#include "system_wrappers/include/clock.h" namespace webrtc { class FecControllerDefault : public FecController { public: - FecControllerDefault(Clock* clock, + FecControllerDefault(const Environment& env, VCMProtectionCallback* protection_callback); - explicit FecControllerDefault(Clock* clock); - ~FecControllerDefault() override; + explicit FecControllerDefault(const Environment& env); FecControllerDefault(const FecControllerDefault&) = delete; FecControllerDefault& operator=(const FecControllerDefault&) = delete; + ~FecControllerDefault() override; + void SetProtectionCallback( VCMProtectionCallback* protection_callback) override; void SetProtectionMethod(bool enable_fec, bool enable_nack) override; @@ -54,7 +55,7 @@ class FecControllerDefault : public FecController { private: enum { kBitrateAverageWinMs = 1000 }; - Clock* const clock_; + const Environment env_; VCMProtectionCallback* protection_callback_; Mutex mutex_; std::unique_ptr<media_optimization::VCMLossProtectionLogic> loss_prot_logic_ diff --git a/third_party/libwebrtc/modules/video_coding/fec_controller_unittest.cc b/third_party/libwebrtc/modules/video_coding/fec_controller_unittest.cc index fa3cc7a93b..c4a0a08fd1 100644 --- a/third_party/libwebrtc/modules/video_coding/fec_controller_unittest.cc +++ b/third_party/libwebrtc/modules/video_coding/fec_controller_unittest.cc @@ -14,6 +14,7 @@ #include <vector> +#include "api/environment/environment_factory.h" #include "modules/include/module_fec_types.h" #include "modules/video_coding/fec_controller_default.h" #include "system_wrappers/include/clock.h" @@ -50,7 +51,8 @@ class ProtectionBitrateCalculatorTest : public ::testing::Test { // Note: simulated clock starts at 1 seconds, since parts of webrtc use 0 as // a special case (e.g. frame rate in media optimization). ProtectionBitrateCalculatorTest() - : clock_(1000), fec_controller_(&clock_, &protection_callback_) {} + : clock_(1000), + fec_controller_(CreateEnvironment(&clock_), &protection_callback_) {} SimulatedClock clock_; ProtectionCallback protection_callback_; diff --git a/third_party/libwebrtc/modules/video_coding/nack_requester.cc b/third_party/libwebrtc/modules/video_coding/nack_requester.cc index 008420f4da..b3e928d05e 100644 --- a/third_party/libwebrtc/modules/video_coding/nack_requester.cc +++ b/third_party/libwebrtc/modules/video_coding/nack_requester.cc @@ -141,13 +141,12 @@ void NackRequester::ProcessNacks() { } } -int NackRequester::OnReceivedPacket(uint16_t seq_num, bool is_keyframe) { +int NackRequester::OnReceivedPacket(uint16_t seq_num) { RTC_DCHECK_RUN_ON(worker_thread_); - return OnReceivedPacket(seq_num, is_keyframe, false); + return OnReceivedPacket(seq_num, false); } int NackRequester::OnReceivedPacket(uint16_t seq_num, - bool is_keyframe, bool is_recovered) { RTC_DCHECK_RUN_ON(worker_thread_); // TODO(philipel): When the packet includes information whether it is @@ -158,8 +157,6 @@ int NackRequester::OnReceivedPacket(uint16_t seq_num, if (!initialized_) { newest_seq_num_ = seq_num; - if (is_keyframe) - keyframe_list_.insert(seq_num); initialized_ = true; return 0; } @@ -182,15 +179,6 @@ int NackRequester::OnReceivedPacket(uint16_t seq_num, return nacks_sent_for_packet; } - // Keep track of new keyframes. - if (is_keyframe) - keyframe_list_.insert(seq_num); - - // And remove old ones so we don't accumulate keyframes. - auto it = keyframe_list_.lower_bound(seq_num - kMaxPacketAge); - if (it != keyframe_list_.begin()) - keyframe_list_.erase(keyframe_list_.begin(), it); - if (is_recovered) { recovered_list_.insert(seq_num); @@ -225,8 +213,6 @@ void NackRequester::ClearUpTo(uint16_t seq_num) { // thread. RTC_DCHECK_RUN_ON(worker_thread_); nack_list_.erase(nack_list_.begin(), nack_list_.lower_bound(seq_num)); - keyframe_list_.erase(keyframe_list_.begin(), - keyframe_list_.lower_bound(seq_num)); recovered_list_.erase(recovered_list_.begin(), recovered_list_.lower_bound(seq_num)); } @@ -236,25 +222,6 @@ void NackRequester::UpdateRtt(int64_t rtt_ms) { rtt_ = TimeDelta::Millis(rtt_ms); } -bool NackRequester::RemovePacketsUntilKeyFrame() { - // Called on worker_thread_. - while (!keyframe_list_.empty()) { - auto it = nack_list_.lower_bound(*keyframe_list_.begin()); - - if (it != nack_list_.begin()) { - // We have found a keyframe that actually is newer than at least one - // packet in the nack list. - nack_list_.erase(nack_list_.begin(), it); - return true; - } - - // If this keyframe is so old it does not remove any packets from the list, - // remove it from the list of keyframes and try the next keyframe. - keyframe_list_.erase(keyframe_list_.begin()); - } - return false; -} - void NackRequester::AddPacketsToNack(uint16_t seq_num_start, uint16_t seq_num_end) { // Called on worker_thread_. @@ -262,22 +229,13 @@ void NackRequester::AddPacketsToNack(uint16_t seq_num_start, auto it = nack_list_.lower_bound(seq_num_end - kMaxPacketAge); nack_list_.erase(nack_list_.begin(), it); - // If the nack list is too large, remove packets from the nack list until - // the latest first packet of a keyframe. If the list is still too large, - // clear it and request a keyframe. uint16_t num_new_nacks = ForwardDiff(seq_num_start, seq_num_end); if (nack_list_.size() + num_new_nacks > kMaxNackPackets) { - while (RemovePacketsUntilKeyFrame() && - nack_list_.size() + num_new_nacks > kMaxNackPackets) { - } - - if (nack_list_.size() + num_new_nacks > kMaxNackPackets) { - nack_list_.clear(); - RTC_LOG(LS_WARNING) << "NACK list full, clearing NACK" - " list and requesting keyframe."; - keyframe_request_sender_->RequestKeyFrame(); - return; - } + nack_list_.clear(); + RTC_LOG(LS_WARNING) << "NACK list full, clearing NACK" + " list and requesting keyframe."; + keyframe_request_sender_->RequestKeyFrame(); + return; } for (uint16_t seq_num = seq_num_start; seq_num != seq_num_end; ++seq_num) { diff --git a/third_party/libwebrtc/modules/video_coding/nack_requester.h b/third_party/libwebrtc/modules/video_coding/nack_requester.h index c860787dcf..b5ef30f01b 100644 --- a/third_party/libwebrtc/modules/video_coding/nack_requester.h +++ b/third_party/libwebrtc/modules/video_coding/nack_requester.h @@ -78,8 +78,8 @@ class NackRequester final : public NackRequesterBase { void ProcessNacks() override; - int OnReceivedPacket(uint16_t seq_num, bool is_keyframe); - int OnReceivedPacket(uint16_t seq_num, bool is_keyframe, bool is_recovered); + int OnReceivedPacket(uint16_t seq_num); + int OnReceivedPacket(uint16_t seq_num, bool is_recovered); void ClearUpTo(uint16_t seq_num); void UpdateRtt(int64_t rtt_ms); @@ -108,10 +108,6 @@ class NackRequester final : public NackRequesterBase { void AddPacketsToNack(uint16_t seq_num_start, uint16_t seq_num_end) RTC_EXCLUSIVE_LOCKS_REQUIRED(worker_thread_); - // Removes packets from the nack list until the next keyframe. Returns true - // if packets were removed. - bool RemovePacketsUntilKeyFrame() - RTC_EXCLUSIVE_LOCKS_REQUIRED(worker_thread_); std::vector<uint16_t> GetNackBatch(NackFilterOptions options) RTC_EXCLUSIVE_LOCKS_REQUIRED(worker_thread_); @@ -134,8 +130,6 @@ class NackRequester final : public NackRequesterBase { // synchronized access. std::map<uint16_t, NackInfo, DescendingSeqNumComp<uint16_t>> nack_list_ RTC_GUARDED_BY(worker_thread_); - std::set<uint16_t, DescendingSeqNumComp<uint16_t>> keyframe_list_ - RTC_GUARDED_BY(worker_thread_); std::set<uint16_t, DescendingSeqNumComp<uint16_t>> recovered_list_ RTC_GUARDED_BY(worker_thread_); video_coding::Histogram reordering_histogram_ RTC_GUARDED_BY(worker_thread_); diff --git a/third_party/libwebrtc/modules/video_coding/nack_requester_unittest.cc b/third_party/libwebrtc/modules/video_coding/nack_requester_unittest.cc index 6f11cb6e91..2f24df2aef 100644 --- a/third_party/libwebrtc/modules/video_coding/nack_requester_unittest.cc +++ b/third_party/libwebrtc/modules/video_coding/nack_requester_unittest.cc @@ -102,90 +102,25 @@ class TestNackRequester : public ::testing::Test, TEST_F(TestNackRequester, NackOnePacket) { NackRequester& nack_module = CreateNackModule(); - nack_module.OnReceivedPacket(1, false, false); - nack_module.OnReceivedPacket(3, false, false); + nack_module.OnReceivedPacket(1); + nack_module.OnReceivedPacket(3); ASSERT_EQ(1u, sent_nacks_.size()); EXPECT_EQ(2, sent_nacks_[0]); } TEST_F(TestNackRequester, WrappingSeqNum) { NackRequester& nack_module = CreateNackModule(); - nack_module.OnReceivedPacket(0xfffe, false, false); - nack_module.OnReceivedPacket(1, false, false); + nack_module.OnReceivedPacket(0xfffe); + nack_module.OnReceivedPacket(1); ASSERT_EQ(2u, sent_nacks_.size()); EXPECT_EQ(0xffff, sent_nacks_[0]); EXPECT_EQ(0, sent_nacks_[1]); } -TEST_F(TestNackRequester, WrappingSeqNumClearToKeyframe) { - NackRequester& nack_module = CreateNackModule(TimeDelta::Millis(10)); - nack_module.OnReceivedPacket(0xfffe, false, false); - nack_module.OnReceivedPacket(1, false, false); - ASSERT_EQ(2u, sent_nacks_.size()); - EXPECT_EQ(0xffff, sent_nacks_[0]); - EXPECT_EQ(0, sent_nacks_[1]); - - sent_nacks_.clear(); - nack_module.OnReceivedPacket(2, true, false); - ASSERT_EQ(0u, sent_nacks_.size()); - - nack_module.OnReceivedPacket(501, true, false); - ASSERT_EQ(498u, sent_nacks_.size()); - for (int seq_num = 3; seq_num < 501; ++seq_num) - EXPECT_EQ(seq_num, sent_nacks_[seq_num - 3]); - - sent_nacks_.clear(); - nack_module.OnReceivedPacket(1001, false, false); - EXPECT_EQ(499u, sent_nacks_.size()); - for (int seq_num = 502; seq_num < 1001; ++seq_num) - EXPECT_EQ(seq_num, sent_nacks_[seq_num - 502]); - - sent_nacks_.clear(); - clock_->AdvanceTimeMilliseconds(100); - ASSERT_TRUE(WaitForSendNack()); - ASSERT_EQ(999u, sent_nacks_.size()); - EXPECT_EQ(0xffff, sent_nacks_[0]); - EXPECT_EQ(0, sent_nacks_[1]); - for (int seq_num = 3; seq_num < 501; ++seq_num) - EXPECT_EQ(seq_num, sent_nacks_[seq_num - 1]); - for (int seq_num = 502; seq_num < 1001; ++seq_num) - EXPECT_EQ(seq_num, sent_nacks_[seq_num - 2]); - - // Adding packet 1004 will cause the nack list to reach it's max limit. - // It will then clear all nacks up to the next keyframe (seq num 2), - // thus removing 0xffff and 0 from the nack list. - sent_nacks_.clear(); - nack_module.OnReceivedPacket(1004, false, false); - ASSERT_EQ(2u, sent_nacks_.size()); - EXPECT_EQ(1002, sent_nacks_[0]); - EXPECT_EQ(1003, sent_nacks_[1]); - - sent_nacks_.clear(); - clock_->AdvanceTimeMilliseconds(100); - ASSERT_TRUE(WaitForSendNack()); - ASSERT_EQ(999u, sent_nacks_.size()); - for (int seq_num = 3; seq_num < 501; ++seq_num) - EXPECT_EQ(seq_num, sent_nacks_[seq_num - 3]); - for (int seq_num = 502; seq_num < 1001; ++seq_num) - EXPECT_EQ(seq_num, sent_nacks_[seq_num - 4]); - - // Adding packet 1007 will cause the nack module to overflow again, thus - // clearing everything up to 501 which is the next keyframe. - nack_module.OnReceivedPacket(1007, false, false); - sent_nacks_.clear(); - clock_->AdvanceTimeMilliseconds(100); - ASSERT_TRUE(WaitForSendNack()); - ASSERT_EQ(503u, sent_nacks_.size()); - for (int seq_num = 502; seq_num < 1001; ++seq_num) - EXPECT_EQ(seq_num, sent_nacks_[seq_num - 502]); - EXPECT_EQ(1005, sent_nacks_[501]); - EXPECT_EQ(1006, sent_nacks_[502]); -} - TEST_F(TestNackRequester, ResendNack) { NackRequester& nack_module = CreateNackModule(TimeDelta::Millis(1)); - nack_module.OnReceivedPacket(1, false, false); - nack_module.OnReceivedPacket(3, false, false); + nack_module.OnReceivedPacket(1); + nack_module.OnReceivedPacket(3); size_t expected_nacks_sent = 1; ASSERT_EQ(expected_nacks_sent, sent_nacks_.size()); EXPECT_EQ(2, sent_nacks_[0]); @@ -225,8 +160,8 @@ TEST_F(TestNackRequester, ResendNack) { TEST_F(TestNackRequester, ResendPacketMaxRetries) { NackRequester& nack_module = CreateNackModule(TimeDelta::Millis(1)); - nack_module.OnReceivedPacket(1, false, false); - nack_module.OnReceivedPacket(3, false, false); + nack_module.OnReceivedPacket(1); + nack_module.OnReceivedPacket(3); ASSERT_EQ(1u, sent_nacks_.size()); EXPECT_EQ(2, sent_nacks_[0]); @@ -246,37 +181,22 @@ TEST_F(TestNackRequester, ResendPacketMaxRetries) { TEST_F(TestNackRequester, TooLargeNackList) { NackRequester& nack_module = CreateNackModule(); - nack_module.OnReceivedPacket(0, false, false); - nack_module.OnReceivedPacket(1001, false, false); + nack_module.OnReceivedPacket(0); + nack_module.OnReceivedPacket(1001); EXPECT_EQ(1000u, sent_nacks_.size()); EXPECT_EQ(0, keyframes_requested_); - nack_module.OnReceivedPacket(1003, false, false); + nack_module.OnReceivedPacket(1003); EXPECT_EQ(1000u, sent_nacks_.size()); EXPECT_EQ(1, keyframes_requested_); - nack_module.OnReceivedPacket(1004, false, false); - EXPECT_EQ(1000u, sent_nacks_.size()); - EXPECT_EQ(1, keyframes_requested_); -} - -TEST_F(TestNackRequester, TooLargeNackListWithKeyFrame) { - NackRequester& nack_module = CreateNackModule(); - nack_module.OnReceivedPacket(0, false, false); - nack_module.OnReceivedPacket(1, true, false); - nack_module.OnReceivedPacket(1001, false, false); - EXPECT_EQ(999u, sent_nacks_.size()); - EXPECT_EQ(0, keyframes_requested_); - nack_module.OnReceivedPacket(1003, false, false); - EXPECT_EQ(1000u, sent_nacks_.size()); - EXPECT_EQ(0, keyframes_requested_); - nack_module.OnReceivedPacket(1005, false, false); + nack_module.OnReceivedPacket(1004); EXPECT_EQ(1000u, sent_nacks_.size()); EXPECT_EQ(1, keyframes_requested_); } TEST_F(TestNackRequester, ClearUpTo) { NackRequester& nack_module = CreateNackModule(TimeDelta::Millis(1)); - nack_module.OnReceivedPacket(0, false, false); - nack_module.OnReceivedPacket(100, false, false); + nack_module.OnReceivedPacket(0); + nack_module.OnReceivedPacket(100); EXPECT_EQ(99u, sent_nacks_.size()); sent_nacks_.clear(); @@ -289,8 +209,8 @@ TEST_F(TestNackRequester, ClearUpTo) { TEST_F(TestNackRequester, ClearUpToWrap) { NackRequester& nack_module = CreateNackModule(); - nack_module.OnReceivedPacket(0xfff0, false, false); - nack_module.OnReceivedPacket(0xf, false, false); + nack_module.OnReceivedPacket(0xfff0); + nack_module.OnReceivedPacket(0xf); EXPECT_EQ(30u, sent_nacks_.size()); sent_nacks_.clear(); @@ -303,13 +223,13 @@ TEST_F(TestNackRequester, ClearUpToWrap) { TEST_F(TestNackRequester, PacketNackCount) { NackRequester& nack_module = CreateNackModule(TimeDelta::Millis(1)); - EXPECT_EQ(0, nack_module.OnReceivedPacket(0, false, false)); - EXPECT_EQ(0, nack_module.OnReceivedPacket(2, false, false)); - EXPECT_EQ(1, nack_module.OnReceivedPacket(1, false, false)); + EXPECT_EQ(0, nack_module.OnReceivedPacket(0)); + EXPECT_EQ(0, nack_module.OnReceivedPacket(2)); + EXPECT_EQ(1, nack_module.OnReceivedPacket(1)); sent_nacks_.clear(); nack_module.UpdateRtt(100); - EXPECT_EQ(0, nack_module.OnReceivedPacket(5, false, false)); + EXPECT_EQ(0, nack_module.OnReceivedPacket(5)); clock_->AdvanceTimeMilliseconds(100); WaitForSendNack(); EXPECT_EQ(4u, sent_nacks_.size()); @@ -319,40 +239,24 @@ TEST_F(TestNackRequester, PacketNackCount) { EXPECT_EQ(6u, sent_nacks_.size()); - EXPECT_EQ(3, nack_module.OnReceivedPacket(3, false, false)); - EXPECT_EQ(3, nack_module.OnReceivedPacket(4, false, false)); - EXPECT_EQ(0, nack_module.OnReceivedPacket(4, false, false)); -} - -TEST_F(TestNackRequester, NackListFullAndNoOverlapWithKeyframes) { - NackRequester& nack_module = CreateNackModule(); - const int kMaxNackPackets = 1000; - const unsigned int kFirstGap = kMaxNackPackets - 20; - const unsigned int kSecondGap = 200; - uint16_t seq_num = 0; - nack_module.OnReceivedPacket(seq_num++, true, false); - seq_num += kFirstGap; - nack_module.OnReceivedPacket(seq_num++, true, false); - EXPECT_EQ(kFirstGap, sent_nacks_.size()); - sent_nacks_.clear(); - seq_num += kSecondGap; - nack_module.OnReceivedPacket(seq_num, true, false); - EXPECT_EQ(kSecondGap, sent_nacks_.size()); + EXPECT_EQ(3, nack_module.OnReceivedPacket(3)); + EXPECT_EQ(3, nack_module.OnReceivedPacket(4)); + EXPECT_EQ(0, nack_module.OnReceivedPacket(4)); } TEST_F(TestNackRequester, HandleFecRecoveredPacket) { NackRequester& nack_module = CreateNackModule(); - nack_module.OnReceivedPacket(1, false, false); - nack_module.OnReceivedPacket(4, false, true); + nack_module.OnReceivedPacket(1); + nack_module.OnReceivedPacket(4, /*is_recovered=*/true); EXPECT_EQ(0u, sent_nacks_.size()); - nack_module.OnReceivedPacket(5, false, false); + nack_module.OnReceivedPacket(5); EXPECT_EQ(2u, sent_nacks_.size()); } TEST_F(TestNackRequester, SendNackWithoutDelay) { NackRequester& nack_module = CreateNackModule(); - nack_module.OnReceivedPacket(0, false, false); - nack_module.OnReceivedPacket(100, false, false); + nack_module.OnReceivedPacket(0); + nack_module.OnReceivedPacket(100); EXPECT_EQ(99u, sent_nacks_.size()); } @@ -389,14 +293,14 @@ class TestNackRequesterWithFieldTrial : public ::testing::Test, }; TEST_F(TestNackRequesterWithFieldTrial, SendNackWithDelay) { - nack_module_.OnReceivedPacket(0, false, false); - nack_module_.OnReceivedPacket(100, false, false); + nack_module_.OnReceivedPacket(0); + nack_module_.OnReceivedPacket(100); EXPECT_EQ(0u, sent_nacks_.size()); clock_->AdvanceTimeMilliseconds(10); - nack_module_.OnReceivedPacket(106, false, false); + nack_module_.OnReceivedPacket(106); EXPECT_EQ(99u, sent_nacks_.size()); clock_->AdvanceTimeMilliseconds(10); - nack_module_.OnReceivedPacket(109, false, false); + nack_module_.OnReceivedPacket(109); EXPECT_EQ(104u, sent_nacks_.size()); } } // namespace webrtc diff --git a/third_party/libwebrtc/modules/video_coding/utility/qp_parser.cc b/third_party/libwebrtc/modules/video_coding/utility/qp_parser.cc index 3b9aaa377e..a531b54a7e 100644 --- a/third_party/libwebrtc/modules/video_coding/utility/qp_parser.cc +++ b/third_party/libwebrtc/modules/video_coding/utility/qp_parser.cc @@ -37,7 +37,10 @@ absl::optional<uint32_t> QpParser::Parse(VideoCodecType codec_type, } else if (codec_type == kVideoCodecH264) { return h264_parsers_[spatial_idx].Parse(frame_data, frame_size); } else if (codec_type == kVideoCodecH265) { - // TODO(bugs.webrtc.org/13485) + // H.265 bitstream parser is conditionally built. +#ifdef RTC_ENABLE_H265 + return h265_parsers_[spatial_idx].Parse(frame_data, frame_size); +#endif } return absl::nullopt; @@ -52,4 +55,15 @@ absl::optional<uint32_t> QpParser::H264QpParser::Parse( return bitstream_parser_.GetLastSliceQp(); } +#ifdef RTC_ENABLE_H265 +absl::optional<uint32_t> QpParser::H265QpParser::Parse( + const uint8_t* frame_data, + size_t frame_size) { + MutexLock lock(&mutex_); + bitstream_parser_.ParseBitstream( + rtc::ArrayView<const uint8_t>(frame_data, frame_size)); + return bitstream_parser_.GetLastSliceQp(); +} +#endif + } // namespace webrtc diff --git a/third_party/libwebrtc/modules/video_coding/utility/qp_parser.h b/third_party/libwebrtc/modules/video_coding/utility/qp_parser.h index f132ff9337..210fe02bc3 100644 --- a/third_party/libwebrtc/modules/video_coding/utility/qp_parser.h +++ b/third_party/libwebrtc/modules/video_coding/utility/qp_parser.h @@ -15,6 +15,9 @@ #include "api/video/video_codec_constants.h" #include "api/video/video_codec_type.h" #include "common_video/h264/h264_bitstream_parser.h" +#ifdef RTC_ENABLE_H265 +#include "common_video/h265/h265_bitstream_parser.h" +#endif #include "rtc_base/synchronization/mutex.h" namespace webrtc { @@ -38,6 +41,21 @@ class QpParser { }; H264QpParser h264_parsers_[kMaxSimulcastStreams]; + +#ifdef RTC_ENABLE_H265 + // A thread safe wrapper for H.265 bitstream parser. + class H265QpParser { + public: + absl::optional<uint32_t> Parse(const uint8_t* frame_data, + size_t frame_size); + + private: + Mutex mutex_; + H265BitstreamParser bitstream_parser_ RTC_GUARDED_BY(mutex_); + }; + + H265QpParser h265_parsers_[kMaxSimulcastStreams]; +#endif }; } // namespace webrtc |