1/*
2 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11//
12// vie_autotest_render.cc
13//
14
15#include "webrtc/engine_configurations.h"
16#include "webrtc/video_engine/test/auto_test/interface/vie_autotest.h"
17#include "webrtc/video_engine/test/auto_test/interface/vie_autotest_defines.h"
18
19#include "webrtc/modules/video_render/include/video_render.h"
20
21#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
22#include "webrtc/video_engine/test/libvietest/include/tb_capture_device.h"
23#include "webrtc/video_engine/test/libvietest/include/tb_interfaces.h"
24#include "webrtc/video_engine/test/libvietest/include/tb_video_channel.h"
25
26#if defined(WIN32)
27#include <ddraw.h>
28#include <tchar.h>
29#include <windows.h>
30#elif defined(WEBRTC_LINUX)
31    //From windgi.h
32    #undef RGB
33    #define RGB(r,g,b)          ((unsigned long)(((unsigned char)(r)|((unsigned short)((unsigned char)(g))<<8))|(((unsigned long)(unsigned char)(b))<<16)))
34    //From ddraw.h
35/*    typedef struct _DDCOLORKEY
36 {
37 DWORD       dwColorSpaceLowValue;   // low boundary of color space that is to
38 DWORD       dwColorSpaceHighValue;  // high boundary of color space that is
39 } DDCOLORKEY;*/
40#elif defined(WEBRTC_MAC)
41#endif
42
43class ViEAutoTestExternalRenderer: public webrtc::ExternalRenderer
44{
45public:
46    ViEAutoTestExternalRenderer() :
47        _width(0),
48        _height(0)
49    {
50    }
51    virtual int FrameSizeChange(unsigned int width, unsigned int height,
52                                unsigned int numberOfStreams)
53    {
54        _width = width;
55        _height = height;
56        return 0;
57    }
58
59    virtual int DeliverFrame(unsigned char* buffer,
60                             int bufferSize,
61                             uint32_t time_stamp,
62                             int64_t ntp_time_ms,
63                             int64_t render_time,
64                             void* /*handle*/) {
65      if (bufferSize != CalcBufferSize(webrtc::kI420, _width, _height)) {
66        ViETest::Log("Incorrect render buffer received, of length = %d\n",
67                     bufferSize);
68        return 0;
69      }
70      return 0;
71    }
72
73    virtual bool IsTextureSupported() { return false; }
74
75public:
76    virtual ~ViEAutoTestExternalRenderer()
77    {
78    }
79private:
80    int _width, _height;
81};
82
83void ViEAutoTest::ViERenderStandardTest()
84{
85    //***************************************************************
86    //	Begin create/initialize WebRTC Video Engine for testing
87    //***************************************************************
88    int rtpPort = 6000;
89
90    TbInterfaces ViE("ViERenderStandardTest");
91
92    // Create a video channel
93    TbVideoChannel tbChannel(ViE, webrtc::kVideoCodecVP8);
94    TbCaptureDevice tbCapture(ViE); // Create a capture device
95    tbCapture.ConnectTo(tbChannel.videoChannel);
96    tbChannel.StartReceive(rtpPort);
97    tbChannel.StartSend(rtpPort);
98
99    EXPECT_EQ(0, ViE.render->RegisterVideoRenderModule(*_vrm1));
100    EXPECT_EQ(0, ViE.render->AddRenderer(
101        tbCapture.captureId, _window1, 0, 0.0, 0.0, 1.0, 1.0));
102    EXPECT_EQ(0, ViE.render->StartRender(tbCapture.captureId));
103    EXPECT_EQ(0, ViE.render->RegisterVideoRenderModule(*_vrm2));
104    EXPECT_EQ(0, ViE.render->AddRenderer(
105        tbChannel.videoChannel, _window2, 1, 0.0, 0.0, 1.0, 1.0));
106    EXPECT_EQ(0, ViE.render->StartRender(tbChannel.videoChannel));
107
108    ViETest::Log("\nCapture device is renderered in Window 1");
109    ViETest::Log("Remote stream is renderered in Window 2");
110    AutoTestSleep(kAutoTestSleepTimeMs);
111
112    EXPECT_EQ(0, ViE.render->StopRender(tbCapture.captureId));
113    EXPECT_EQ(0, ViE.render->RemoveRenderer(tbCapture.captureId));
114
115    // PIP and full screen rendering is not supported on Android
116#ifndef WEBRTC_ANDROID
117    EXPECT_EQ(0, ViE.render->DeRegisterVideoRenderModule(*_vrm1));
118    EXPECT_EQ(0, ViE.render->AddRenderer(
119        tbCapture.captureId, _window2, 0, 0.75, 0.75, 1.0, 1.0));
120    EXPECT_EQ(0, ViE.render->StartRender(tbCapture.captureId));
121
122    ViETest::Log("\nCapture device is now rendered in Window 2, PiP.");
123    ViETest::Log("Switching to full screen rendering in %d seconds.\n",
124                 kAutoTestSleepTimeMs / 1000);
125    AutoTestSleep(kAutoTestSleepTimeMs);
126
127    EXPECT_EQ(0, ViE.render->RemoveRenderer(tbCapture.captureId));
128    EXPECT_EQ(0, ViE.render->RemoveRenderer(tbChannel.videoChannel));
129    EXPECT_EQ(0, ViE.render->DeRegisterVideoRenderModule(*_vrm2));
130
131    // Destroy render module and create new in full screen mode
132    webrtc::VideoRender::DestroyVideoRender(_vrm1);
133    _vrm1 = NULL;
134    _vrm1 = webrtc::VideoRender::CreateVideoRender(
135        4563, _window1, true, _renderType);
136    EXPECT_TRUE(_vrm1 != NULL);
137
138    EXPECT_EQ(0, ViE.render->RegisterVideoRenderModule(*_vrm1));
139    EXPECT_EQ(0, ViE.render->AddRenderer(
140        tbCapture.captureId, _window1, 0, 0.75f, 0.75f, 1.0f, 1.0f));
141    EXPECT_EQ(0, ViE.render->StartRender(tbCapture.captureId));
142    EXPECT_EQ(0, ViE.render->AddRenderer(
143        tbChannel.videoChannel, _window1, 1, 0.0, 0.0, 1.0, 1.0));
144    EXPECT_EQ(0, ViE.render->StartRender(tbChannel.videoChannel));
145
146    AutoTestSleep(kAutoTestSleepTimeMs);
147
148    EXPECT_EQ(0, ViE.render->RemoveRenderer(tbCapture.captureId));
149
150    EXPECT_EQ(0, ViE.render->RemoveRenderer(tbChannel.videoChannel));
151    EXPECT_EQ(0, ViE.render->DeRegisterVideoRenderModule(*_vrm1));
152
153    // Destroy full screen render module and create new in normal mode
154    webrtc::VideoRender::DestroyVideoRender(_vrm1);
155    _vrm1 = NULL;
156    _vrm1 = webrtc::VideoRender::CreateVideoRender(
157        4561, _window1, false, _renderType);
158    EXPECT_TRUE(_vrm1 != NULL);
159#endif
160
161    //***************************************************************
162    //	Engine ready. Begin testing class
163    //***************************************************************
164
165
166    //***************************************************************
167    //	Testing finished. Tear down Video Engine
168    //***************************************************************
169    tbCapture.Disconnect(tbChannel.videoChannel);
170}
171
172void ViEAutoTest::ViERenderExtendedTest()
173{
174    int rtpPort = 6000;
175
176    TbInterfaces ViE("ViERenderExtendedTest");
177
178    // Create a video channel
179    TbVideoChannel tbChannel(ViE, webrtc::kVideoCodecVP8);
180    TbCaptureDevice tbCapture(ViE); // Create a capture device
181    tbCapture.ConnectTo(tbChannel.videoChannel);
182    tbChannel.StartReceive(rtpPort);
183    tbChannel.StartSend(rtpPort);
184
185    EXPECT_EQ(0, ViE.render->RegisterVideoRenderModule(*_vrm1));
186    EXPECT_EQ(0, ViE.render->AddRenderer(
187        tbCapture.captureId, _window1, 0, 0.0, 0.0, 1.0, 1.0));
188    EXPECT_EQ(0, ViE.render->StartRender(tbCapture.captureId));
189    EXPECT_EQ(0, ViE.render->RegisterVideoRenderModule(*_vrm2));
190    EXPECT_EQ(0, ViE.render->AddRenderer(
191        tbChannel.videoChannel, _window2, 1, 0.0, 0.0, 1.0, 1.0));
192    EXPECT_EQ(0, ViE.render->StartRender(tbChannel.videoChannel));
193
194    ViETest::Log("\nCapture device is renderered in Window 1");
195    ViETest::Log("Remote stream is renderered in Window 2");
196    AutoTestSleep(kAutoTestSleepTimeMs);
197
198#ifdef _WIN32
199    ViETest::Log("\nConfiguring Window2");
200    ViETest::Log("you will see video only in first quadrant");
201    EXPECT_EQ(0, ViE.render->ConfigureRender(
202        tbChannel.videoChannel, 0, 0.0f, 0.0f, 0.5f, 0.5f));
203    AutoTestSleep(kAutoTestSleepTimeMs);
204
205    ViETest::Log("you will see video only in fourth quadrant");
206    EXPECT_EQ(0, ViE.render->ConfigureRender(
207        tbChannel.videoChannel, 0, 0.5f, 0.5f, 1.0f, 1.0f));
208    AutoTestSleep(kAutoTestSleepTimeMs);
209
210    ViETest::Log("normal video on Window2");
211    EXPECT_EQ(0, ViE.render->ConfigureRender(
212        tbChannel.videoChannel, 0, 0.0f, 0.0f, 1.0f, 1.0f));
213    AutoTestSleep(kAutoTestSleepTimeMs);
214#endif
215
216    ViETest::Log("Mirroring Local Preview (Window1) Left-Right");
217    EXPECT_EQ(0, ViE.render->MirrorRenderStream(
218        tbCapture.captureId, true, false, true));
219    AutoTestSleep(kAutoTestSleepTimeMs);
220
221    ViETest::Log("\nMirroring Local Preview (Window1) Left-Right and Up-Down");
222    EXPECT_EQ(0, ViE.render->MirrorRenderStream(
223        tbCapture.captureId, true, true, true));
224    AutoTestSleep(kAutoTestSleepTimeMs);
225
226    ViETest::Log("\nMirroring Remote Window(Window2) Up-Down");
227    EXPECT_EQ(0, ViE.render->MirrorRenderStream(
228        tbChannel.videoChannel, true, true, false));
229    AutoTestSleep(kAutoTestSleepTimeMs);
230
231    ViETest::Log("Disabling Mirroing on Window1 and Window2");
232    EXPECT_EQ(0, ViE.render->MirrorRenderStream(
233        tbCapture.captureId, false, false, false));
234    AutoTestSleep(kAutoTestSleepTimeMs);
235    EXPECT_EQ(0, ViE.render->MirrorRenderStream(
236        tbChannel.videoChannel, false, false, false));
237    AutoTestSleep(kAutoTestSleepTimeMs);
238
239    ViETest::Log("\nEnabling Full Screen render in 5 sec");
240
241    EXPECT_EQ(0, ViE.render->RemoveRenderer(tbCapture.captureId));
242    EXPECT_EQ(0, ViE.render->DeRegisterVideoRenderModule(*_vrm1));
243    EXPECT_EQ(0, ViE.render->RemoveRenderer(tbChannel.videoChannel));
244    EXPECT_EQ(0, ViE.render->DeRegisterVideoRenderModule(*_vrm2));
245
246    // Destroy render module and create new in full screen mode
247    webrtc::VideoRender::DestroyVideoRender(_vrm1);
248    _vrm1 = NULL;
249    _vrm1 = webrtc::VideoRender::CreateVideoRender(
250        4563, _window1, true, _renderType);
251    EXPECT_TRUE(_vrm1 != NULL);
252
253    EXPECT_EQ(0, ViE.render->RegisterVideoRenderModule(*_vrm1));
254    EXPECT_EQ(0, ViE.render->AddRenderer(
255        tbCapture.captureId, _window1, 0, 0.0f, 0.0f, 1.0f, 1.0f));
256    EXPECT_EQ(0, ViE.render->StartRender(tbCapture.captureId));
257    AutoTestSleep(kAutoTestSleepTimeMs);
258
259    ViETest::Log("\nStop renderer");
260    EXPECT_EQ(0, ViE.render->StopRender(tbCapture.captureId));
261    ViETest::Log("\nRemove renderer");
262    EXPECT_EQ(0, ViE.render->RemoveRenderer(tbCapture.captureId));
263
264    EXPECT_EQ(0, ViE.render->DeRegisterVideoRenderModule(*_vrm1));
265
266    // Destroy full screen render module and create new for external rendering
267    webrtc::VideoRender::DestroyVideoRender(_vrm1);
268    _vrm1 = NULL;
269    _vrm1 = webrtc::VideoRender::CreateVideoRender(4564, NULL, false,
270                                                   _renderType);
271    EXPECT_TRUE(_vrm1 != NULL);
272
273    EXPECT_EQ(0, ViE.render->RegisterVideoRenderModule(*_vrm1));
274
275    ViETest::Log("\nExternal Render Test");
276    ViEAutoTestExternalRenderer externalRenderObj;
277    EXPECT_EQ(0, ViE.render->AddRenderer(
278        tbCapture.captureId, webrtc::kVideoI420, &externalRenderObj));
279    EXPECT_EQ(0, ViE.render->StartRender(tbCapture.captureId));
280    AutoTestSleep(kAutoTestSleepTimeMs);
281
282    EXPECT_EQ(0, ViE.render->StopRender(tbCapture.captureId));
283    EXPECT_EQ(0, ViE.render->RemoveRenderer(tbCapture.captureId));
284    EXPECT_EQ(0, ViE.render->DeRegisterVideoRenderModule(*_vrm1));
285
286    // Destroy render module for external rendering and create new in normal
287    // mode
288    webrtc::VideoRender::DestroyVideoRender(_vrm1);
289    _vrm1 = NULL;
290    _vrm1 = webrtc::VideoRender::CreateVideoRender(
291        4561, _window1, false, _renderType);
292    EXPECT_TRUE(_vrm1 != NULL);
293    tbCapture.Disconnect(tbChannel.videoChannel);
294}
295
296void ViEAutoTest::ViERenderAPITest() {
297  TbInterfaces ViE("ViERenderAPITest");
298
299  TbVideoChannel tbChannel(ViE, webrtc::kVideoCodecVP8);
300  TbCaptureDevice tbCapture(ViE);
301  tbCapture.ConnectTo(tbChannel.videoChannel);
302  tbChannel.StartReceive();
303  tbChannel.StartSend();
304
305  EXPECT_EQ(0, ViE.render->AddRenderer(
306      tbCapture.captureId, _window1, 0, 0.0, 0.0, 1.0, 1.0));
307  EXPECT_EQ(0, ViE.render->StartRender(tbCapture.captureId));
308  EXPECT_EQ(0, ViE.render->AddRenderer(
309      tbChannel.videoChannel, _window2, 1, 0.0, 0.0, 1.0, 1.0));
310  EXPECT_EQ(0, ViE.render->StartRender(tbChannel.videoChannel));
311
312  // Test setting HW render delay.
313  // Already started.
314  EXPECT_EQ(-1, ViE.render->SetExpectedRenderDelay(tbChannel.videoChannel, 50));
315  EXPECT_EQ(0, ViE.render->StopRender(tbChannel.videoChannel));
316  // Invalid values.
317  EXPECT_EQ(-1, ViE.render->SetExpectedRenderDelay(tbChannel.videoChannel, 9));
318  EXPECT_EQ(-1, ViE.render->SetExpectedRenderDelay(tbChannel.videoChannel,
319                                                   501));
320  // Valid values.
321  EXPECT_EQ(0, ViE.render->SetExpectedRenderDelay(tbChannel.videoChannel, 11));
322  EXPECT_EQ(0, ViE.render->SetExpectedRenderDelay(tbChannel.videoChannel, 499));
323}
324