Change FakePeriodicVideoCapturer to use a TaskQueue instead of Thread.
This changes callbacks to OnFrame methods to occur on a task queue which is in line with how it's called in production. The change is essentially around inheriting from FakeVideoCapturerWithTaskQueue instead of FakeVideoCapturer, but also removes the dependency on rtc::MessageHandler. Along the way I'm also updating an ortc test that uses FakePeriodicVideoCapturer and had a bug that was masked by the fact that FakePeriodicVideoCapturer previously used rtc::Thread::Current internally, but was being called by the wrong thread (and there were no checks for it). As a result, I'm also adding a bunch of checks to help with correct usage. Bug: webrtc:8841, webrtc:8848 Change-Id: I21b710873b508ebc55f8d2e4545d862766656871 Reviewed-on: https://webrtc-review.googlesource.com/49400 Commit-Queue: Tommi <tommi@webrtc.org> Reviewed-by: Taylor Brandstetter <deadbeef@webrtc.org> Cr-Commit-Position: refs/heads/master@{#21951}
This commit is contained in:
parent
7ff6ca5844
commit
8b0ebb9484
@ -77,6 +77,7 @@ class OrtcFactoryIntegrationTest : public testing::Test {
|
||||
// Sockets are bound to the ANY address, so this is needed to tell the
|
||||
// virtual network which address to use in this case.
|
||||
virtual_socket_server_.SetDefaultRoute(kIPv4LocalHostAddress);
|
||||
network_thread_.SetName("TestNetworkThread", this);
|
||||
network_thread_.Start();
|
||||
// Need to create after network thread is started.
|
||||
ortc_factory1_ =
|
||||
@ -220,7 +221,7 @@ class OrtcFactoryIntegrationTest : public testing::Test {
|
||||
rtc::scoped_refptr<webrtc::VideoTrackInterface>
|
||||
CreateLocalVideoTrackAndFakeCapturer(const std::string& id,
|
||||
OrtcFactoryInterface* ortc_factory) {
|
||||
cricket::FakeVideoCapturer* fake_capturer =
|
||||
webrtc::FakePeriodicVideoCapturer* fake_capturer =
|
||||
new webrtc::FakePeriodicVideoCapturer();
|
||||
fake_video_capturers_.push_back(fake_capturer);
|
||||
rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> source =
|
||||
@ -350,7 +351,7 @@ class OrtcFactoryIntegrationTest : public testing::Test {
|
||||
std::unique_ptr<OrtcFactoryInterface> ortc_factory1_;
|
||||
std::unique_ptr<OrtcFactoryInterface> ortc_factory2_;
|
||||
// Actually owned by video tracks.
|
||||
std::vector<cricket::FakeVideoCapturer*> fake_video_capturers_;
|
||||
std::vector<webrtc::FakePeriodicVideoCapturer*> fake_video_capturers_;
|
||||
int received_audio_frames1_ = 0;
|
||||
int received_audio_frames2_ = 0;
|
||||
int rendered_video_frames1_ = 0;
|
||||
@ -462,7 +463,7 @@ TEST_F(OrtcFactoryIntegrationTest, SetTrackWhileSending) {
|
||||
// Stop the old capturer, set a new track, and verify new frames are received
|
||||
// from the new track. Stopping the old capturer ensures that we aren't
|
||||
// actually still getting frames from it.
|
||||
fake_video_capturers_[0]->Stop();
|
||||
fake_video_capturers_[0]->StopFrameDelivery();
|
||||
int prev_num_frames = fake_renderer.num_rendered_frames();
|
||||
error = sender->SetTrack(
|
||||
CreateLocalVideoTrackAndFakeCapturer("video_2", ortc_factory1_.get()));
|
||||
|
||||
@ -368,6 +368,7 @@ if (rtc_include_tests) {
|
||||
"../rtc_base:rtc_base",
|
||||
"../rtc_base:rtc_base_approved",
|
||||
"../rtc_base:rtc_base_tests_utils",
|
||||
"../rtc_base:rtc_task_queue_api",
|
||||
"../test:test_support",
|
||||
]
|
||||
|
||||
|
||||
@ -14,59 +14,83 @@
|
||||
#ifndef PC_TEST_FAKEPERIODICVIDEOCAPTURER_H_
|
||||
#define PC_TEST_FAKEPERIODICVIDEOCAPTURER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "media/base/fakevideocapturer.h"
|
||||
#include "rtc_base/thread.h"
|
||||
#include "rtc_base/arraysize.h"
|
||||
#include "rtc_base/thread_checker.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class FakePeriodicVideoCapturer : public cricket::FakeVideoCapturer,
|
||||
public rtc::MessageHandler {
|
||||
class FakePeriodicVideoCapturer
|
||||
: public cricket::FakeVideoCapturerWithTaskQueue {
|
||||
public:
|
||||
FakePeriodicVideoCapturer() {
|
||||
std::vector<cricket::VideoFormat> formats;
|
||||
formats.push_back(cricket::VideoFormat(1280, 720,
|
||||
cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
|
||||
formats.push_back(cricket::VideoFormat(640, 480,
|
||||
cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
|
||||
formats.push_back(cricket::VideoFormat(640, 360,
|
||||
cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
|
||||
formats.push_back(cricket::VideoFormat(320, 240,
|
||||
cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
|
||||
formats.push_back(cricket::VideoFormat(160, 120,
|
||||
cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
|
||||
ResetSupportedFormats(formats);
|
||||
worker_thread_checker_.DetachFromThread();
|
||||
using cricket::VideoFormat;
|
||||
static const VideoFormat formats[] = {
|
||||
{1280, 720, VideoFormat::FpsToInterval(30), cricket::FOURCC_I420},
|
||||
{640, 480, VideoFormat::FpsToInterval(30), cricket::FOURCC_I420},
|
||||
{640, 360, VideoFormat::FpsToInterval(30), cricket::FOURCC_I420},
|
||||
{320, 240, VideoFormat::FpsToInterval(30), cricket::FOURCC_I420},
|
||||
{160, 120, VideoFormat::FpsToInterval(30), cricket::FOURCC_I420},
|
||||
};
|
||||
|
||||
ResetSupportedFormats({&formats[0], &formats[arraysize(formats)]});
|
||||
}
|
||||
|
||||
virtual cricket::CaptureState Start(const cricket::VideoFormat& format) {
|
||||
cricket::CaptureState state = FakeVideoCapturer::Start(format);
|
||||
if (state != cricket::CS_FAILED) {
|
||||
rtc::Thread::Current()->Post(RTC_FROM_HERE, this, MSG_CREATEFRAME);
|
||||
}
|
||||
return state;
|
||||
~FakePeriodicVideoCapturer() override {
|
||||
RTC_DCHECK(main_thread_checker_.CalledOnValidThread());
|
||||
}
|
||||
virtual void Stop() {
|
||||
rtc::Thread::Current()->Clear(this);
|
||||
}
|
||||
// Inherited from MesageHandler.
|
||||
virtual void OnMessage(rtc::Message* msg) {
|
||||
if (msg->message_id == MSG_CREATEFRAME) {
|
||||
if (IsRunning()) {
|
||||
CaptureFrame();
|
||||
rtc::Thread::Current()->PostDelayed(
|
||||
RTC_FROM_HERE, static_cast<int>(GetCaptureFormat()->interval /
|
||||
rtc::kNumNanosecsPerMillisec),
|
||||
this, MSG_CREATEFRAME);
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround method for tests to allow stopping frame delivery directly.
|
||||
// The |Start()| method expects to be called from the "worker thread" that
|
||||
// is owned by the factory (think OrtcFactoryInterface or
|
||||
// PeerConnectionFactoryInterface). That thread is not directly exposed,
|
||||
// which can make it tricky for tests to inject calls on.
|
||||
// So, in order to allow tests to stop frame delivery directly from the
|
||||
// test thread, we expose this method publicly.
|
||||
void StopFrameDelivery() {
|
||||
RunSynchronouslyOnTaskQueue([this]() {
|
||||
RTC_DCHECK_RUN_ON(&task_queue_);
|
||||
deliver_frames_ = false;
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
enum {
|
||||
// Offset 0xFF to make sure this don't collide with base class messages.
|
||||
MSG_CREATEFRAME = 0xFF
|
||||
};
|
||||
cricket::CaptureState Start(const cricket::VideoFormat& format) override {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
cricket::CaptureState state = FakeVideoCapturer::Start(format);
|
||||
if (state != cricket::CS_FAILED) {
|
||||
task_queue_.PostTask([this]() {
|
||||
RTC_DCHECK_RUN_ON(&task_queue_);
|
||||
deliver_frames_ = true;
|
||||
DeliverFrame();
|
||||
});
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
void Stop() override {
|
||||
RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
||||
StopFrameDelivery();
|
||||
}
|
||||
|
||||
void DeliverFrame() {
|
||||
RTC_DCHECK_RUN_ON(&task_queue_);
|
||||
if (IsRunning() && deliver_frames_) {
|
||||
CaptureFrame();
|
||||
task_queue_.PostDelayedTask(
|
||||
[this]() { DeliverFrame(); },
|
||||
static_cast<int>(GetCaptureFormat()->interval /
|
||||
rtc::kNumNanosecsPerMillisec));
|
||||
}
|
||||
}
|
||||
|
||||
rtc::ThreadChecker main_thread_checker_;
|
||||
rtc::ThreadChecker worker_thread_checker_;
|
||||
bool deliver_frames_ RTC_GUARDED_BY(task_queue_) = false;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user