Fixed standard PSNR/SSIM test.
BUG=1103 Review URL: https://webrtc-codereview.appspot.com/971005 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3197 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
bf41508807
commit
273ccad59d
@ -43,6 +43,9 @@ enum VideoType {
|
||||
kBGRA,
|
||||
};
|
||||
|
||||
// This is the max PSNR value our algorithms can return.
|
||||
const double kInfinitePSNR = 48.0f;
|
||||
|
||||
// Conversion between the RawVideoType and the LibYuv videoType.
|
||||
// TODO(wu): Consolidate types into one type throughout WebRtc.
|
||||
VideoType RawVideoTypeToCommonVideoVideoType(RawVideoType type);
|
||||
@ -163,6 +166,7 @@ int MirrorI420UpDown(const I420VideoFrame* src_frame,
|
||||
I420VideoFrame* dst_frame);
|
||||
|
||||
// Compute PSNR for an I420 frame (all planes).
|
||||
// Returns the PSNR in decibel, to a maximum of kInfinitePSNR.
|
||||
double I420PSNR(const I420VideoFrame* ref_frame,
|
||||
const I420VideoFrame* test_frame);
|
||||
// Compute SSIM for an I420 frame (all planes).
|
||||
@ -171,6 +175,7 @@ double I420SSIM(const I420VideoFrame* ref_frame,
|
||||
|
||||
// TODO(mikhal): Remove these functions and keep only the above functionality.
|
||||
// Compute PSNR for an I420 buffer (all planes).
|
||||
// Returns the PSNR in decibel, to a maximum of kInfinitePSNR.
|
||||
double I420PSNR(const uint8_t* ref_frame,
|
||||
const uint8_t* test_frame,
|
||||
int width, int height);
|
||||
|
@ -352,9 +352,9 @@ double I420PSNR(const I420VideoFrame* ref_frame,
|
||||
test_frame->buffer(kVPlane),
|
||||
test_frame->stride(kVPlane),
|
||||
test_frame->width(), test_frame->height());
|
||||
// LibYuv sets the max psnr value to 128, we restrict it to 48.
|
||||
// LibYuv sets the max psnr value to 128, we restrict it here.
|
||||
// In case of 0 mse in one frame, 128 can skew the results significantly.
|
||||
return (psnr > 48.0) ? 48.0 : psnr;
|
||||
return (psnr > kInfinitePSNR) ? kInfinitePSNR : psnr;
|
||||
}
|
||||
|
||||
// Compute SSIM for an I420 frame (all planes)
|
||||
@ -407,9 +407,9 @@ double I420PSNR(const uint8_t* ref_frame,
|
||||
src_u_b, half_width,
|
||||
src_v_b, half_width,
|
||||
width, height);
|
||||
// LibYuv sets the max psnr value to 128, we restrict it to 48.
|
||||
// LibYuv sets the max psnr value to 128, we restrict it here.
|
||||
// In case of 0 mse in one frame, 128 can skew the results significantly.
|
||||
return (psnr > 48.0) ? 48.0 : psnr;
|
||||
return (psnr > kInfinitePSNR) ? kInfinitePSNR : psnr;
|
||||
}
|
||||
// Compute SSIM for an I420 frame (all planes)
|
||||
double I420SSIM(const uint8_t* ref_frame,
|
||||
|
@ -249,6 +249,7 @@ VCMMediaOptimization::DropFrame()
|
||||
{
|
||||
// leak appropriate number of bytes
|
||||
_frameDropper->Leak((WebRtc_UWord32)(InputFrameRate() + 0.5f));
|
||||
|
||||
return _frameDropper->DropFrame();
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,9 @@
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
// Copy here so our callers won't need to include libyuv for this constant.
|
||||
double kMetricsInfinitePSNR = kInfinitePSNR;
|
||||
|
||||
// Used for calculating min and max values.
|
||||
static bool LessForFrameResultValue (const FrameResult& s1,
|
||||
const FrameResult& s2) {
|
||||
|
@ -17,6 +17,9 @@
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
// The highest PSNR value our algorithms will return.
|
||||
extern double kMetricsInfinitePSNR;
|
||||
|
||||
// Contains video quality metrics result for a single frame.
|
||||
struct FrameResult {
|
||||
int frame_number;
|
||||
@ -43,10 +46,13 @@ struct QualityMetricsResult {
|
||||
|
||||
// Calculates PSNR and SSIM values for the reference and test video files
|
||||
// (must be in I420 format). All calculated values are filled into the
|
||||
// QualityMetricsResult stucts.
|
||||
// QualityMetricsResult structs.
|
||||
//
|
||||
// PSNR values have the unit decibel (dB) where a high value means the test file
|
||||
// is similar to the reference file. The higher value, the more similar.
|
||||
// For more info about PSNR, see http://en.wikipedia.org/wiki/PSNR
|
||||
// is similar to the reference file. The higher value, the more similar. The
|
||||
// maximum PSNR value is kMetricsInfinitePSNR. For more info about PSNR, see
|
||||
// http://en.wikipedia.org/wiki/PSNR.
|
||||
//
|
||||
// SSIM values range between -1.0 and 1.0, where 1.0 means the files are
|
||||
// identical. For more info about SSIM, see http://en.wikipedia.org/wiki/SSIM
|
||||
// This function only compares video frames up to the point when the shortest
|
||||
@ -67,11 +73,14 @@ int I420MetricsFromFiles(const char* ref_filename,
|
||||
// Calculates PSNR values for the reference and test video files (must be in
|
||||
// I420 format). All calculated values are filled into the QualityMetricsResult
|
||||
// struct.
|
||||
//
|
||||
// PSNR values have the unit decibel (dB) where a high value means the test file
|
||||
// is similar to the reference file. The higher value, the more similar.
|
||||
// is similar to the reference file. The higher value, the more similar. The
|
||||
// maximum PSNR value is kMetricsInfinitePSNR. For more info about PSNR, see
|
||||
// http://en.wikipedia.org/wiki/PSNR.
|
||||
//
|
||||
// This function only compares video frames up to the point when the shortest
|
||||
// video ends.
|
||||
// For more info about PSNR, see http://en.wikipedia.org/wiki/PSNR
|
||||
//
|
||||
// Return value:
|
||||
// 0 if successful, negative on errors:
|
||||
|
@ -25,7 +25,6 @@ namespace {
|
||||
// wouldn't like scaling, so this will work when we compare with the original.
|
||||
const int kInputWidth = 176;
|
||||
const int kInputHeight = 144;
|
||||
const int kVerifyingTestMaxNumAttempts = 3;
|
||||
|
||||
class ViEVideoVerificationTest : public testing::Test {
|
||||
protected:
|
||||
@ -72,7 +71,8 @@ class ViEVideoVerificationTest : public testing::Test {
|
||||
EXPECT_EQ(0, error) << "SSIM routine failed - output files missing?";
|
||||
*ssim_result = ssim.average;
|
||||
|
||||
ViETest::Log("Results: PSNR is %f (dB), SSIM is %f (1 is perfect)",
|
||||
ViETest::Log("Results: PSNR is %f (dB; 48 is max), "
|
||||
"SSIM is %f (1 is perfect)",
|
||||
psnr.average, ssim.average);
|
||||
}
|
||||
|
||||
@ -140,41 +140,40 @@ class ParameterizedFullStackTest : public ViEVideoVerificationTest,
|
||||
TestParameters parameter_table_[2];
|
||||
};
|
||||
|
||||
// TODO(phoglund): Needs to be rewritten to use external transport. Currently
|
||||
// the new memory-safe decoder is too slow with I420 with the default packet
|
||||
// engine. See http://code.google.com/p/webrtc/issues/detail?id=1103.
|
||||
TEST_F(ViEVideoVerificationTest, DISABLED_RunsBaseStandardTestWithoutErrors) {
|
||||
// The I420 test should give pretty good values since it's a lossless codec
|
||||
// running on the default bitrate. It should average about 30 dB but there
|
||||
// may be cases where it dips as low as 26 under adverse conditions. That's
|
||||
// why we have a retrying mechanism in place for this test.
|
||||
const double kExpectedMinimumPSNR = 30;
|
||||
const double kExpectedMinimumSSIM = 0.95;
|
||||
|
||||
for (int attempt = 0; attempt < kVerifyingTestMaxNumAttempts; attempt++) {
|
||||
TEST_F(ViEVideoVerificationTest, RunsBaseStandardTestWithoutErrors) {
|
||||
// I420 is lossless, so the I420 test should obviously get perfect results -
|
||||
// the local preview and remote output files should be bit-exact. This test
|
||||
// runs on external transport to ensure we do not drop packets.
|
||||
// However, it's hard to make 100% stringent requirements on the video engine
|
||||
// since for instance the jitter buffer has non-deterministic elements. If it
|
||||
// breaks five times in a row though, you probably introduced a bug.
|
||||
const int kNumAttempts = 5;
|
||||
for (int attempt = 0; attempt < kNumAttempts; ++attempt) {
|
||||
InitializeFileRenderers();
|
||||
ASSERT_TRUE(tests_.TestCallSetup(input_file_, kInputWidth, kInputHeight,
|
||||
local_file_renderer_,
|
||||
remote_file_renderer_));
|
||||
std::string output_file = remote_file_renderer_->GetFullOutputPath();
|
||||
std::string remote_file = remote_file_renderer_->GetFullOutputPath();
|
||||
std::string local_preview = local_file_renderer_->GetFullOutputPath();
|
||||
StopRenderers();
|
||||
|
||||
double actual_psnr = 0;
|
||||
double actual_ssim = 0;
|
||||
CompareFiles(input_file_, output_file, &actual_psnr, &actual_ssim);
|
||||
CompareFiles(local_preview, remote_file, &actual_psnr, &actual_ssim);
|
||||
|
||||
TearDownFileRenderers();
|
||||
|
||||
if (actual_psnr >= kExpectedMinimumPSNR &&
|
||||
actual_ssim >= kExpectedMinimumSSIM) {
|
||||
// Test succeeded!
|
||||
if (actual_psnr == webrtc::test::kMetricsInfinitePSNR &&
|
||||
actual_ssim == 1.0f) {
|
||||
// Test successful.
|
||||
return;
|
||||
} else {
|
||||
ViETest::Log("Retrying; attempt %d of %d.", attempt + 1, kNumAttempts);
|
||||
}
|
||||
}
|
||||
|
||||
ADD_FAILURE() << "Failed to achieve PSNR " << kExpectedMinimumPSNR <<
|
||||
" and SSIM " << kExpectedMinimumSSIM << " after " <<
|
||||
kVerifyingTestMaxNumAttempts << " attempts.";
|
||||
FAIL() << "Failed to achieve perfect PSNR and SSIM results after " <<
|
||||
kNumAttempts << " attempts.";
|
||||
}
|
||||
|
||||
// Runs a whole stack processing with tracking of which frames are dropped
|
||||
|
@ -8,11 +8,36 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "base_primitives.h"
|
||||
#include "webrtc/video_engine/test/auto_test/primitives/base_primitives.h"
|
||||
|
||||
#include "vie_autotest.h"
|
||||
#include "vie_autotest_defines.h"
|
||||
#include "webrtc/modules/video_capture/include/video_capture_factory.h"
|
||||
#include "webrtc/video_engine/test/auto_test/interface/vie_autotest.h"
|
||||
#include "webrtc/video_engine/test/auto_test/interface/vie_autotest_defines.h"
|
||||
#include "webrtc/video_engine/test/libvietest/include/tb_external_transport.h"
|
||||
|
||||
static void ConfigureCodecsToI420(int video_channel,
|
||||
webrtc::VideoCodec video_codec,
|
||||
webrtc::ViECodec* codec_interface) {
|
||||
// Set up the codec interface with all known receive codecs and with
|
||||
// I420 as the send codec.
|
||||
for (int i = 0; i < codec_interface->NumberOfCodecs(); i++) {
|
||||
EXPECT_EQ(0, codec_interface->GetCodec(i, video_codec));
|
||||
|
||||
// Try to keep the test frame size small and bit rate generous when I420.
|
||||
if (video_codec.codecType == webrtc::kVideoCodecI420) {
|
||||
video_codec.width = 176;
|
||||
video_codec.height = 144;
|
||||
video_codec.maxBitrate = 32000;
|
||||
video_codec.startBitrate = 32000;
|
||||
EXPECT_EQ(0, codec_interface->SetSendCodec(video_channel, video_codec));
|
||||
}
|
||||
|
||||
EXPECT_EQ(0, codec_interface->SetReceiveCodec(video_channel, video_codec));
|
||||
}
|
||||
// Verify that we really found the I420 codec.
|
||||
EXPECT_EQ(0, codec_interface->GetSendCodec(video_channel, video_codec));
|
||||
EXPECT_EQ(webrtc::kVideoCodecI420, video_codec.codecType);
|
||||
}
|
||||
|
||||
void TestI420CallSetup(webrtc::ViECodec* codec_interface,
|
||||
webrtc::VideoEngine* video_engine,
|
||||
@ -23,45 +48,26 @@ void TestI420CallSetup(webrtc::ViECodec* codec_interface,
|
||||
webrtc::VideoCodec video_codec;
|
||||
memset(&video_codec, 0, sizeof(webrtc::VideoCodec));
|
||||
|
||||
// Set up the codec interface with all known receive codecs and with
|
||||
// I420 as the send codec.
|
||||
for (int i = 0; i < codec_interface->NumberOfCodecs(); i++) {
|
||||
EXPECT_EQ(0, codec_interface->GetCodec(i, video_codec));
|
||||
ConfigureCodecsToI420(video_channel, video_codec, codec_interface);
|
||||
|
||||
// Try to keep the test frame size small when I420.
|
||||
if (video_codec.codecType == webrtc::kVideoCodecI420) {
|
||||
video_codec.width = 176;
|
||||
video_codec.height = 144;
|
||||
EXPECT_EQ(0, codec_interface->SetSendCodec(video_channel, video_codec));
|
||||
}
|
||||
|
||||
EXPECT_EQ(0, codec_interface->SetReceiveCodec(video_channel, video_codec));
|
||||
}
|
||||
|
||||
// Verify that we really found the I420 codec.
|
||||
EXPECT_EQ(0, codec_interface->GetSendCodec(video_channel, video_codec));
|
||||
EXPECT_EQ(webrtc::kVideoCodecI420, video_codec.codecType);
|
||||
|
||||
// Set up senders and receivers.
|
||||
char version[1024] = "";
|
||||
EXPECT_EQ(0, base_interface->GetVersion(version));
|
||||
ViETest::Log("\nUsing WebRTC Video Engine version: %s", version);
|
||||
|
||||
const char *ipAddress = "127.0.0.1";
|
||||
WebRtc_UWord16 rtpPortListen = 6100;
|
||||
WebRtc_UWord16 rtpPortSend = 6100;
|
||||
EXPECT_EQ(0, network_interface->SetLocalReceiver(video_channel,
|
||||
rtpPortListen));
|
||||
TbExternalTransport external_transport(
|
||||
*network_interface, video_channel, NULL);
|
||||
EXPECT_EQ(0, network_interface->RegisterSendTransport(
|
||||
video_channel, external_transport));
|
||||
EXPECT_EQ(0, base_interface->StartReceive(video_channel));
|
||||
EXPECT_EQ(0, network_interface->SetSendDestination(video_channel, ipAddress,
|
||||
rtpPortSend));
|
||||
EXPECT_EQ(0, base_interface->StartSend(video_channel));
|
||||
|
||||
// Call started.
|
||||
// Let the call run for a while.
|
||||
ViETest::Log("Call started");
|
||||
|
||||
AutoTestSleep(KAutoTestSleepTimeMs);
|
||||
|
||||
// Done.
|
||||
// Stop the call.
|
||||
ViETest::Log("Stopping call.");
|
||||
EXPECT_EQ(0, base_interface->StopSend(video_channel));
|
||||
|
||||
// Make sure we receive all packets.
|
||||
AutoTestSleep(1000);
|
||||
|
||||
EXPECT_EQ(0, base_interface->StopReceive(video_channel));
|
||||
EXPECT_EQ(0, network_interface->DeregisterSendTransport(video_channel));
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "video_engine/test/auto_test/primitives/general_primitives.h"
|
||||
#include "video_engine/test/libvietest/include/tb_interfaces.h"
|
||||
#include "video_engine/test/libvietest/include/tb_external_transport.h"
|
||||
#include "video_engine/test/libvietest/include/vie_external_render_filter.h"
|
||||
#include "video_engine/test/libvietest/include/vie_to_file_renderer.h"
|
||||
|
||||
enum { kWaitTimeForFinalDecodeMs = 100 };
|
||||
@ -29,34 +30,22 @@ enum { kWaitTimeForFinalDecodeMs = 100 };
|
||||
// Writes the frames to be encoded to file and tracks which frames are sent in
|
||||
// external transport on the local side and reports them to the
|
||||
// FrameDropDetector class.
|
||||
class LocalRendererEffectFilter : public webrtc::ViEEffectFilter {
|
||||
class LocalRendererEffectFilter : public webrtc::ExternalRendererEffectFilter {
|
||||
public:
|
||||
explicit LocalRendererEffectFilter(FrameDropDetector* frame_drop_detector,
|
||||
webrtc::ExternalRenderer* renderer)
|
||||
: width_(0), height_(0), frame_drop_detector_(frame_drop_detector),
|
||||
renderer_(renderer) {}
|
||||
virtual ~LocalRendererEffectFilter() {}
|
||||
virtual int Transform(int size, unsigned char* frameBuffer,
|
||||
unsigned int timeStamp90KHz, unsigned int width,
|
||||
unsigned int height) {
|
||||
if (width != width_ || height_ != height) {
|
||||
renderer_->FrameSizeChange(width, height, 1);
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
}
|
||||
LocalRendererEffectFilter(webrtc::ExternalRenderer* renderer,
|
||||
FrameDropDetector* frame_drop_detector)
|
||||
: ExternalRendererEffectFilter(renderer),
|
||||
frame_drop_detector_(frame_drop_detector) {}
|
||||
int Transform(int size, unsigned char* frameBuffer,
|
||||
unsigned int timeStamp90KHz, unsigned int width,
|
||||
unsigned int height) {
|
||||
frame_drop_detector_->ReportFrameState(FrameDropDetector::kCreated,
|
||||
timeStamp90KHz);
|
||||
return renderer_->DeliverFrame(frameBuffer,
|
||||
size,
|
||||
timeStamp90KHz,
|
||||
webrtc::TickTime::MillisecondTimestamp());
|
||||
return webrtc::ExternalRendererEffectFilter::Transform(
|
||||
size, frameBuffer, timeStamp90KHz, width, height);
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned int width_;
|
||||
unsigned int height_;
|
||||
FrameDropDetector* frame_drop_detector_;
|
||||
webrtc::ExternalRenderer* renderer_;
|
||||
};
|
||||
|
||||
// Tracks which frames are sent in external transport on the local side
|
||||
@ -175,8 +164,8 @@ void TestFullStack(const TbInterfaces& interfaces,
|
||||
// Setup the effect filters.
|
||||
// Local rendering at the send-side is done in an effect filter to avoid
|
||||
// synchronization issues with the remote renderer.
|
||||
LocalRendererEffectFilter local_renderer_filter(frame_drop_detector,
|
||||
local_file_renderer);
|
||||
LocalRendererEffectFilter local_renderer_filter(local_file_renderer,
|
||||
frame_drop_detector);
|
||||
EXPECT_EQ(0, image_process->RegisterSendEffectFilter(video_channel,
|
||||
local_renderer_filter));
|
||||
DecodedTimestampEffectFilter decode_filter(frame_drop_detector);
|
||||
|
@ -73,15 +73,6 @@ void RenderToFile(webrtc::ViERender* renderer_interface,
|
||||
EXPECT_EQ(0, renderer_interface->StartRender(frame_provider_id));
|
||||
}
|
||||
|
||||
void StopAndRemoveRenderers(webrtc::ViEBase* base_interface,
|
||||
webrtc::ViERender* render_interface,
|
||||
int channel_id,
|
||||
int capture_id) {
|
||||
EXPECT_EQ(0, render_interface->StopRender(channel_id));
|
||||
EXPECT_EQ(0, render_interface->RemoveRenderer(channel_id));
|
||||
EXPECT_EQ(0, render_interface->RemoveRenderer(capture_id));
|
||||
}
|
||||
|
||||
void ConfigureRtpRtcp(webrtc::ViERTP_RTCP* rtcp_interface,
|
||||
int video_channel) {
|
||||
EXPECT_EQ(0, rtcp_interface->SetRTCPStatus(video_channel,
|
||||
|
@ -55,13 +55,6 @@ void RenderToFile(webrtc::ViERender* renderer_interface,
|
||||
int frame_provider_id,
|
||||
ViEToFileRenderer* to_file_renderer);
|
||||
|
||||
// Stops all rendering given the normal case that we have a capture device
|
||||
// and a video channel set up for rendering.
|
||||
void StopAndRemoveRenderers(webrtc::ViEBase* base_interface,
|
||||
webrtc::ViERender* render_interface,
|
||||
int channel_id,
|
||||
int capture_id);
|
||||
|
||||
// Configures RTP-RTCP.
|
||||
void ConfigureRtpRtcp(webrtc::ViERTP_RTCP* rtcp_interface,
|
||||
int video_channel);
|
||||
|
@ -75,8 +75,9 @@ void ViEAutoTest::ViEBaseStandardTest() {
|
||||
EXPECT_EQ(0, capture_interface->StopCapture(capture_id));
|
||||
EXPECT_EQ(0, base_interface->StopReceive(video_channel));
|
||||
|
||||
StopAndRemoveRenderers(base_interface, render_interface, video_channel,
|
||||
capture_id);
|
||||
EXPECT_EQ(0, render_interface->StopRender(video_channel));
|
||||
EXPECT_EQ(0, render_interface->RemoveRenderer(video_channel));
|
||||
EXPECT_EQ(0, render_interface->RemoveRenderer(capture_id));
|
||||
|
||||
EXPECT_EQ(0, render_interface->DeRegisterVideoRenderModule(*_vrm1));
|
||||
EXPECT_EQ(0, render_interface->DeRegisterVideoRenderModule(*_vrm2));
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "video_engine/test/auto_test/primitives/framedrop_primitives.h"
|
||||
#include "video_engine/test/auto_test/primitives/general_primitives.h"
|
||||
#include "video_engine/test/libvietest/include/tb_interfaces.h"
|
||||
#include "video_engine/test/libvietest/include/vie_external_render_filter.h"
|
||||
#include "video_engine/test/libvietest/include/vie_fake_camera.h"
|
||||
#include "video_engine/test/libvietest/include/vie_to_file_renderer.h"
|
||||
|
||||
@ -48,11 +49,18 @@ bool ViEFileBasedComparisonTests::TestCallSetup(
|
||||
|
||||
ConfigureRtpRtcp(interfaces.rtp_rtcp, video_channel);
|
||||
|
||||
webrtc::ViERender *render_interface = interfaces.render;
|
||||
webrtc::ViERender* render_interface = interfaces.render;
|
||||
webrtc::ViEImageProcess* image_process = interfaces.image_process;
|
||||
|
||||
RenderToFile(render_interface, capture_id, local_file_renderer);
|
||||
RenderToFile(render_interface, video_channel, remote_file_renderer);
|
||||
|
||||
// We make a special hookup of the local renderer to use an effect filter
|
||||
// instead of using the render interface for the capture device. This way
|
||||
// we will only render frames that actually get sent.
|
||||
webrtc::ExternalRendererEffectFilter renderer_filter(local_file_renderer);
|
||||
EXPECT_EQ(0, image_process->RegisterSendEffectFilter(video_channel,
|
||||
renderer_filter));
|
||||
|
||||
// Run the test itself:
|
||||
const char* device_name = "Fake Capture Device";
|
||||
|
||||
@ -60,12 +68,8 @@ bool ViEFileBasedComparisonTests::TestCallSetup(
|
||||
interfaces.base, interfaces.network, video_channel,
|
||||
device_name);
|
||||
|
||||
AutoTestSleep(KAutoTestSleepTimeMs);
|
||||
|
||||
EXPECT_EQ(0, interfaces.base->StopReceive(video_channel));
|
||||
|
||||
StopAndRemoveRenderers(interfaces.base, render_interface, video_channel,
|
||||
capture_id);
|
||||
EXPECT_EQ(0, render_interface->StopRender(video_channel));
|
||||
EXPECT_EQ(0, render_interface->RemoveRenderer(video_channel));
|
||||
|
||||
interfaces.capture->DisconnectCaptureDevice(video_channel);
|
||||
|
||||
@ -74,6 +78,7 @@ bool ViEFileBasedComparisonTests::TestCallSetup(
|
||||
// tests that the system doesn't mind that the external capture device sends
|
||||
// data after rendering has been stopped.
|
||||
fake_camera.StopCamera();
|
||||
EXPECT_EQ(0, image_process->DeregisterSendEffectFilter(video_channel));
|
||||
|
||||
EXPECT_EQ(0, interfaces.base->DeleteChannel(video_channel));
|
||||
return true;
|
||||
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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 WEBRTC_VIDEO_ENGINE_TEST_LIBVIETEST_INCLUDE_VIE_EXTERNAL_RENDER_H_
|
||||
#define WEBRTC_VIDEO_ENGINE_TEST_LIBVIETEST_INCLUDE_VIE_EXTERNAL_RENDER_H_
|
||||
|
||||
#include "webrtc/system_wrappers/interface/tick_util.h"
|
||||
#include "webrtc/video_engine/include/vie_render.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// A render filter which passes frames directly to an external renderer. This
|
||||
// is different from plugging the external renderer directly into the sending
|
||||
// side since this will only run on frames that actually get sent and not on
|
||||
// frames that only get captured.
|
||||
class ExternalRendererEffectFilter : public webrtc::ViEEffectFilter {
|
||||
public:
|
||||
explicit ExternalRendererEffectFilter(webrtc::ExternalRenderer* renderer)
|
||||
: width_(0), height_(0), renderer_(renderer) {}
|
||||
virtual ~ExternalRendererEffectFilter() {}
|
||||
virtual int Transform(int size, unsigned char* frame_buffer,
|
||||
unsigned int time_stamp90KHz, unsigned int width,
|
||||
unsigned int height) {
|
||||
if (width != width_ || height_ != height) {
|
||||
renderer_->FrameSizeChange(width, height, 1);
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
}
|
||||
return renderer_->DeliverFrame(frame_buffer,
|
||||
size,
|
||||
time_stamp90KHz,
|
||||
webrtc::TickTime::MillisecondTimestamp());
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned int width_;
|
||||
unsigned int height_;
|
||||
webrtc::ExternalRenderer* renderer_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_VIDEO_ENGINE_TEST_LIBVIETEST_INCLUDE_VIE_EXTERNAL_RENDER_H_
|
@ -27,6 +27,7 @@
|
||||
],
|
||||
'sources': [
|
||||
# Helper classes
|
||||
'include/vie_external_effect_filter.h',
|
||||
'include/vie_fake_camera.h',
|
||||
'include/vie_file_capture_device.h',
|
||||
'include/vie_to_file_renderer.h',
|
||||
|
Loading…
x
Reference in New Issue
Block a user