From 273ccad59db734e787a46275b4109c9025b75aea Mon Sep 17 00:00:00 2001 From: "phoglund@webrtc.org" Date: Thu, 29 Nov 2012 10:08:16 +0000 Subject: [PATCH] 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 --- .../libyuv/include/webrtc_libyuv.h | 5 ++ webrtc/common_video/libyuv/webrtc_libyuv.cc | 8 +- .../main/source/media_optimization.cc | 1 + .../test/testsupport/metrics/video_metrics.cc | 3 + .../test/testsupport/metrics/video_metrics.h | 19 +++-- .../automated/vie_video_verification_test.cc | 43 +++++----- .../auto_test/primitives/base_primitives.cc | 78 ++++++++++--------- .../primitives/framedrop_primitives.cc | 37 ++++----- .../primitives/general_primitives.cc | 9 --- .../auto_test/primitives/general_primitives.h | 7 -- .../auto_test/source/vie_autotest_base.cc | 5 +- .../source/vie_file_based_comparison_tests.cc | 21 +++-- .../include/vie_external_render_filter.h | 49 ++++++++++++ .../test/libvietest/libvietest.gypi | 1 + 14 files changed, 169 insertions(+), 117 deletions(-) create mode 100644 webrtc/video_engine/test/libvietest/include/vie_external_render_filter.h diff --git a/webrtc/common_video/libyuv/include/webrtc_libyuv.h b/webrtc/common_video/libyuv/include/webrtc_libyuv.h index c6a0046ac..777e7c72d 100644 --- a/webrtc/common_video/libyuv/include/webrtc_libyuv.h +++ b/webrtc/common_video/libyuv/include/webrtc_libyuv.h @@ -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); diff --git a/webrtc/common_video/libyuv/webrtc_libyuv.cc b/webrtc/common_video/libyuv/webrtc_libyuv.cc index 004de5386..fdef25530 100644 --- a/webrtc/common_video/libyuv/webrtc_libyuv.cc +++ b/webrtc/common_video/libyuv/webrtc_libyuv.cc @@ -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, diff --git a/webrtc/modules/video_coding/main/source/media_optimization.cc b/webrtc/modules/video_coding/main/source/media_optimization.cc index 48b7b4761..8dd47fc7c 100644 --- a/webrtc/modules/video_coding/main/source/media_optimization.cc +++ b/webrtc/modules/video_coding/main/source/media_optimization.cc @@ -249,6 +249,7 @@ VCMMediaOptimization::DropFrame() { // leak appropriate number of bytes _frameDropper->Leak((WebRtc_UWord32)(InputFrameRate() + 0.5f)); + return _frameDropper->DropFrame(); } diff --git a/webrtc/test/testsupport/metrics/video_metrics.cc b/webrtc/test/testsupport/metrics/video_metrics.cc index ddd31c46d..c9d6d9dcc 100644 --- a/webrtc/test/testsupport/metrics/video_metrics.cc +++ b/webrtc/test/testsupport/metrics/video_metrics.cc @@ -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) { diff --git a/webrtc/test/testsupport/metrics/video_metrics.h b/webrtc/test/testsupport/metrics/video_metrics.h index df11a49db..36e62a076 100644 --- a/webrtc/test/testsupport/metrics/video_metrics.h +++ b/webrtc/test/testsupport/metrics/video_metrics.h @@ -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: diff --git a/webrtc/video_engine/test/auto_test/automated/vie_video_verification_test.cc b/webrtc/video_engine/test/auto_test/automated/vie_video_verification_test.cc index f5237c0a1..fbe97aa4b 100644 --- a/webrtc/video_engine/test/auto_test/automated/vie_video_verification_test.cc +++ b/webrtc/video_engine/test/auto_test/automated/vie_video_verification_test.cc @@ -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 diff --git a/webrtc/video_engine/test/auto_test/primitives/base_primitives.cc b/webrtc/video_engine/test/auto_test/primitives/base_primitives.cc index a8e2da3aa..317a850fc 100644 --- a/webrtc/video_engine/test/auto_test/primitives/base_primitives.cc +++ b/webrtc/video_engine/test/auto_test/primitives/base_primitives.cc @@ -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)); } diff --git a/webrtc/video_engine/test/auto_test/primitives/framedrop_primitives.cc b/webrtc/video_engine/test/auto_test/primitives/framedrop_primitives.cc index f75911851..321c74c45 100644 --- a/webrtc/video_engine/test/auto_test/primitives/framedrop_primitives.cc +++ b/webrtc/video_engine/test/auto_test/primitives/framedrop_primitives.cc @@ -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); diff --git a/webrtc/video_engine/test/auto_test/primitives/general_primitives.cc b/webrtc/video_engine/test/auto_test/primitives/general_primitives.cc index 5ef2aa648..8d6089ff5 100644 --- a/webrtc/video_engine/test/auto_test/primitives/general_primitives.cc +++ b/webrtc/video_engine/test/auto_test/primitives/general_primitives.cc @@ -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, diff --git a/webrtc/video_engine/test/auto_test/primitives/general_primitives.h b/webrtc/video_engine/test/auto_test/primitives/general_primitives.h index 7c1740d7a..3ef8d85df 100644 --- a/webrtc/video_engine/test/auto_test/primitives/general_primitives.h +++ b/webrtc/video_engine/test/auto_test/primitives/general_primitives.h @@ -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); diff --git a/webrtc/video_engine/test/auto_test/source/vie_autotest_base.cc b/webrtc/video_engine/test/auto_test/source/vie_autotest_base.cc index 4a7437a96..28a20290e 100644 --- a/webrtc/video_engine/test/auto_test/source/vie_autotest_base.cc +++ b/webrtc/video_engine/test/auto_test/source/vie_autotest_base.cc @@ -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)); diff --git a/webrtc/video_engine/test/auto_test/source/vie_file_based_comparison_tests.cc b/webrtc/video_engine/test/auto_test/source/vie_file_based_comparison_tests.cc index d32223603..7fcc69335 100644 --- a/webrtc/video_engine/test/auto_test/source/vie_file_based_comparison_tests.cc +++ b/webrtc/video_engine/test/auto_test/source/vie_file_based_comparison_tests.cc @@ -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; diff --git a/webrtc/video_engine/test/libvietest/include/vie_external_render_filter.h b/webrtc/video_engine/test/libvietest/include/vie_external_render_filter.h new file mode 100644 index 000000000..a1aeb4c94 --- /dev/null +++ b/webrtc/video_engine/test/libvietest/include/vie_external_render_filter.h @@ -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_ diff --git a/webrtc/video_engine/test/libvietest/libvietest.gypi b/webrtc/video_engine/test/libvietest/libvietest.gypi index 562bdbeb4..c8a84ad04 100644 --- a/webrtc/video_engine/test/libvietest/libvietest.gypi +++ b/webrtc/video_engine/test/libvietest/libvietest.gypi @@ -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',