Added fake camera, rewrote one test to use it.

Wrote a "file capture device" which is a kind of fake capture device. It reads a YUV file from disk and pretends that it is what the "camera" is seeing. This makes is possible to run tests based on video input without having an actual physical camera. This is good because physical cameras are quite unreliable.

Rewrote the standard mirrored preview loopback test so it can use the new file capture device. The old "classic" test is preserved. I tried to minimize duplication between the classic test case and the new one, which turned out to be quite painful.

There are some rough edges left in in the code. Suggested improvements is to get rid of the error counting mechanism since the code seems to assume that TestError invocations cause hard asserts anyway. The code will segfault for certain errors if the hard asserts doesn't happen, which means the error counting mechanism is unnecessary. This, by the way, could be a problem for the new test since it doesn't cause hard asserts.

Fixed comments for the thread wrapper and the external capture device interface.

BUG=
TEST=

Review URL: http://webrtc-codereview.appspot.com/224003

git-svn-id: http://webrtc.googlecode.com/svn/trunk@801 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
phoglund@webrtc.org
2011-10-24 13:20:09 +00:00
parent bf478faebb
commit c63f788e0f
11 changed files with 884 additions and 513 deletions

View File

@ -21,7 +21,9 @@ namespace webrtc {
// function.
#define ThreadObj void*
// Callback function that the spawned thread will enter once spawned
// Callback function that the spawned thread will enter once spawned.
// A return value of false is interpreted as that the function has no
// more work to do and that the thread can be released.
typedef bool(*ThreadRunFunction)(ThreadObj);
enum ThreadPriority

View File

@ -98,9 +98,12 @@ struct ViEVideoFrameI420
unsigned short height;
};
// This class declares an abstract interface to be used when using an external
// capture device. The user implemented derived class is registered using
// AllocateExternalCaptureDevice and is released using ReleaseCaptureDevice.
// This class declares an abstract interface to be used when implementing
// a user-defined capture device. This interface is not meant to be
// implemented by the user. Instead, the user should call AllocateCaptureDevice
// in the ViECapture interface, which will create a suitable implementation.
// The user should then call IncomingFrame in this interface to deliver
// captured frames to the system.
class WEBRTC_DLLEXPORT ViEExternalCapture
{
public:

View File

@ -13,7 +13,6 @@
*/
#include "gtest/gtest.h"
#include "vie_integration_test_base.h"
#include "vie_autotest.h"
@ -57,4 +56,5 @@ TEST_F(ViEApiIntegrationTest, RunsRenderTestWithoutErrors) {
TEST_F(ViEApiIntegrationTest, RunsRtpRtcpTestWithoutErrors) {
ASSERT_EQ(0, tests_->ViERtpRtcpAPITest());
}
}
} // namespace

View File

@ -13,7 +13,6 @@
*/
#include "gtest/gtest.h"
#include "vie_integration_test_base.h"
#include "vie_autotest.h"
@ -57,4 +56,5 @@ TEST_F(ViEExtendedIntegrationTest, RunsRenderTestWithoutErrors) {
TEST_F(ViEExtendedIntegrationTest, RunsRtpRtcpTestWithoutErrors) {
ASSERT_EQ(0, tests_->ViERtpRtcpExtendedTest());
}
}
} // namespace

View File

@ -15,8 +15,8 @@
* to verify any video output - it only checks for direct errors.
*/
#include "gflags/gflags.h"
#include "gtest/gtest.h"
#include "vie_autotest.h"
#include "vie_autotest_window_manager_interface.h"
#include "vie_integration_test_base.h"
@ -24,13 +24,45 @@
namespace {
// Define flag validators for our flags:
static bool ValidatePath(const char* flag_name, const std::string& value) {
return !value.empty();
}
static bool ValidateDimension(const char* flag_name, WebRtc_Word32 value) {
if (value <= 0) {
return false;
}
return true;
}
// Define the flags themselves:
DEFINE_string(i420_test_video_path, "", "Path to an i420-coded raw video file"
" to use for the test. This file is fed into the fake camera"
" and will therefore be what the camera 'sees'.");
static const bool dummy1 =
google::RegisterFlagValidator(&FLAGS_i420_test_video_path,
&ValidatePath);
DEFINE_int32(i420_test_video_width, 0, "The width of the provided video.");
static const bool dummy2 =
google::RegisterFlagValidator(&FLAGS_i420_test_video_width,
&ValidateDimension);
DEFINE_int32(i420_test_video_height, 0, "The height of the provided video.");
static const bool dummy3 =
google::RegisterFlagValidator(&FLAGS_i420_test_video_height,
&ValidateDimension);
class ViEStandardIntegrationTest: public ViEIntegrationTest {
};
TEST_F(ViEStandardIntegrationTest, RunsBaseTestWithoutErrors) {
ASSERT_EQ(0, tests_->ViEBaseStandardTest());
tests_->ViEAutomatedBaseStandardTest(FLAGS_i420_test_video_path,
FLAGS_i420_test_video_width,
FLAGS_i420_test_video_height);
}
// These tests still require a physical camera:
TEST_F(ViEStandardIntegrationTest, RunsCaptureTestWithoutErrors) {
ASSERT_EQ(0, tests_->ViECaptureStandardTest());
}
@ -62,4 +94,5 @@ TEST_F(ViEStandardIntegrationTest, RunsRenderTestWithoutErrors) {
TEST_F(ViEStandardIntegrationTest, RunsRtpRctpTestWithoutErrors) {
ASSERT_EQ(0, tests_->ViERtpRtcpStandardTest());
}
}
} // namespace

View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "vie_file_capture_device.h"
#include "common_types.h"
#include "critical_section_wrapper.h"
#include "event_wrapper.h"
#include "module_common_types.h"
#include "vie_autotest_defines.h"
#include "vie_capture.h"
#include "tick_util.h"
// This class ensures we are not exceeding the max FPS.
class FramePacemaker {
public:
explicit FramePacemaker(uint32_t max_fps)
: time_per_frame_ms_(1000 / max_fps) {
frame_start_ = webrtc::TickTime::MillisecondTimestamp();
}
void SleepIfNecessary(webrtc::EventWrapper* sleeper) {
uint64_t now = webrtc::TickTime::MillisecondTimestamp();
if (now - frame_start_ < time_per_frame_ms_) {
sleeper->Wait(time_per_frame_ms_ - (now - frame_start_));
}
}
private:
uint64_t frame_start_;
uint64_t time_per_frame_ms_;
};
ViEFileCaptureDevice::ViEFileCaptureDevice(
webrtc::ViEExternalCapture* input_sink)
: input_sink_(input_sink),
input_file_(NULL) {
mutex_ = webrtc::CriticalSectionWrapper::CreateCriticalSection();
}
ViEFileCaptureDevice::~ViEFileCaptureDevice() {
delete mutex_;
}
bool ViEFileCaptureDevice::OpenI420File(const std::string& path,
int width,
int height) {
webrtc::CriticalSectionScoped cs(*mutex_);
assert(input_file_ == NULL);
input_file_ = std::fopen(path.c_str(), "rb");
if (input_file_ == NULL) {
return false;
}
frame_length_ = 3 * width * height / 2;
width_ = width;
height_ = height;
return true;
}
void ViEFileCaptureDevice::ReadFileFor(uint64_t time_slice_ms,
uint32_t max_fps) {
webrtc::CriticalSectionScoped cs(*mutex_);
assert(input_file_ != NULL);
webrtc::VideoFrame sourceFrame;
sourceFrame.VerifyAndAllocate(frame_length_);
unsigned char* frame_buffer = new unsigned char[frame_length_];
webrtc::EventWrapper* sleeper = webrtc::EventWrapper::Create();
uint64_t start_time_ms = webrtc::TickTime::MillisecondTimestamp();
uint64_t elapsed_ms = 0;
while (elapsed_ms < time_slice_ms) {
FramePacemaker pacemaker(max_fps);
std::fread(frame_buffer, 1, frame_length_, input_file_);
if (std::feof(input_file_)) {
std::rewind(input_file_);
}
input_sink_->IncomingFrame(frame_buffer, frame_length_, width_,
height_, webrtc::kVideoI420,
webrtc::TickTime::MillisecondTimestamp());
pacemaker.SleepIfNecessary(sleeper);
elapsed_ms = webrtc::TickTime::MillisecondTimestamp() - start_time_ms;
}
delete sleeper;
delete[] frame_buffer;
}
void ViEFileCaptureDevice::CloseFile() {
webrtc::CriticalSectionScoped cs(*mutex_);
assert(input_file_ != NULL);
std::fclose(input_file_);
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef SRC_VIDEO_ENGINE_MAIN_TEST_AUTOTEST_HELPERS_VIE_FILE_CAPTURE_DEVICE_H_
#define SRC_VIDEO_ENGINE_MAIN_TEST_AUTOTEST_HELPERS_VIE_FILE_CAPTURE_DEVICE_H_
#include <cstdio>
#include <string>
#include "typedefs.h"
namespace webrtc {
class CriticalSectionWrapper;
class EventWrapper;
class ViEExternalCapture;
}
/**
* This class opens a i420 file and feeds it into a ExternalCapture instance,
* thereby acting as a faked capture device with deterministic input.
*/
class ViEFileCaptureDevice {
public:
// The input sink is where to send the I420 video frames.
explicit ViEFileCaptureDevice(webrtc::ViEExternalCapture* input_sink);
virtual ~ViEFileCaptureDevice();
// Opens the provided I420 file and interprets it according to the provided
// width and height. Returns false if the file doesn't exist.
bool OpenI420File(const std::string& path, int width, int height);
// Reads the previously opened file for at most time_slice_ms milliseconds,
// after which it will return. It will make sure to sleep accordingly so we
// do not send more than max_fps cap (we may send less, though).
void ReadFileFor(uint64_t time_slice_ms, uint32_t max_fps);
// Closes the opened input file.
void CloseFile();
private:
webrtc::ViEExternalCapture* input_sink_;
std::FILE* input_file_;
webrtc::CriticalSectionWrapper* mutex_;
WebRtc_UWord32 frame_length_;
WebRtc_UWord8* frame_buffer_;
WebRtc_UWord32 width_;
WebRtc_UWord32 height_;
};
#endif // SRC_VIDEO_ENGINE_MAIN_TEST_AUTOTEST_HELPERS_VIE_FILE_CAPTURE_DEVICE_H_

View File

@ -60,6 +60,11 @@ public:
int ViEBaseExtendedTest();
int ViEBaseAPITest();
// This is a variant of the base standard test, meant to run in GTest.
void ViEAutomatedBaseStandardTest(const std::string& pathToTestI420Video,
int width,
int height);
// vie_autotest_capture.cc
int ViECaptureStandardTest();
int ViECaptureExtendedTest();
@ -108,12 +113,16 @@ private:
// If this operation fails, device_id is assigned a negative value
// and number_of_errors is incremented.
void FindCaptureDeviceOnSystem(webrtc::ViECapture* capture,
WebRtc_UWord8* device_name,
unsigned char* device_name,
const unsigned int kDeviceNameLength,
int* device_id,
int* number_of_errors,
webrtc::VideoCaptureModule** device_video);
webrtc::ViERender *RenderInBothWindows(webrtc::VideoEngine * ptrViE,
int & numberOfErrors, int captureId,
int videoChannel);
void PrintAudioCodec(const webrtc::CodecInst audioCodec);
void PrintVideoCodec(const webrtc::VideoCodec videoCodec);

View File

@ -12,11 +12,13 @@
// vie_autotest_base.cc
//
#include "vie_autotest.h"
#include "gtest/gtest.h"
#include "thread_wrapper.h"
#include "vie_autotest.h"
#include "vie_autotest_defines.h"
#include "engine_configurations.h"
#include "video_capture_factory.h"
#include "vie_file_capture_device.h"
class BaseObserver : public webrtc::ViEBaseObserver {
public:
@ -29,84 +31,72 @@ class BaseObserver : public webrtc::ViEBaseObserver {
unsigned int cpu_load_;
};
int ViEAutoTest::ViEBaseStandardTest() {
ViETest::Log(" ");
ViETest::Log("========================================");
ViETest::Log(" ViEBase Standard Test");
// ***************************************************************
// Begin create/initialize WebRTC Video Engine for testing
// ***************************************************************
int error = 0;
int numberOfErrors = 0;
webrtc::VideoEngine *InitializeVideoEngine(int & numberOfErrors) {
ViETest::Log("Starting a loopback call...");
webrtc::VideoEngine* ptrViE = NULL;
ptrViE = webrtc::VideoEngine::Create();
webrtc::VideoEngine *ptrViE = webrtc::VideoEngine::Create();
numberOfErrors += ViETest::TestError(ptrViE != NULL,
"ERROR: %s at line %d", __FUNCTION__,
__LINE__);
#ifdef WEBRTC_ANDROID
error = ptrViE->SetTraceFile("/sdcard/ViEBaseStandardTest_trace.txt");
int error = ptrViE->SetTraceFile("/sdcard/ViEBaseStandardTest_trace.txt");
numberOfErrors += ViETest::TestError(error == 0,
"ERROR: %s at line %d", __FUNCTION__,
__LINE__);
#else
error = ptrViE->SetTraceFile("ViEBaseStandardTest_trace.txt");
int error = ptrViE->SetTraceFile("ViEBaseStandardTest_trace.txt");
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
#endif
return ptrViE;
}
webrtc::ViEBase *InitializeViEBase(webrtc::VideoEngine * ptrViE,
int & numberOfErrors) {
webrtc::ViEBase *ptrViEBase = webrtc::ViEBase::GetInterface(ptrViE);
numberOfErrors += ViETest::TestError(ptrViEBase != NULL,
"ERROR: %s at line %d", __FUNCTION__,
__LINE__);
error = ptrViEBase->Init();
int error = ptrViEBase->Init();
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
return ptrViEBase;
}
webrtc::ViECapture *InitializeChannel(webrtc::ViEBase * ptrViEBase,
int & videoChannel,
int & numberOfErrors,
webrtc::VideoEngine * ptrViE) {
int error = ptrViEBase->CreateChannel(videoChannel);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
// ***************************************************************
// Engine ready. Begin testing class
// ***************************************************************
int videoChannel = -1;
error = ptrViEBase->CreateChannel(videoChannel);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
webrtc::ViECapture *ptrViECapture =
webrtc::ViECapture::GetInterface(ptrViE);
webrtc::ViECapture *ptrViECapture = webrtc::ViECapture::GetInterface(ptrViE);
numberOfErrors += ViETest::TestError(ptrViECapture != NULL,
"ERROR: %s at line %d", __FUNCTION__,
__LINE__);
return ptrViECapture;
}
webrtc::VideoCaptureModule* vcpm(NULL);
const unsigned int KMaxDeviceNameLength = 128;
WebRtc_UWord8 deviceName[KMaxDeviceNameLength];
memset(deviceName, 0, KMaxDeviceNameLength);
int captureId;
FindCaptureDeviceOnSystem(ptrViECapture,
deviceName,
KMaxDeviceNameLength,
&captureId,
&numberOfErrors,
&vcpm);
error = ptrViECapture->ConnectCaptureDevice(captureId, videoChannel);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
error = ptrViECapture->StartCapture(captureId);
void ConnectCaptureDevice(webrtc::ViECapture * ptrViECapture,
int captureId,
int videoChannel,
int & numberOfErrors) {
int error = ptrViECapture->ConnectCaptureDevice(captureId, videoChannel);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
}
webrtc::ViERTP_RTCP *ConfigureRtpRtcp(webrtc::VideoEngine * ptrViE,
int & numberOfErrors,
int videoChannel) {
webrtc::ViERTP_RTCP *ptrViERtpRtcp =
webrtc::ViERTP_RTCP::GetInterface(ptrViE);
numberOfErrors += ViETest::TestError(ptrViE != NULL,
"ERROR: %s at line %d", __FUNCTION__,
__LINE__);
error = ptrViERtpRtcp->SetRTCPStatus(videoChannel,
webrtc::kRtcpCompound_RFC4585);
int error = ptrViERtpRtcp->
SetRTCPStatus(videoChannel, webrtc::kRtcpCompound_RFC4585);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
error = ptrViERtpRtcp->
@ -117,11 +107,17 @@ int ViEAutoTest::ViEBaseStandardTest() {
error = ptrViERtpRtcp->SetTMMBRStatus(videoChannel, true);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
return ptrViERtpRtcp;
}
webrtc::ViERender *ViEAutoTest::RenderInBothWindows(
webrtc::VideoEngine * ptrViE, int & numberOfErrors,
int captureId, int videoChannel) {
webrtc::ViERender *ptrViERender = webrtc::ViERender::GetInterface(ptrViE);
numberOfErrors += ViETest::TestError(ptrViERender != NULL,
"ERROR: %s at line %d", __FUNCTION__,
__LINE__);
error = ptrViERender->RegisterVideoRenderModule(*_vrm1);
int error = ptrViERender->RegisterVideoRenderModule(*_vrm1);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
error = ptrViERender->AddRenderer(captureId, _window1, 0, 0.0,
@ -134,17 +130,23 @@ int ViEAutoTest::ViEBaseStandardTest() {
error = ptrViERender->RegisterVideoRenderModule(*_vrm2);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
error = ptrViERender->AddRenderer(videoChannel, _window2, 1, 0.0, 0.0,
1.0, 1.0);
error = ptrViERender->AddRenderer(videoChannel, _window2, 1, 0.0,
0.0, 1.0, 1.0);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
error = ptrViERender->StartRender(videoChannel);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
webrtc::ViECodec *ptrViECodec = webrtc::ViECodec::GetInterface(ptrViE);
numberOfErrors += ViETest::TestError(ptrViECodec != NULL,
"ERROR: %s at line %d", __FUNCTION__,
__LINE__);
return ptrViERender;
}
webrtc::ViENetwork *TestCallSetup(webrtc::ViECodec * ptrViECodec,
int & numberOfErrors,
int videoChannel,
webrtc::VideoEngine * ptrViE,
webrtc::ViEBase * ptrViEBase,
const WebRtc_UWord8 *deviceName) {
int error;
webrtc::VideoCodec videoCodec;
memset(&videoCodec, 0, sizeof(webrtc::VideoCodec));
for (int idx = 0; idx < ptrViECodec->NumberOfCodecs(); idx++) {
@ -179,8 +181,8 @@ int ViEAutoTest::ViEBaseStandardTest() {
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
const char *ipAddress = "127.0.0.1";
unsigned short rtpPortListen = 6000;
unsigned short rtpPortSend = 6000;
WebRtc_UWord16 rtpPortListen = 6000;
WebRtc_UWord16 rtpPortSend = 6000;
rtpPortListen = 6100;
rtpPortSend = 6100;
error = ptrViENetwork->SetLocalReceiver(videoChannel, rtpPortListen);
@ -189,116 +191,176 @@ int ViEAutoTest::ViEBaseStandardTest() {
error = ptrViEBase->StartReceive(videoChannel);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
error = ptrViENetwork->SetSendDestination(videoChannel,
ipAddress, rtpPortSend);
error = ptrViENetwork->SetSendDestination(videoChannel, ipAddress,
rtpPortSend);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
error = ptrViEBase->StartSend(videoChannel);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
error = ptrViERender->MirrorRenderStream(captureId, true, false, true);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
// Call started
ViETest::Log("Call started");
ViETest::Log(
"You should see a mirrored local preview from camera %s"
ViETest::Log("You should see a local preview from camera %s"
" in window 1 and the remote video in window 2.", deviceName);
return ptrViENetwork;
}
void StopEverything(webrtc::ViEBase * ptrViEBase,
int videoChannel,
int & numberOfErrors,
webrtc::ViERender * ptrViERender,
int captureId,
webrtc::ViECapture * ptrViECapture,
webrtc::VideoRender* vrm1,
webrtc::VideoRender* vrm2) {
int error = ptrViEBase->StopReceive(videoChannel);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
error = ptrViERender->StopRender(videoChannel);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
error = ptrViERender->RemoveRenderer(videoChannel);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
error = ptrViERender->DeRegisterVideoRenderModule(*vrm2);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
error = ptrViEBase->StopSend(videoChannel);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
error = ptrViERender->RemoveRenderer(captureId);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
error = ptrViERender->DeRegisterVideoRenderModule(*vrm1);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
error = ptrViECapture->DisconnectCaptureDevice(videoChannel);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
error = ptrViECapture->ReleaseCaptureDevice(captureId);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
}
void ReleaseEverything(webrtc::ViECapture *ptrViECapture,
int& numberOfErrors,
webrtc::ViEBase *ptrViEBase,
int videoChannel,
webrtc::ViECodec *ptrViECodec,
webrtc::ViERTP_RTCP *ptrViERtpRtcp,
webrtc::ViERender *ptrViERender,
webrtc::ViENetwork *ptrViENetwork,
webrtc::VideoEngine *ptrViE) {
int remainingInterfaces = ptrViECapture->Release();
numberOfErrors += ViETest::TestError(remainingInterfaces == 0,
"ERROR: %s at line %d", __FUNCTION__,
__LINE__);
int error2 = ptrViEBase->DeleteChannel(videoChannel);
numberOfErrors += ViETest::TestError(error2 == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
remainingInterfaces = ptrViECodec->Release();
numberOfErrors += ViETest::TestError(remainingInterfaces == 0,
"ERROR: %s at line %d", __FUNCTION__,
__LINE__);
remainingInterfaces = ptrViERtpRtcp->Release();
numberOfErrors += ViETest::TestError(remainingInterfaces == 0,
"ERROR: %s at line %d", __FUNCTION__,
__LINE__);
remainingInterfaces = ptrViERender->Release();
numberOfErrors += ViETest::TestError(remainingInterfaces == 0,
"ERROR: %s at line %d", __FUNCTION__,
__LINE__);
remainingInterfaces = ptrViENetwork->Release();
numberOfErrors += ViETest::TestError(remainingInterfaces == 0,
"ERROR: %s at line %d", __FUNCTION__,
__LINE__);
remainingInterfaces = ptrViEBase->Release();
numberOfErrors += ViETest::TestError(remainingInterfaces == 0,
"ERROR: %s at line %d", __FUNCTION__,
__LINE__);
bool deleted = webrtc::VideoEngine::Delete(ptrViE);
numberOfErrors += ViETest::TestError(deleted == true,
"ERROR: %s at line %d", __FUNCTION__,
__LINE__);
}
int ViEAutoTest::ViEBaseStandardTest() {
ViETest::Log(" ");
ViETest::Log("========================================");
ViETest::Log(" ViEBase Standard Test");
// ***************************************************************
// Finished initializing engine. Begin testing
// Begin create/initialize WebRTC Video Engine for testing
// ***************************************************************
int numberOfErrors = 0;
webrtc::VideoEngine* ptrViE = InitializeVideoEngine(numberOfErrors);
webrtc::ViEBase *ptrViEBase = InitializeViEBase(ptrViE, numberOfErrors);
// ***************************************************************
// Engine ready. Set up the test case:
// ***************************************************************
int videoChannel = -1;
webrtc::ViECapture *ptrViECapture =
InitializeChannel(ptrViEBase, videoChannel, numberOfErrors, ptrViE);
webrtc::VideoCaptureModule* vcpm(NULL);
const unsigned int kMaxDeviceNameLength = 128;
WebRtc_UWord8 deviceName[kMaxDeviceNameLength];
memset(deviceName, 0, kMaxDeviceNameLength);
int captureId;
FindCaptureDeviceOnSystem(ptrViECapture,
deviceName,
kMaxDeviceNameLength,
&captureId,
&numberOfErrors,
&vcpm);
ConnectCaptureDevice(ptrViECapture, captureId, videoChannel, numberOfErrors);
int error = ptrViECapture->StartCapture(captureId);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
webrtc::ViERTP_RTCP *ptrViERtpRtcp =
ConfigureRtpRtcp(ptrViE, numberOfErrors, videoChannel);
webrtc::ViERender *ptrViERender =
RenderInBothWindows(ptrViE, numberOfErrors, captureId, videoChannel);
webrtc::ViECodec *ptrViECodec = webrtc::ViECodec::GetInterface(ptrViE);
numberOfErrors += ViETest::TestError(ptrViECodec != NULL,
"ERROR: %s at line %d", __FUNCTION__,
__LINE__);
// ***************************************************************
// Set up the call and wait.
// ***************************************************************
webrtc::ViENetwork *ptrViENetwork =
TestCallSetup(ptrViECodec, numberOfErrors, videoChannel,
ptrViE, ptrViEBase, deviceName);
AutoTestSleep(KAutoTestSleepTimeMs);
// ***************************************************************
// Testing finished. Tear down Video Engine
// ***************************************************************
// Shut down
error = ptrViEBase->StopReceive(videoChannel);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
error = ptrViERender->StopRender(videoChannel);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
error = ptrViERender->RemoveRenderer(videoChannel);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
error = ptrViERender->DeRegisterVideoRenderModule(*_vrm2);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
int remainingInterfaces = 0;
error = ptrViEBase->StopSend(videoChannel);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
error = ptrViERender->RemoveRenderer(captureId);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
error = ptrViERender->DeRegisterVideoRenderModule(*_vrm1);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
error = ptrViECapture->StopCapture(captureId);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
error = ptrViECapture->DisconnectCaptureDevice(videoChannel);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
error = ptrViECapture->ReleaseCaptureDevice(captureId);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
StopEverything(ptrViEBase, videoChannel, numberOfErrors, ptrViERender,
captureId, ptrViECapture, _vrm1, _vrm2);
vcpm->Release();
vcpm = NULL;
remainingInterfaces = ptrViECapture->Release();
numberOfErrors += ViETest::TestError(remainingInterfaces == 0,
"ERROR: %s at line %d", __FUNCTION__,
__LINE__);
error = ptrViEBase->DeleteChannel(videoChannel);
numberOfErrors += ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
remainingInterfaces = ptrViECodec->Release();
numberOfErrors += ViETest::TestError(remainingInterfaces == 0,
"ERROR: %s at line %d", __FUNCTION__,
__LINE__);
remainingInterfaces = ptrViERtpRtcp->Release();
numberOfErrors += ViETest::TestError(remainingInterfaces == 0,
"ERROR: %s at line %d", __FUNCTION__,
__LINE__);
remainingInterfaces = ptrViERender->Release();
numberOfErrors += ViETest::TestError(remainingInterfaces == 0,
"ERROR: %s at line %d", __FUNCTION__,
__LINE__);
remainingInterfaces = ptrViENetwork->Release();
numberOfErrors += ViETest::TestError(remainingInterfaces == 0,
"ERROR: %s at line %d", __FUNCTION__,
__LINE__);
remainingInterfaces = ptrViEBase->Release();
numberOfErrors += ViETest::TestError(remainingInterfaces == 0,
"ERROR: %s at line %d", __FUNCTION__,
__LINE__);
bool deleted = webrtc::VideoEngine::Delete(ptrViE);
numberOfErrors += ViETest::TestError(deleted == true,
"ERROR: %s at line %d", __FUNCTION__,
__LINE__);
ReleaseEverything(ptrViECapture, numberOfErrors, ptrViEBase, videoChannel,
ptrViECodec, ptrViERtpRtcp, ptrViERender, ptrViENetwork,
ptrViE);
if (numberOfErrors > 0) {
// Test failed
@ -360,7 +422,6 @@ int ViEAutoTest::ViEBaseAPITest() {
// ***************************************************************
// Begin create/initialize WebRTC Video Engine for testing
// ***************************************************************
int error = 0;
int numberOfErrors = 0;
@ -474,7 +535,6 @@ int ViEAutoTest::ViEBaseAPITest() {
// ***************************************************************
// Testing finished. Tear down Video Engine
// ***************************************************************
error = ptrViEBase->DisconnectAudioChannel(videoChannel + 5);
numberOfErrors += ViETest::TestError(error != 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
@ -530,9 +590,98 @@ int ViEAutoTest::ViEBaseAPITest() {
return 0;
}
// This callback gets used in the automated test case below:
bool StreamVideoFileRepeatedlyIntoCaptureDevice(void* data) {
ViEFileCaptureDevice* file_capture_device =
reinterpret_cast<ViEFileCaptureDevice*>(data);
WebRtc_UWord64 time_slice_ms = 1500;
WebRtc_UWord64 max_fps = 30;
file_capture_device->ReadFileFor(time_slice_ms, max_fps);
return true;
}
void ViEAutoTest::ViEAutomatedBaseStandardTest(
const std::string& pathToTestI420Video, int width, int height) {
int ignoredNumberOfErrors;
// Initialize the test:
webrtc::VideoEngine* ptrViE =
InitializeVideoEngine(ignoredNumberOfErrors);
webrtc::ViEBase *ptrViEBase =
InitializeViEBase(ptrViE, ignoredNumberOfErrors);
int videoChannel = -1;
webrtc::ViECapture *ptrViECapture =
InitializeChannel(ptrViEBase, videoChannel,
ignoredNumberOfErrors, ptrViE);
int captureId;
webrtc::ViEExternalCapture* externalCapture;
int error = ptrViECapture->AllocateExternalCaptureDevice(captureId,
externalCapture);
ViETest::TestError(error == 0, "ERROR: %s at line %d",
__FUNCTION__, __LINE__);
ViEFileCaptureDevice capturer(externalCapture);
if (!capturer.OpenI420File(pathToTestI420Video, width, height)) {
// No point in continuing if we have no proper video source
ViETest::TestError(false, "ERROR: %s at line %d: "
"Could not open input video %s: aborting test...",
__FUNCTION__, __LINE__, pathToTestI420Video.c_str());
return;
}
// Set up a thread which runs the fake camera. Note that the capturer is
// handed off to the other thread - it should not be touched in this
// method until the other thread is stopped!
webrtc::ThreadWrapper* thread = webrtc::ThreadWrapper::CreateThread(
StreamVideoFileRepeatedlyIntoCaptureDevice, &capturer);
unsigned int id;
thread->Start(id);
// Apparently, we need to connect external capture devices, but we should
// not start them since the external device is not a proper device.
ConnectCaptureDevice(ptrViECapture, captureId, videoChannel,
ignoredNumberOfErrors);
webrtc::ViERTP_RTCP *ptrViERtpRtcp =
ConfigureRtpRtcp(ptrViE, ignoredNumberOfErrors, videoChannel);
webrtc::ViERender *ptrViERender =
RenderInBothWindows(ptrViE, ignoredNumberOfErrors,
captureId, videoChannel);
webrtc::ViECodec *ptrViECodec = webrtc::ViECodec::GetInterface(ptrViE);
ignoredNumberOfErrors +=
ViETest::TestError(ptrViECodec != NULL,
"ERROR: %s at line %d", __FUNCTION__,
__LINE__);
// Run the test itself:
const WebRtc_UWord8* deviceName =
reinterpret_cast<const WebRtc_UWord8*>("Fake Capture Device");
webrtc::ViENetwork *ptrViENetwork =
TestCallSetup(ptrViECodec, ignoredNumberOfErrors, videoChannel,
ptrViE, ptrViEBase, deviceName);
AutoTestSleep(KAutoTestSleepTimeMs);
// Done, clean up
thread->Stop();
capturer.CloseFile();
StopEverything(ptrViEBase, videoChannel, ignoredNumberOfErrors, ptrViERender,
captureId, ptrViECapture, _vrm1, _vrm2);
ReleaseEverything(ptrViECapture, ignoredNumberOfErrors, ptrViEBase,
videoChannel, ptrViECodec, ptrViERtpRtcp, ptrViERender,
ptrViENetwork, ptrViE);
}
void ViEAutoTest::FindCaptureDeviceOnSystem(
webrtc::ViECapture* capture,
WebRtc_UWord8* device_name,
unsigned char* device_name,
unsigned int device_name_length,
int* device_id,
int* number_of_errors,

View File

@ -11,15 +11,14 @@
//
// vie_autotest_linux.cc
//
#include "gtest/gtest.h"
#include <string>
#include "vie_autotest_linux.h"
#include <string>
#include "gflags/gflags.h"
#include "gtest/gtest.h"
#include "vie_autotest_defines.h"
#include "vie_autotest_main.h"
#include "engine_configurations.h"
#include "critical_section_wrapper.h"
#include "thread_wrapper.h"
@ -138,10 +137,18 @@ bool ViEAutoTestWindowManager::SetTopmostWindow() {
int main(int argc, char** argv) {
// This command-line flag is a transitory solution until we
// managed to rewrite all tests to GUnit tests. This flag is
// manage to rewrite all tests to GUnit tests. This flag is
// currently only supported in Linux.
if (argc == 2 && std::string(argv[1]) == "--automated") {
if (argc > 1 && std::string(argv[1]) == "--automated") {
// Let GTest and GFlags handle flags from now on
argc -= 1;
argv += 1;
// Initialize the testing framework
testing::InitGoogleTest(&argc, argv);
// Parse remaining flags:
google::ParseCommandLineFlags(&argc, &argv, true);
// Run tests
return RUN_ALL_TESTS();
}

View File

@ -17,6 +17,7 @@
'<(webrtc_root)/modules/modules.gyp:video_capture_module',
'<(webrtc_root)/voice_engine/voice_engine.gyp:voice_engine_core',
'<(webrtc_root)/../testing/gtest.gyp:gtest',
'<(webrtc_root)/../third_party/google-gflags/google-gflags.gyp:google-gflags',
'video_engine_core',
],
'include_dirs': [
@ -44,6 +45,7 @@
# Helper classes
'helpers/vie_window_creator.cc',
'helpers/vie_file_capture_device.cc',
# New, fully automated tests
'automated/vie_api_integration_test.cc',