blob: 5f4fd565c6f7766938b683607afb43fa940ef480 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
leozwang@webrtc.org77fe4312012-03-06 20:59:55 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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
pbos@webrtc.org5aa3f1b2013-07-12 08:12:08 +000011#include "webrtc/modules/video_render/test/testAPI/testAPI.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
13#include <stdio.h>
14
15#if defined(_WIN32)
16#include <tchar.h>
17#include <windows.h>
18#include <cassert>
19#include <fstream>
20#include <iostream>
21#include <string>
22#include <windows.h>
23#include <ddraw.h>
24
leozwang@webrtc.org57da7182012-03-06 21:28:48 +000025#elif defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
niklase@google.com470e71d2011-07-07 08:21:25 +000026
niklase@google.com470e71d2011-07-07 08:21:25 +000027#include <X11/Xlib.h>
28#include <X11/Xutil.h>
pbos@webrtc.org5aa3f1b2013-07-12 08:12:08 +000029#include <iostream>
niklase@google.com470e71d2011-07-07 08:21:25 +000030#include <sys/time.h>
31
niklase@google.com470e71d2011-07-07 08:21:25 +000032#endif
33
pbos@webrtc.org5aa3f1b2013-07-12 08:12:08 +000034#include "webrtc/common_types.h"
35#include "webrtc/modules/interface/module_common_types.h"
36#include "webrtc/modules/utility/interface/process_thread.h"
37#include "webrtc/modules/video_render/include/video_render.h"
38#include "webrtc/modules/video_render/include/video_render_defines.h"
39#include "webrtc/system_wrappers/interface/sleep.h"
40#include "webrtc/system_wrappers/interface/tick_util.h"
41#include "webrtc/system_wrappers/interface/trace.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000042
43using namespace webrtc;
44
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +000045void GetTestVideoFrame(I420VideoFrame* frame,
pbos@webrtc.orgddf94e72013-04-10 08:09:04 +000046 uint8_t startColor);
niklase@google.com470e71d2011-07-07 08:21:25 +000047int TestSingleStream(VideoRender* renderModule);
48int TestFullscreenStream(VideoRender* &renderModule,
49 void* window,
50 const VideoRenderType videoRenderType);
51int TestBitmapText(VideoRender* renderModule);
52int TestMultipleStreams(VideoRender* renderModule);
53int TestExternalRender(VideoRender* renderModule);
54
55#define TEST_FRAME_RATE 30
56#define TEST_TIME_SECOND 5
57#define TEST_FRAME_NUM (TEST_FRAME_RATE*TEST_TIME_SECOND)
58#define TEST_STREAM0_START_COLOR 0
59#define TEST_STREAM1_START_COLOR 64
60#define TEST_STREAM2_START_COLOR 128
61#define TEST_STREAM3_START_COLOR 192
62
hta@webrtc.org626dccc2012-06-25 11:30:33 +000063#if defined(WEBRTC_LINUX)
niklase@google.com470e71d2011-07-07 08:21:25 +000064
65#define GET_TIME_IN_MS timeGetTime()
niklase@google.com470e71d2011-07-07 08:21:25 +000066
67unsigned long timeGetTime()
68{
69 struct timeval tv;
70 struct timezone tz;
71 unsigned long val;
72
73 gettimeofday(&tv, &tz);
74 val= tv.tv_sec*1000+ tv.tv_usec/1000;
75 return(val);
76}
77
andrew@webrtc.orgf3b65db2012-09-06 18:17:00 +000078#elif defined(WEBRTC_MAC)
niklase@google.com470e71d2011-07-07 08:21:25 +000079
phoglund@webrtc.org337dc682011-11-16 15:36:44 +000080#include <unistd.h>
81
niklase@google.com470e71d2011-07-07 08:21:25 +000082#define GET_TIME_IN_MS timeGetTime()
niklase@google.com470e71d2011-07-07 08:21:25 +000083
84unsigned long timeGetTime()
85{
86 return 0;
87}
88
89#else
90
91#define GET_TIME_IN_MS ::timeGetTime()
niklase@google.com470e71d2011-07-07 08:21:25 +000092
93#endif
94
95using namespace std;
96
97#if defined(_WIN32)
98LRESULT CALLBACK WebRtcWinProc( HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
99{
100 switch(uMsg)
101 {
102 case WM_DESTROY:
103 break;
104 case WM_COMMAND:
105 break;
106 }
107 return DefWindowProc(hWnd,uMsg,wParam,lParam);
108}
109
110int WebRtcCreateWindow(HWND &hwndMain,int winNum, int width, int height)
111{
112 HINSTANCE hinst = GetModuleHandle(0);
113 WNDCLASSEX wcx;
114 wcx.hInstance = hinst;
115 wcx.lpszClassName = TEXT("VideoRenderTest");
116 wcx.lpfnWndProc = (WNDPROC)WebRtcWinProc;
117 wcx.style = CS_DBLCLKS;
118 wcx.hIcon = LoadIcon (NULL, IDI_APPLICATION);
119 wcx.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
120 wcx.hCursor = LoadCursor (NULL, IDC_ARROW);
121 wcx.lpszMenuName = NULL;
122 wcx.cbSize = sizeof (WNDCLASSEX);
123 wcx.cbClsExtra = 0;
124 wcx.cbWndExtra = 0;
125 wcx.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
126
127 // Register our window class with the operating system.
128 // If there is an error, exit program.
129 if ( !RegisterClassEx (&wcx) )
130 {
131 MessageBox( 0, TEXT("Failed to register window class!"),TEXT("Error!"), MB_OK|MB_ICONERROR );
132 return 0;
133 }
134
135 // Create the main window.
136 hwndMain = CreateWindowEx(
137 0, // no extended styles
138 TEXT("VideoRenderTest"), // class name
139 TEXT("VideoRenderTest Window"), // window name
140 WS_OVERLAPPED |WS_THICKFRAME, // overlapped window
141 800, // horizontal position
142 0, // vertical position
143 width, // width
144 height, // height
145 (HWND) NULL, // no parent or owner window
146 (HMENU) NULL, // class menu used
147 hinst, // instance handle
148 NULL); // no window creation data
149
150 if (!hwndMain)
niklase@google.com470e71d2011-07-07 08:21:25 +0000151 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000152
153 // Show the window using the flag specified by the program
154 // that started the application, and send the application
155 // a WM_PAINT message.
156
157 ShowWindow(hwndMain, SW_SHOWDEFAULT);
158 UpdateWindow(hwndMain);
159 return 0;
160}
161
leozwang@webrtc.org57da7182012-03-06 21:28:48 +0000162#elif defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
niklase@google.com470e71d2011-07-07 08:21:25 +0000163
164int WebRtcCreateWindow(Window *outWindow, Display **outDisplay, int winNum, int width, int height) // unsigned char* title, int titleLength)
165
166{
167 int screen, xpos = 10, ypos = 10;
168 XEvent evnt;
169 XSetWindowAttributes xswa; // window attribute struct
170 XVisualInfo vinfo; // screen visual info struct
171 unsigned long mask; // attribute mask
172
173 // get connection handle to xserver
174 Display* _display = XOpenDisplay( NULL );
175
176 // get screen number
177 screen = DefaultScreen(_display);
178
phoglund@webrtc.org5b343ae2011-12-07 10:34:35 +0000179 // put desired visual info for the screen in vinfo
niklase@google.com470e71d2011-07-07 08:21:25 +0000180 if( XMatchVisualInfo(_display, screen, 24, TrueColor, &vinfo) != 0 )
181 {
182 //printf( "Screen visual info match!\n" );
183 }
184
phoglund@webrtc.org5b343ae2011-12-07 10:34:35 +0000185 // set window attributes
niklase@google.com470e71d2011-07-07 08:21:25 +0000186 xswa.colormap = XCreateColormap(_display, DefaultRootWindow(_display), vinfo.visual, AllocNone);
187 xswa.event_mask = StructureNotifyMask | ExposureMask;
188 xswa.background_pixel = 0;
189 xswa.border_pixel = 0;
190
191 // value mask for attributes
192 mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
193
194 switch( winNum )
195 {
196 case 0:
197 xpos = 200;
198 ypos = 200;
199 break;
200 case 1:
201 xpos = 300;
202 ypos = 200;
203 break;
204 default:
205 break;
206 }
207
208 // create a subwindow for parent (defroot)
209 Window _window = XCreateWindow(_display, DefaultRootWindow(_display),
210 xpos, ypos,
211 width,
212 height,
213 0, vinfo.depth,
214 InputOutput,
215 vinfo.visual,
216 mask, &xswa);
217
218 // Set window name
219 if( winNum == 0 )
220 {
221 XStoreName(_display, _window, "VE MM Local Window");
222 XSetIconName(_display, _window, "VE MM Local Window");
223 }
224 else if( winNum == 1 )
225 {
226 XStoreName(_display, _window, "VE MM Remote Window");
227 XSetIconName(_display, _window, "VE MM Remote Window");
228 }
229
phoglund@webrtc.org5b343ae2011-12-07 10:34:35 +0000230 // make x report events for mask
niklase@google.com470e71d2011-07-07 08:21:25 +0000231 XSelectInput(_display, _window, StructureNotifyMask);
232
233 // map the window to the display
234 XMapWindow(_display, _window);
235
236 // wait for map event
237 do
238 {
239 XNextEvent(_display, &evnt);
240 }
241 while (evnt.type != MapNotify || evnt.xmap.event != _window);
242
243 *outWindow = _window;
244 *outDisplay = _display;
245
246 return 0;
247}
phoglund@webrtc.org337dc682011-11-16 15:36:44 +0000248#endif // LINUX
niklase@google.com470e71d2011-07-07 08:21:25 +0000249
phoglund@webrtc.org337dc682011-11-16 15:36:44 +0000250// Note: Mac code is in testApi_mac.mm.
niklase@google.com470e71d2011-07-07 08:21:25 +0000251
252class MyRenderCallback: public VideoRenderCallback
253{
254public:
255 MyRenderCallback() :
256 _cnt(0)
257 {
258 }
259 ;
260 ~MyRenderCallback()
261 {
262 }
263 ;
pbos@webrtc.orgddf94e72013-04-10 08:09:04 +0000264 virtual int32_t RenderFrame(const uint32_t streamId,
265 I420VideoFrame& videoFrame)
niklase@google.com470e71d2011-07-07 08:21:25 +0000266 {
267 _cnt++;
268 if (_cnt % 100 == 0)
269 {
270 printf("Render callback %d \n",_cnt);
271 }
272 return 0;
273 }
pbos@webrtc.orgddf94e72013-04-10 08:09:04 +0000274 int32_t _cnt;
niklase@google.com470e71d2011-07-07 08:21:25 +0000275};
276
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000277void GetTestVideoFrame(I420VideoFrame* frame,
pbos@webrtc.orgddf94e72013-04-10 08:09:04 +0000278 uint8_t startColor) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000279 // changing color
pbos@webrtc.orgddf94e72013-04-10 08:09:04 +0000280 static uint8_t color = startColor;
niklase@google.com470e71d2011-07-07 08:21:25 +0000281
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000282 memset(frame->buffer(kYPlane), color, frame->allocated_size(kYPlane));
283 memset(frame->buffer(kUPlane), color, frame->allocated_size(kUPlane));
284 memset(frame->buffer(kVPlane), color, frame->allocated_size(kVPlane));
niklase@google.com470e71d2011-07-07 08:21:25 +0000285
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000286 ++color;
niklase@google.com470e71d2011-07-07 08:21:25 +0000287}
288
289int TestSingleStream(VideoRender* renderModule) {
290 int error = 0;
291 // Add settings for a stream to render
292 printf("Add stream 0 to entire window\n");
293 const int streamId0 = 0;
294 VideoRenderCallback* renderCallback0 = renderModule->AddIncomingRenderStream(streamId0, 0, 0.0f, 0.0f, 1.0f, 1.0f);
295 assert(renderCallback0 != NULL);
296
wu@webrtc.orgf3f2f6a2011-10-19 18:42:17 +0000297#ifndef WEBRTC_INCLUDE_INTERNAL_VIDEO_RENDER
niklase@google.com470e71d2011-07-07 08:21:25 +0000298 MyRenderCallback externalRender;
299 renderModule->AddExternalRenderCallback(streamId0, &externalRender);
300#endif
301
302 printf("Start render\n");
303 error = renderModule->StartRender(streamId0);
phoglund@webrtc.orgd1a860b2012-01-26 14:49:28 +0000304 if (error != 0) {
305 // TODO(phoglund): This test will not work if compiled in release mode.
306 // This rather silly construct here is to avoid compilation errors when
307 // compiling in release. Release => no asserts => unused 'error' variable.
308 assert(false);
309 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000310
311 // Loop through an I420 file and render each frame
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000312 const int width = 352;
313 const int half_width = (width + 1) / 2;
314 const int height = 288;
niklase@google.com470e71d2011-07-07 08:21:25 +0000315
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000316 I420VideoFrame videoFrame0;
317 videoFrame0.CreateEmptyFrame(width, height, width, half_width, half_width);
niklase@google.com470e71d2011-07-07 08:21:25 +0000318
pbos@webrtc.orgddf94e72013-04-10 08:09:04 +0000319 const uint32_t renderDelayMs = 500;
niklase@google.com470e71d2011-07-07 08:21:25 +0000320
321 for (int i=0; i<TEST_FRAME_NUM; i++) {
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000322 GetTestVideoFrame(&videoFrame0, TEST_STREAM0_START_COLOR);
323 // Render this frame with the specified delay
324 videoFrame0.set_render_time_ms(TickTime::MillisecondTimestamp()
325 + renderDelayMs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000326 renderCallback0->RenderFrame(streamId0, videoFrame0);
hta@webrtc.org626dccc2012-06-25 11:30:33 +0000327 SleepMs(1000/TEST_FRAME_RATE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000328 }
329
niklase@google.com470e71d2011-07-07 08:21:25 +0000330
331 // Shut down
332 printf("Closing...\n");
333 error = renderModule->StopRender(streamId0);
334 assert(error == 0);
335
336 error = renderModule->DeleteIncomingRenderStream(streamId0);
337 assert(error == 0);
338
339 return 0;
340}
341
342int TestFullscreenStream(VideoRender* &renderModule,
343 void* window,
344 const VideoRenderType videoRenderType) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000345 VideoRender::DestroyVideoRender(renderModule);
346 renderModule = VideoRender::CreateVideoRender(12345, window, true, videoRenderType);
347
348 TestSingleStream(renderModule);
349
350 VideoRender::DestroyVideoRender(renderModule);
351 renderModule = VideoRender::CreateVideoRender(12345, window, false, videoRenderType);
352
353 return 0;
354}
355
356int TestBitmapText(VideoRender* renderModule) {
357#if defined(WIN32)
358
359 int error = 0;
360 // Add settings for a stream to render
361 printf("Add stream 0 to entire window\n");
362 const int streamId0 = 0;
363 VideoRenderCallback* renderCallback0 = renderModule->AddIncomingRenderStream(streamId0, 0, 0.0f, 0.0f, 1.0f, 1.0f);
364 assert(renderCallback0 != NULL);
365
366 printf("Adding Bitmap\n");
367 DDCOLORKEY ColorKey; // black
368 ColorKey.dwColorSpaceHighValue = RGB(0, 0, 0);
369 ColorKey.dwColorSpaceLowValue = RGB(0, 0, 0);
370 HBITMAP hbm = (HBITMAP)LoadImage(NULL,
371 (LPCTSTR)_T("renderStartImage.bmp"),
372 IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
373 renderModule->SetBitmap(hbm, 0, &ColorKey, 0.0f, 0.0f, 0.3f,
374 0.3f);
375
376 printf("Adding Text\n");
pbos@webrtc.orgddf94e72013-04-10 08:09:04 +0000377 renderModule->SetText(1, (uint8_t*) "WebRtc Render Demo App", 20,
niklase@google.com470e71d2011-07-07 08:21:25 +0000378 RGB(255, 0, 0), RGB(0, 0, 0), 0.25f, 0.1f, 1.0f,
379 1.0f);
380
381 printf("Start render\n");
382 error = renderModule->StartRender(streamId0);
383 assert(error == 0);
384
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000385 // Loop through an I420 file and render each frame
386 const int width = 352;
387 const int half_width = (width + 1) / 2;
388 const int height = 288;
niklase@google.com470e71d2011-07-07 08:21:25 +0000389
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000390 I420VideoFrame videoFrame0;
391 videoFrame0.CreateEmptyFrame(width, height, width, half_width, half_width);
niklase@google.com470e71d2011-07-07 08:21:25 +0000392
pbos@webrtc.orgddf94e72013-04-10 08:09:04 +0000393 const uint32_t renderDelayMs = 500;
niklase@google.com470e71d2011-07-07 08:21:25 +0000394
395 for (int i=0; i<TEST_FRAME_NUM; i++) {
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000396 GetTestVideoFrame(&videoFrame0, TEST_STREAM0_START_COLOR);
397 // Render this frame with the specified delay
398 videoFrame0.set_render_time_ms(TickTime::MillisecondTimestamp() +
399 renderDelayMs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000400 renderCallback0->RenderFrame(streamId0, videoFrame0);
hta@webrtc.org626dccc2012-06-25 11:30:33 +0000401 SleepMs(1000/TEST_FRAME_RATE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000402 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000403 // Sleep and let all frames be rendered before closing
hta@webrtc.org626dccc2012-06-25 11:30:33 +0000404 SleepMs(renderDelayMs*2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000405
phoglund@webrtc.org5b343ae2011-12-07 10:34:35 +0000406
niklase@google.com470e71d2011-07-07 08:21:25 +0000407 // Shut down
408 printf("Closing...\n");
409 ColorKey.dwColorSpaceHighValue = RGB(0,0,0);
phoglund@webrtc.org5b343ae2011-12-07 10:34:35 +0000410 ColorKey.dwColorSpaceLowValue = RGB(0,0,0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000411 renderModule->SetBitmap(NULL, 0, &ColorKey, 0.0f, 0.0f, 0.0f, 0.0f);
phoglund@webrtc.org5b343ae2011-12-07 10:34:35 +0000412 renderModule->SetText(1, NULL, 20, RGB(255,255,255),
niklase@google.com470e71d2011-07-07 08:21:25 +0000413 RGB(0,0,0), 0.0f, 0.0f, 0.0f, 0.0f);
phoglund@webrtc.org5b343ae2011-12-07 10:34:35 +0000414
niklase@google.com470e71d2011-07-07 08:21:25 +0000415 error = renderModule->StopRender(streamId0);
416 assert(error == 0);
417
418 error = renderModule->DeleteIncomingRenderStream(streamId0);
419 assert(error == 0);
420#endif
421
422 return 0;
423}
424
425int TestMultipleStreams(VideoRender* renderModule) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000426 // Add settings for a stream to render
427 printf("Add stream 0\n");
428 const int streamId0 = 0;
429 VideoRenderCallback* renderCallback0 =
430 renderModule->AddIncomingRenderStream(streamId0, 0, 0.0f, 0.0f, 0.45f, 0.45f);
431 assert(renderCallback0 != NULL);
432 printf("Add stream 1\n");
433 const int streamId1 = 1;
434 VideoRenderCallback* renderCallback1 =
435 renderModule->AddIncomingRenderStream(streamId1, 0, 0.55f, 0.0f, 1.0f, 0.45f);
436 assert(renderCallback1 != NULL);
437 printf("Add stream 2\n");
438 const int streamId2 = 2;
439 VideoRenderCallback* renderCallback2 =
440 renderModule->AddIncomingRenderStream(streamId2, 0, 0.0f, 0.55f, 0.45f, 1.0f);
441 assert(renderCallback2 != NULL);
442 printf("Add stream 3\n");
443 const int streamId3 = 3;
444 VideoRenderCallback* renderCallback3 =
445 renderModule->AddIncomingRenderStream(streamId3, 0, 0.55f, 0.55f, 1.0f, 1.0f);
446 assert(renderCallback3 != NULL);
447 assert(renderModule->StartRender(streamId0) == 0);
448 assert(renderModule->StartRender(streamId1) == 0);
449 assert(renderModule->StartRender(streamId2) == 0);
450 assert(renderModule->StartRender(streamId3) == 0);
451
452 // Loop through an I420 file and render each frame
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000453 const int width = 352;
454 const int half_width = (width + 1) / 2;
455 const int height = 288;
niklase@google.com470e71d2011-07-07 08:21:25 +0000456
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000457 I420VideoFrame videoFrame0;
458 videoFrame0.CreateEmptyFrame(width, height, width, half_width, half_width);
459 I420VideoFrame videoFrame1;
460 videoFrame1.CreateEmptyFrame(width, height, width, half_width, half_width);
461 I420VideoFrame videoFrame2;
462 videoFrame2.CreateEmptyFrame(width, height, width, half_width, half_width);
463 I420VideoFrame videoFrame3;
464 videoFrame3.CreateEmptyFrame(width, height, width, half_width, half_width);
niklase@google.com470e71d2011-07-07 08:21:25 +0000465
pbos@webrtc.orgddf94e72013-04-10 08:09:04 +0000466 const uint32_t renderDelayMs = 500;
niklase@google.com470e71d2011-07-07 08:21:25 +0000467
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000468 // Render frames with the specified delay.
niklase@google.com470e71d2011-07-07 08:21:25 +0000469 for (int i=0; i<TEST_FRAME_NUM; i++) {
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000470 GetTestVideoFrame(&videoFrame0, TEST_STREAM0_START_COLOR);
niklase@google.com470e71d2011-07-07 08:21:25 +0000471
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000472 videoFrame0.set_render_time_ms(TickTime::MillisecondTimestamp() +
473 renderDelayMs);
474 renderCallback0->RenderFrame(streamId0, videoFrame0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000475
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000476 GetTestVideoFrame(&videoFrame1, TEST_STREAM1_START_COLOR);
477 videoFrame1.set_render_time_ms(TickTime::MillisecondTimestamp() +
478 renderDelayMs);
479 renderCallback1->RenderFrame(streamId1, videoFrame1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000480
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000481 GetTestVideoFrame(&videoFrame2, TEST_STREAM2_START_COLOR);
482 videoFrame2.set_render_time_ms(TickTime::MillisecondTimestamp() +
483 renderDelayMs);
484 renderCallback2->RenderFrame(streamId2, videoFrame2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000485
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000486 GetTestVideoFrame(&videoFrame3, TEST_STREAM3_START_COLOR);
487 videoFrame3.set_render_time_ms(TickTime::MillisecondTimestamp() +
488 renderDelayMs);
489 renderCallback3->RenderFrame(streamId3, videoFrame3);
490
491 SleepMs(1000/TEST_FRAME_RATE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000492 }
493
niklase@google.com470e71d2011-07-07 08:21:25 +0000494 // Shut down
495 printf("Closing...\n");
496 assert(renderModule->StopRender(streamId0) == 0);
497 assert(renderModule->DeleteIncomingRenderStream(streamId0) == 0);
498 assert(renderModule->StopRender(streamId1) == 0);
499 assert(renderModule->DeleteIncomingRenderStream(streamId1) == 0);
500 assert(renderModule->StopRender(streamId2) == 0);
501 assert(renderModule->DeleteIncomingRenderStream(streamId2) == 0);
502 assert(renderModule->StopRender(streamId3) == 0);
503 assert(renderModule->DeleteIncomingRenderStream(streamId3) == 0);
504
505 return 0;
506}
507
508int TestExternalRender(VideoRender* renderModule) {
509 MyRenderCallback *externalRender = new MyRenderCallback();
510
511 const int streamId0 = 0;
512 VideoRenderCallback* renderCallback0 =
513 renderModule->AddIncomingRenderStream(streamId0, 0, 0.0f, 0.0f,
514 1.0f, 1.0f);
515 assert(renderCallback0 != NULL);
516 assert(renderModule->AddExternalRenderCallback(streamId0,
517 externalRender) == 0);
518
519 assert(renderModule->StartRender(streamId0) == 0);
520
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000521 const int width = 352;
522 const int half_width = (width + 1) / 2;
523 const int height = 288;
524 I420VideoFrame videoFrame0;
525 videoFrame0.CreateEmptyFrame(width, height, width, half_width, half_width);
niklase@google.com470e71d2011-07-07 08:21:25 +0000526
pbos@webrtc.orgddf94e72013-04-10 08:09:04 +0000527 const uint32_t renderDelayMs = 500;
niklase@google.com470e71d2011-07-07 08:21:25 +0000528 int frameCount = TEST_FRAME_NUM;
529 for (int i=0; i<frameCount; i++) {
mikhal@webrtc.org9fedff72012-10-24 18:33:04 +0000530 videoFrame0.set_render_time_ms(TickTime::MillisecondTimestamp() +
531 renderDelayMs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000532 renderCallback0->RenderFrame(streamId0, videoFrame0);
hta@webrtc.org626dccc2012-06-25 11:30:33 +0000533 SleepMs(33);
niklase@google.com470e71d2011-07-07 08:21:25 +0000534 }
535
536 // Sleep and let all frames be rendered before closing
hta@webrtc.org626dccc2012-06-25 11:30:33 +0000537 SleepMs(2*renderDelayMs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000538
539 assert(renderModule->StopRender(streamId0) == 0);
540 assert(renderModule->DeleteIncomingRenderStream(streamId0) == 0);
541 assert(frameCount == externalRender->_cnt);
542
543 delete externalRender;
544 externalRender = NULL;
545
546 return 0;
547}
548
phoglund@webrtc.org337dc682011-11-16 15:36:44 +0000549void RunVideoRenderTests(void* window, VideoRenderType windowType) {
wu@webrtc.orgf3f2f6a2011-10-19 18:42:17 +0000550#ifndef WEBRTC_INCLUDE_INTERNAL_VIDEO_RENDER
niklase@google.com470e71d2011-07-07 08:21:25 +0000551 windowType = kRenderExternal;
552#endif
553
phoglund@webrtc.org337dc682011-11-16 15:36:44 +0000554 int myId = 12345;
555
niklase@google.com470e71d2011-07-07 08:21:25 +0000556 // Create the render module
557 printf("Create render module\n");
558 VideoRender* renderModule = NULL;
559 renderModule = VideoRender::CreateVideoRender(myId,
560 window,
561 false,
562 windowType);
563 assert(renderModule != NULL);
564
565
566 // ##### Test single stream rendering ####
567 printf("#### TestSingleStream ####\n");
568 if (TestSingleStream(renderModule) != 0) {
569 printf ("TestSingleStream failed\n");
570 }
571
572 // ##### Test fullscreen rendering ####
573 printf("#### TestFullscreenStream ####\n");
574 if (TestFullscreenStream(renderModule, window, windowType) != 0) {
575 printf ("TestFullscreenStream failed\n");
576 }
577
578 // ##### Test bitmap and text ####
579 printf("#### TestBitmapText ####\n");
580 if (TestBitmapText(renderModule) != 0) {
581 printf ("TestBitmapText failed\n");
582 }
583
584 // ##### Test multiple streams ####
585 printf("#### TestMultipleStreams ####\n");
586 if (TestMultipleStreams(renderModule) != 0) {
587 printf ("TestMultipleStreams failed\n");
588 }
589
590 // ##### Test multiple streams ####
591 printf("#### TestExternalRender ####\n");
592 if (TestExternalRender(renderModule) != 0) {
593 printf ("TestExternalRender failed\n");
594 }
595
596 delete renderModule;
597 renderModule = NULL;
598
599 printf("VideoRender unit tests passed.\n");
phoglund@webrtc.org337dc682011-11-16 15:36:44 +0000600}
niklase@google.com470e71d2011-07-07 08:21:25 +0000601
phoglund@webrtc.org337dc682011-11-16 15:36:44 +0000602// Note: The Mac main is implemented in testApi_mac.mm.
603#if defined(_WIN32)
604int _tmain(int argc, _TCHAR* argv[])
leozwang@webrtc.org77fe4312012-03-06 20:59:55 +0000605#elif defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
phoglund@webrtc.org337dc682011-11-16 15:36:44 +0000606int main(int argc, char* argv[])
niklase@google.com470e71d2011-07-07 08:21:25 +0000607#endif
leozwang@webrtc.org77fe4312012-03-06 20:59:55 +0000608#if !defined(WEBRTC_MAC) && !defined(WEBRTC_ANDROID)
phoglund@webrtc.org337dc682011-11-16 15:36:44 +0000609{
610 // Create a window for testing.
611 void* window = NULL;
612#if defined (_WIN32)
613 HWND testHwnd;
614 WebRtcCreateWindow(testHwnd, 0, 352, 288);
615 window = (void*)testHwnd;
616 VideoRenderType windowType = kRenderWindows;
617#elif defined(WEBRTC_LINUX)
618 Window testWindow;
619 Display* display;
620 WebRtcCreateWindow(&testWindow, &display, 0, 352, 288);
621 VideoRenderType windowType = kRenderX11;
622 window = (void*)testWindow;
623#endif // WEBRTC_LINUX
624
625 RunVideoRenderTests(window, windowType);
niklase@google.com470e71d2011-07-07 08:21:25 +0000626 return 0;
627}
phoglund@webrtc.org337dc682011-11-16 15:36:44 +0000628#endif // !WEBRTC_MAC