diff --git a/webrtc/test/fake_encoder.cc b/webrtc/test/fake_encoder.cc index ac7144079b..1db93eb40e 100644 --- a/webrtc/test/fake_encoder.cc +++ b/webrtc/test/fake_encoder.cc @@ -15,7 +15,6 @@ #include #include -#include "webrtc/base/atomicops.h" #include "webrtc/base/checks.h" #include "webrtc/common_types.h" #include "webrtc/modules/video_coding/include/video_codec_interface.h" @@ -36,8 +35,6 @@ FakeEncoder::FakeEncoder(Clock* clock) } } -FakeEncoder::~FakeEncoder() {} - void FakeEncoder::SetMaxBitrate(int max_kbps) { RTC_DCHECK_GE(max_kbps, -1); // max_kbps == -1 disables it. rtc::CritScope cs(&crit_sect_); @@ -254,33 +251,47 @@ EncodedImageCallback::Result FakeH264Encoder::OnEncodedImage( } DelayedEncoder::DelayedEncoder(Clock* clock, int delay_ms) - : test::FakeEncoder(clock), - delay_ms_(delay_ms) {} + : test::FakeEncoder(clock), delay_ms_(delay_ms) { + // The encoder could be created on a different thread than + // it is being used on. + sequence_checker_.Detach(); +} void DelayedEncoder::SetDelay(int delay_ms) { - rtc::CritScope cs(&local_crit_sect_); + RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_); delay_ms_ = delay_ms; } int32_t DelayedEncoder::Encode(const VideoFrame& input_image, const CodecSpecificInfo* codec_specific_info, const std::vector* frame_types) { - int delay_ms = 0; - { - rtc::CritScope cs(&local_crit_sect_); - delay_ms = delay_ms_; - } - SleepMs(delay_ms); + RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_); + + SleepMs(delay_ms_); + return FakeEncoder::Encode(input_image, codec_specific_info, frame_types); } MultithreadedFakeH264Encoder::MultithreadedFakeH264Encoder(Clock* clock) : test::FakeH264Encoder(clock), current_queue_(0), - queue1_("Queue 1"), - queue2_("Queue 2") {} + queue1_(nullptr), + queue2_(nullptr) { + // The encoder could be created on a different thread than + // it is being used on. + sequence_checker_.Detach(); +} -MultithreadedFakeH264Encoder::~MultithreadedFakeH264Encoder() = default; +int32_t MultithreadedFakeH264Encoder::InitEncode(const VideoCodec* config, + int32_t number_of_cores, + size_t max_payload_size) { + RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_); + + queue1_.reset(new rtc::TaskQueue("Queue 1")); + queue2_.reset(new rtc::TaskQueue("Queue 2")); + + return FakeH264Encoder::InitEncode(config, number_of_cores, max_payload_size); +} class MultithreadedFakeH264Encoder::EncodeTask : public rtc::QueuedTask { public: @@ -313,13 +324,19 @@ int32_t MultithreadedFakeH264Encoder::Encode( const VideoFrame& input_image, const CodecSpecificInfo* codec_specific_info, const std::vector* frame_types) { - int current_queue = rtc::AtomicOps::Increment(¤t_queue_); - rtc::TaskQueue& queue = (current_queue % 2 == 0) ? queue1_ : queue2_; + RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_); - queue.PostTask(std::unique_ptr( + std::unique_ptr& queue = + (current_queue_++ % 2 == 0) ? queue1_ : queue2_; + + if (!queue) { + return WEBRTC_VIDEO_CODEC_UNINITIALIZED; + } + + queue->PostTask(std::unique_ptr( new EncodeTask(this, input_image, codec_specific_info, frame_types))); - return 0; + return WEBRTC_VIDEO_CODEC_OK; } int32_t MultithreadedFakeH264Encoder::EncodeCallback( @@ -329,5 +346,14 @@ int32_t MultithreadedFakeH264Encoder::EncodeCallback( return FakeH264Encoder::Encode(input_image, codec_specific_info, frame_types); } +int32_t MultithreadedFakeH264Encoder::Release() { + RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_); + + queue1_.reset(); + queue2_.reset(); + + return FakeH264Encoder::Release(); +} + } // namespace test } // namespace webrtc diff --git a/webrtc/test/fake_encoder.h b/webrtc/test/fake_encoder.h index 39c3e3e67f..c07fbb36e1 100644 --- a/webrtc/test/fake_encoder.h +++ b/webrtc/test/fake_encoder.h @@ -12,8 +12,10 @@ #define WEBRTC_TEST_FAKE_ENCODER_H_ #include +#include #include "webrtc/base/criticalsection.h" +#include "webrtc/base/sequenced_task_checker.h" #include "webrtc/base/task_queue.h" #include "webrtc/common_types.h" #include "webrtc/system_wrappers/include/clock.h" @@ -25,7 +27,7 @@ namespace test { class FakeEncoder : public VideoEncoder { public: explicit FakeEncoder(Clock* clock); - virtual ~FakeEncoder(); + virtual ~FakeEncoder() = default; // Sets max bitrate. Not thread-safe, call before registering the encoder. void SetMaxBitrate(int max_kbps); @@ -47,20 +49,21 @@ class FakeEncoder : public VideoEncoder { static const char* kImplementationName; protected: - rtc::CriticalSection crit_sect_; Clock* const clock_; VideoCodec config_ GUARDED_BY(crit_sect_); EncodedImageCallback* callback_ GUARDED_BY(crit_sect_); BitrateAllocation target_bitrate_ GUARDED_BY(crit_sect_); int max_target_bitrate_kbps_ GUARDED_BY(crit_sect_); int64_t last_encode_time_ms_ GUARDED_BY(crit_sect_); + rtc::CriticalSection crit_sect_; + uint8_t encoded_buffer_[100000]; }; class FakeH264Encoder : public FakeEncoder, public EncodedImageCallback { public: explicit FakeH264Encoder(Clock* clock); - virtual ~FakeH264Encoder() {} + virtual ~FakeH264Encoder() = default; int32_t RegisterEncodeCompleteCallback( EncodedImageCallback* callback) override; @@ -70,15 +73,15 @@ class FakeH264Encoder : public FakeEncoder, public EncodedImageCallback { const RTPFragmentationHeader* fragments) override; private: - rtc::CriticalSection local_crit_sect_; EncodedImageCallback* callback_ GUARDED_BY(local_crit_sect_); int idr_counter_ GUARDED_BY(local_crit_sect_); + rtc::CriticalSection local_crit_sect_; }; class DelayedEncoder : public test::FakeEncoder { public: DelayedEncoder(Clock* clock, int delay_ms); - virtual ~DelayedEncoder() {} + virtual ~DelayedEncoder() = default; void SetDelay(int delay_ms); int32_t Encode(const VideoFrame& input_image, @@ -86,17 +89,22 @@ class DelayedEncoder : public test::FakeEncoder { const std::vector* frame_types) override; private: - rtc::CriticalSection local_crit_sect_; - int delay_ms_ GUARDED_BY(&local_crit_sect_); + int delay_ms_ ACCESS_ON(sequence_checker_); + rtc::SequencedTaskChecker sequence_checker_; }; // This class implements a multi-threaded fake encoder by posting // FakeH264Encoder::Encode(.) tasks to |queue1_| and |queue2_|, in an -// alternating fashion. +// alternating fashion. The class itself does not need to be thread safe, +// as it is called from the task queue in ViEEncoder. class MultithreadedFakeH264Encoder : public test::FakeH264Encoder { public: explicit MultithreadedFakeH264Encoder(Clock* clock); - virtual ~MultithreadedFakeH264Encoder() override; + virtual ~MultithreadedFakeH264Encoder() = default; + + int32_t InitEncode(const VideoCodec* config, + int32_t number_of_cores, + size_t max_payload_size) override; int32_t Encode(const VideoFrame& input_image, const CodecSpecificInfo* codec_specific_info, @@ -106,12 +114,15 @@ class MultithreadedFakeH264Encoder : public test::FakeH264Encoder { const CodecSpecificInfo* codec_specific_info, const std::vector* frame_types); + int32_t Release() override; + protected: class EncodeTask; - int current_queue_; - rtc::TaskQueue queue1_; - rtc::TaskQueue queue2_; + int current_queue_ ACCESS_ON(sequence_checker_); + std::unique_ptr queue1_ ACCESS_ON(sequence_checker_); + std::unique_ptr queue2_ ACCESS_ON(sequence_checker_); + rtc::SequencedTaskChecker sequence_checker_; }; } // namespace test