diff --git a/test/testsupport/ivf_video_frame_generator.cc b/test/testsupport/ivf_video_frame_generator.cc index 47edfaa357..9fb057f1c9 100644 --- a/test/testsupport/ivf_video_frame_generator.cc +++ b/test/testsupport/ivf_video_frame_generator.cc @@ -45,10 +45,9 @@ IvfVideoFrameGenerator::IvfVideoFrameGenerator(const std::string& file_name) RTC_CHECK_EQ( video_decoder_->InitDecode(&codec_settings, /*number_of_cores=*/1), WEBRTC_VIDEO_CODEC_OK); - sequence_checker_.Detach(); } IvfVideoFrameGenerator::~IvfVideoFrameGenerator() { - RTC_DCHECK_RUN_ON(&sequence_checker_); + rtc::CritScope crit(&lock_); if (!file_reader_) { return; } @@ -57,7 +56,7 @@ IvfVideoFrameGenerator::~IvfVideoFrameGenerator() { // Reset decoder to prevent it from async access to |this|. video_decoder_.reset(); { - rtc::CritScope crit(&lock_); + rtc::CritScope frame_crit(&frame_decode_lock_); next_frame_ = absl::nullopt; // Set event in case another thread is waiting on it. next_frame_decoded_.Set(); @@ -65,7 +64,7 @@ IvfVideoFrameGenerator::~IvfVideoFrameGenerator() { } FrameGeneratorInterface::VideoFrameData IvfVideoFrameGenerator::NextFrame() { - RTC_DCHECK_RUN_ON(&sequence_checker_); + rtc::CritScope crit(&lock_); next_frame_decoded_.Reset(); RTC_CHECK(file_reader_); if (!file_reader_->HasMoreFrames()) { @@ -81,7 +80,7 @@ FrameGeneratorInterface::VideoFrameData IvfVideoFrameGenerator::NextFrame() { RTC_CHECK(decoded) << "Failed to decode next frame in " << kMaxNextFrameWaitTemeoutMs << "ms. Can't continue"; - rtc::CritScope crit(&lock_); + rtc::CritScope frame_crit(&frame_decode_lock_); rtc::scoped_refptr buffer = next_frame_->video_frame_buffer(); if (width_ != static_cast(buffer->width()) || @@ -97,7 +96,7 @@ FrameGeneratorInterface::VideoFrameData IvfVideoFrameGenerator::NextFrame() { } void IvfVideoFrameGenerator::ChangeResolution(size_t width, size_t height) { - RTC_DCHECK_RUN_ON(&sequence_checker_); + rtc::CritScope crit(&lock_); width_ = width; height_ = height; } @@ -121,7 +120,7 @@ void IvfVideoFrameGenerator::DecodedCallback::Decoded( } void IvfVideoFrameGenerator::OnFrameDecoded(const VideoFrame& decoded_frame) { - rtc::CritScope crit(&lock_); + rtc::CritScope crit(&frame_decode_lock_); next_frame_ = decoded_frame; next_frame_decoded_.Set(); } diff --git a/test/testsupport/ivf_video_frame_generator.h b/test/testsupport/ivf_video_frame_generator.h index e193a039c8..913d882766 100644 --- a/test/testsupport/ivf_video_frame_generator.h +++ b/test/testsupport/ivf_video_frame_generator.h @@ -63,11 +63,22 @@ class IvfVideoFrameGenerator : public FrameGeneratorInterface { size_t width_; size_t height_; - rtc::Event next_frame_decoded_; - SequenceChecker sequence_checker_; - + // This lock is used to ensure that all API method will be called + // sequentially. It is required because we need to ensure that generator + // won't be destroyed while it is reading the next frame on another thread, + // because it will cause SIGSEGV when decoder callback will be invoked. + // + // FrameGenerator is injected into PeerConnection via some scoped_ref object + // and it can happen that the last pointer will be destroyed on the different + // thread comparing to the one from which frames were read. rtc::CriticalSection lock_; - absl::optional next_frame_ RTC_GUARDED_BY(lock_); + // This lock is used to sync between sending and receiving frame from decoder. + // We can't reuse |lock_| because then generator can be destroyed between + // frame was sent to decoder and decoder callback was invoked. + rtc::CriticalSection frame_decode_lock_; + + rtc::Event next_frame_decoded_; + absl::optional next_frame_ RTC_GUARDED_BY(frame_decode_lock_); }; } // namespace test