Do not encode frames in MultithreadedFakeH264Encoder after Release().

Other minor changes:
- Define locks after stuff it is protecting
- Use explicit default dtors
- Replace unnecessary lock in DelayedEncoder with SequencedTaskChecker

BUG=webrtc:7130

Review-Url: https://codereview.webrtc.org/2686103002
Cr-Commit-Position: refs/heads/master@{#16554}
This commit is contained in:
brandtr 2017-02-11 00:25:18 -08:00 committed by Commit bot
parent 6607d84b44
commit 49ce67c992
2 changed files with 68 additions and 31 deletions

View File

@ -15,7 +15,6 @@
#include <algorithm>
#include <memory>
#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<FrameType>* 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<FrameType>* frame_types) {
int current_queue = rtc::AtomicOps::Increment(&current_queue_);
rtc::TaskQueue& queue = (current_queue % 2 == 0) ? queue1_ : queue2_;
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
queue.PostTask(std::unique_ptr<rtc::QueuedTask>(
std::unique_ptr<rtc::TaskQueue>& queue =
(current_queue_++ % 2 == 0) ? queue1_ : queue2_;
if (!queue) {
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
}
queue->PostTask(std::unique_ptr<rtc::QueuedTask>(
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

View File

@ -12,8 +12,10 @@
#define WEBRTC_TEST_FAKE_ENCODER_H_
#include <vector>
#include <memory>
#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<FrameType>* 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<FrameType>* 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<rtc::TaskQueue> queue1_ ACCESS_ON(sequence_checker_);
std::unique_ptr<rtc::TaskQueue> queue2_ ACCESS_ON(sequence_checker_);
rtc::SequencedTaskChecker sequence_checker_;
};
} // namespace test