Home | History | Annotate | Download | only in testAPI
      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 #include "webrtc/modules/video_render/test/testAPI/testAPI.h"
     12 
     13 #include <stdio.h>
     14 
     15 #if defined(_WIN32)
     16 #include <tchar.h>
     17 #include <windows.h>
     18 #include <assert.h>
     19 #include <fstream>
     20 #include <iostream>
     21 #include <string>
     22 #include <windows.h>
     23 #include <ddraw.h>
     24 
     25 #elif defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
     26 
     27 #include <X11/Xlib.h>
     28 #include <X11/Xutil.h>
     29 #include <iostream>
     30 #include <sys/time.h>
     31 
     32 #endif
     33 
     34 #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"
     42 
     43 using namespace webrtc;
     44 
     45 void GetTestVideoFrame(I420VideoFrame* frame,
     46                        uint8_t startColor);
     47 int TestSingleStream(VideoRender* renderModule);
     48 int TestFullscreenStream(VideoRender* &renderModule,
     49                          void* window,
     50                          const VideoRenderType videoRenderType);
     51 int TestBitmapText(VideoRender* renderModule);
     52 int TestMultipleStreams(VideoRender* renderModule);
     53 int 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 
     63 #if defined(WEBRTC_LINUX)
     64 
     65 #define GET_TIME_IN_MS timeGetTime()
     66 
     67 unsigned 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 
     78 #elif defined(WEBRTC_MAC)
     79 
     80 #include <unistd.h>
     81 
     82 #define GET_TIME_IN_MS timeGetTime()
     83 
     84 unsigned long timeGetTime()
     85 {
     86     return 0;
     87 }
     88 
     89 #else
     90 
     91 #define GET_TIME_IN_MS ::timeGetTime()
     92 
     93 #endif
     94 
     95 using namespace std;
     96 
     97 #if defined(_WIN32)
     98 LRESULT 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 
    110 int 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)
    151         return -1;
    152 
    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 
    162 #elif defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
    163 
    164 int 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 
    179     // put desired visual info for the screen in vinfo
    180     if( XMatchVisualInfo(_display, screen, 24, TrueColor, &vinfo) != 0 )
    181     {
    182         //printf( "Screen visual info match!\n" );
    183     }
    184 
    185     // set window attributes
    186     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 
    230     // make x report events for mask
    231     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 }
    248 #endif  // LINUX
    249 
    250 // Note: Mac code is in testApi_mac.mm.
    251 
    252 class MyRenderCallback: public VideoRenderCallback
    253 {
    254 public:
    255     MyRenderCallback() :
    256         _cnt(0)
    257     {
    258     }
    259     ;
    260     ~MyRenderCallback()
    261     {
    262     }
    263     ;
    264     virtual int32_t RenderFrame(const uint32_t streamId,
    265                                 I420VideoFrame& videoFrame)
    266     {
    267         _cnt++;
    268         if (_cnt % 100 == 0)
    269         {
    270             printf("Render callback %d \n",_cnt);
    271         }
    272         return 0;
    273     }
    274     int32_t _cnt;
    275 };
    276 
    277 void GetTestVideoFrame(I420VideoFrame* frame,
    278                        uint8_t startColor) {
    279     // changing color
    280     static uint8_t color = startColor;
    281 
    282     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));
    285 
    286     ++color;
    287 }
    288 
    289 int 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 
    297     printf("Start render\n");
    298     error = renderModule->StartRender(streamId0);
    299     if (error != 0) {
    300       // TODO(phoglund): This test will not work if compiled in release mode.
    301       // This rather silly construct here is to avoid compilation errors when
    302       // compiling in release. Release => no asserts => unused 'error' variable.
    303       assert(false);
    304     }
    305 
    306     // Loop through an I420 file and render each frame
    307     const int width = 352;
    308     const int half_width = (width + 1) / 2;
    309     const int height = 288;
    310 
    311     I420VideoFrame videoFrame0;
    312     videoFrame0.CreateEmptyFrame(width, height, width, half_width, half_width);
    313 
    314     const uint32_t renderDelayMs = 500;
    315 
    316     for (int i=0; i<TEST_FRAME_NUM; i++) {
    317         GetTestVideoFrame(&videoFrame0, TEST_STREAM0_START_COLOR);
    318         // Render this frame with the specified delay
    319         videoFrame0.set_render_time_ms(TickTime::MillisecondTimestamp()
    320                                        + renderDelayMs);
    321         renderCallback0->RenderFrame(streamId0, videoFrame0);
    322         SleepMs(1000/TEST_FRAME_RATE);
    323     }
    324 
    325 
    326     // Shut down
    327     printf("Closing...\n");
    328     error = renderModule->StopRender(streamId0);
    329     assert(error == 0);
    330 
    331     error = renderModule->DeleteIncomingRenderStream(streamId0);
    332     assert(error == 0);
    333 
    334     return 0;
    335 }
    336 
    337 int TestFullscreenStream(VideoRender* &renderModule,
    338                          void* window,
    339                          const VideoRenderType videoRenderType) {
    340     VideoRender::DestroyVideoRender(renderModule);
    341     renderModule = VideoRender::CreateVideoRender(12345, window, true, videoRenderType);
    342 
    343     TestSingleStream(renderModule);
    344 
    345     VideoRender::DestroyVideoRender(renderModule);
    346     renderModule = VideoRender::CreateVideoRender(12345, window, false, videoRenderType);
    347 
    348     return 0;
    349 }
    350 
    351 int TestBitmapText(VideoRender* renderModule) {
    352 #if defined(WIN32)
    353 
    354     int error = 0;
    355     // Add settings for a stream to render
    356     printf("Add stream 0 to entire window\n");
    357     const int streamId0 = 0;
    358     VideoRenderCallback* renderCallback0 = renderModule->AddIncomingRenderStream(streamId0, 0, 0.0f, 0.0f, 1.0f, 1.0f);
    359     assert(renderCallback0 != NULL);
    360 
    361     printf("Adding Bitmap\n");
    362     DDCOLORKEY ColorKey; // black
    363     ColorKey.dwColorSpaceHighValue = RGB(0, 0, 0);
    364     ColorKey.dwColorSpaceLowValue = RGB(0, 0, 0);
    365     HBITMAP hbm = (HBITMAP)LoadImage(NULL,
    366                                      (LPCTSTR)_T("renderStartImage.bmp"),
    367                                      IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    368     renderModule->SetBitmap(hbm, 0, &ColorKey, 0.0f, 0.0f, 0.3f,
    369                              0.3f);
    370 
    371     printf("Adding Text\n");
    372     renderModule->SetText(1, (uint8_t*) "WebRtc Render Demo App", 20,
    373                            RGB(255, 0, 0), RGB(0, 0, 0), 0.25f, 0.1f, 1.0f,
    374                            1.0f);
    375 
    376     printf("Start render\n");
    377     error = renderModule->StartRender(streamId0);
    378     assert(error == 0);
    379 
    380     // Loop through an I420 file and render each frame
    381     const int width = 352;
    382     const int half_width = (width + 1) / 2;
    383     const int height = 288;
    384 
    385     I420VideoFrame videoFrame0;
    386     videoFrame0.CreateEmptyFrame(width, height, width, half_width, half_width);
    387 
    388     const uint32_t renderDelayMs = 500;
    389 
    390     for (int i=0; i<TEST_FRAME_NUM; i++) {
    391         GetTestVideoFrame(&videoFrame0, TEST_STREAM0_START_COLOR);
    392         // Render this frame with the specified delay
    393         videoFrame0.set_render_time_ms(TickTime::MillisecondTimestamp() +
    394                                        renderDelayMs);
    395         renderCallback0->RenderFrame(streamId0, videoFrame0);
    396         SleepMs(1000/TEST_FRAME_RATE);
    397     }
    398     // Sleep and let all frames be rendered before closing
    399     SleepMs(renderDelayMs*2);
    400 
    401 
    402     // Shut down
    403     printf("Closing...\n");
    404     ColorKey.dwColorSpaceHighValue = RGB(0,0,0);
    405     ColorKey.dwColorSpaceLowValue = RGB(0,0,0);
    406     renderModule->SetBitmap(NULL, 0, &ColorKey, 0.0f, 0.0f, 0.0f, 0.0f);
    407     renderModule->SetText(1, NULL, 20, RGB(255,255,255),
    408                     RGB(0,0,0), 0.0f, 0.0f, 0.0f, 0.0f);
    409 
    410     error = renderModule->StopRender(streamId0);
    411     assert(error == 0);
    412 
    413     error = renderModule->DeleteIncomingRenderStream(streamId0);
    414     assert(error == 0);
    415 #endif
    416 
    417     return 0;
    418 }
    419 
    420 int TestMultipleStreams(VideoRender* renderModule) {
    421     int error = 0;
    422 
    423     // Add settings for a stream to render
    424     printf("Add stream 0\n");
    425     const int streamId0 = 0;
    426     VideoRenderCallback* renderCallback0 =
    427         renderModule->AddIncomingRenderStream(streamId0, 0, 0.0f, 0.0f, 0.45f, 0.45f);
    428     assert(renderCallback0 != NULL);
    429     printf("Add stream 1\n");
    430     const int streamId1 = 1;
    431     VideoRenderCallback* renderCallback1 =
    432         renderModule->AddIncomingRenderStream(streamId1, 0, 0.55f, 0.0f, 1.0f, 0.45f);
    433     assert(renderCallback1 != NULL);
    434     printf("Add stream 2\n");
    435     const int streamId2 = 2;
    436     VideoRenderCallback* renderCallback2 =
    437         renderModule->AddIncomingRenderStream(streamId2, 0, 0.0f, 0.55f, 0.45f, 1.0f);
    438     assert(renderCallback2 != NULL);
    439     printf("Add stream 3\n");
    440     const int streamId3 = 3;
    441     VideoRenderCallback* renderCallback3 =
    442         renderModule->AddIncomingRenderStream(streamId3, 0, 0.55f, 0.55f, 1.0f, 1.0f);
    443     assert(renderCallback3 != NULL);
    444     error = renderModule->StartRender(streamId0);
    445     if (error != 0) {
    446       // TODO(phoglund): This test will not work if compiled in release mode.
    447       // This rather silly construct here is to avoid compilation errors when
    448       // compiling in release. Release => no asserts => unused 'error' variable.
    449       assert(false);
    450     }
    451     error = renderModule->StartRender(streamId1);
    452     assert(error == 0);
    453     error = renderModule->StartRender(streamId2);
    454     assert(error == 0);
    455     error = renderModule->StartRender(streamId3);
    456     assert(error == 0);
    457 
    458     // Loop through an I420 file and render each frame
    459     const int width = 352;
    460     const int half_width = (width + 1) / 2;
    461     const int height = 288;
    462 
    463     I420VideoFrame videoFrame0;
    464     videoFrame0.CreateEmptyFrame(width, height, width, half_width, half_width);
    465     I420VideoFrame videoFrame1;
    466     videoFrame1.CreateEmptyFrame(width, height, width, half_width, half_width);
    467     I420VideoFrame videoFrame2;
    468     videoFrame2.CreateEmptyFrame(width, height, width, half_width, half_width);
    469     I420VideoFrame videoFrame3;
    470     videoFrame3.CreateEmptyFrame(width, height, width, half_width, half_width);
    471 
    472     const uint32_t renderDelayMs = 500;
    473 
    474     // Render frames with the specified delay.
    475     for (int i=0; i<TEST_FRAME_NUM; i++) {
    476       GetTestVideoFrame(&videoFrame0, TEST_STREAM0_START_COLOR);
    477 
    478       videoFrame0.set_render_time_ms(TickTime::MillisecondTimestamp() +
    479                                      renderDelayMs);
    480       renderCallback0->RenderFrame(streamId0, videoFrame0);
    481 
    482       GetTestVideoFrame(&videoFrame1, TEST_STREAM1_START_COLOR);
    483       videoFrame1.set_render_time_ms(TickTime::MillisecondTimestamp() +
    484                                      renderDelayMs);
    485       renderCallback1->RenderFrame(streamId1, videoFrame1);
    486 
    487       GetTestVideoFrame(&videoFrame2,  TEST_STREAM2_START_COLOR);
    488       videoFrame2.set_render_time_ms(TickTime::MillisecondTimestamp() +
    489                                      renderDelayMs);
    490       renderCallback2->RenderFrame(streamId2, videoFrame2);
    491 
    492       GetTestVideoFrame(&videoFrame3, TEST_STREAM3_START_COLOR);
    493       videoFrame3.set_render_time_ms(TickTime::MillisecondTimestamp() +
    494                                      renderDelayMs);
    495       renderCallback3->RenderFrame(streamId3, videoFrame3);
    496 
    497       SleepMs(1000/TEST_FRAME_RATE);
    498     }
    499 
    500     // Shut down
    501     printf("Closing...\n");
    502     error = renderModule->StopRender(streamId0);
    503     assert(error == 0);
    504     error = renderModule->DeleteIncomingRenderStream(streamId0);
    505     assert(error == 0);
    506     error = renderModule->StopRender(streamId1);
    507     assert(error == 0);
    508     error = renderModule->DeleteIncomingRenderStream(streamId1);
    509     assert(error == 0);
    510     error = renderModule->StopRender(streamId2);
    511     assert(error == 0);
    512     error = renderModule->DeleteIncomingRenderStream(streamId2);
    513     assert(error == 0);
    514     error = renderModule->StopRender(streamId3);
    515     assert(error == 0);
    516     error = renderModule->DeleteIncomingRenderStream(streamId3);
    517     assert(error == 0);
    518 
    519     return 0;
    520 }
    521 
    522 int TestExternalRender(VideoRender* renderModule) {
    523     int error = 0;
    524     MyRenderCallback *externalRender = new MyRenderCallback();
    525 
    526     const int streamId0 = 0;
    527     VideoRenderCallback* renderCallback0 =
    528         renderModule->AddIncomingRenderStream(streamId0, 0, 0.0f, 0.0f,
    529                                                    1.0f, 1.0f);
    530     assert(renderCallback0 != NULL);
    531     error = renderModule->AddExternalRenderCallback(streamId0, externalRender);
    532     if (error != 0) {
    533       // TODO(phoglund): This test will not work if compiled in release mode.
    534       // This rather silly construct here is to avoid compilation errors when
    535       // compiling in release. Release => no asserts => unused 'error' variable.
    536       assert(false);
    537     }
    538 
    539     error = renderModule->StartRender(streamId0);
    540     assert(error == 0);
    541 
    542     const int width = 352;
    543     const int half_width = (width + 1) / 2;
    544     const int height = 288;
    545     I420VideoFrame videoFrame0;
    546     videoFrame0.CreateEmptyFrame(width, height, width, half_width, half_width);
    547 
    548     const uint32_t renderDelayMs = 500;
    549     int frameCount = TEST_FRAME_NUM;
    550     for (int i=0; i<frameCount; i++) {
    551         videoFrame0.set_render_time_ms(TickTime::MillisecondTimestamp() +
    552                                        renderDelayMs);
    553         renderCallback0->RenderFrame(streamId0, videoFrame0);
    554         SleepMs(33);
    555     }
    556 
    557     // Sleep and let all frames be rendered before closing
    558     SleepMs(2*renderDelayMs);
    559 
    560     // Shut down
    561     printf("Closing...\n");
    562     error = renderModule->StopRender(streamId0);
    563     assert(error == 0);
    564     error = renderModule->DeleteIncomingRenderStream(streamId0);
    565     assert(error == 0);
    566     assert(frameCount == externalRender->_cnt);
    567 
    568     delete externalRender;
    569     externalRender = NULL;
    570 
    571     return 0;
    572 }
    573 
    574 void RunVideoRenderTests(void* window, VideoRenderType windowType) {
    575     int myId = 12345;
    576 
    577     // Create the render module
    578     printf("Create render module\n");
    579     VideoRender* renderModule = NULL;
    580     renderModule = VideoRender::CreateVideoRender(myId,
    581                                                   window,
    582                                                   false,
    583                                                   windowType);
    584     assert(renderModule != NULL);
    585 
    586     // ##### Test single stream rendering ####
    587     printf("#### TestSingleStream ####\n");
    588     if (TestSingleStream(renderModule) != 0) {
    589         printf ("TestSingleStream failed\n");
    590     }
    591 
    592     // ##### Test fullscreen rendering ####
    593     printf("#### TestFullscreenStream ####\n");
    594     if (TestFullscreenStream(renderModule, window, windowType) != 0) {
    595         printf ("TestFullscreenStream failed\n");
    596     }
    597 
    598     // ##### Test bitmap and text ####
    599     printf("#### TestBitmapText ####\n");
    600     if (TestBitmapText(renderModule) != 0) {
    601         printf ("TestBitmapText failed\n");
    602     }
    603 
    604     // ##### Test multiple streams ####
    605     printf("#### TestMultipleStreams ####\n");
    606     if (TestMultipleStreams(renderModule) != 0) {
    607         printf ("TestMultipleStreams failed\n");
    608     }
    609 
    610     // ##### Test multiple streams ####
    611     printf("#### TestExternalRender ####\n");
    612     if (TestExternalRender(renderModule) != 0) {
    613         printf ("TestExternalRender failed\n");
    614     }
    615 
    616     delete renderModule;
    617     renderModule = NULL;
    618 
    619     printf("VideoRender unit tests passed.\n");
    620 }
    621 
    622 // Note: The Mac main is implemented in testApi_mac.mm.
    623 #if defined(_WIN32)
    624 int _tmain(int argc, _TCHAR* argv[])
    625 #elif defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
    626 int main(int argc, char* argv[])
    627 #endif
    628 #if !defined(WEBRTC_MAC) && !defined(WEBRTC_ANDROID)
    629 {
    630     // Create a window for testing.
    631     void* window = NULL;
    632 #if defined (_WIN32)
    633     HWND testHwnd;
    634     WebRtcCreateWindow(testHwnd, 0, 352, 288);
    635     window = (void*)testHwnd;
    636     VideoRenderType windowType = kRenderWindows;
    637 #elif defined(WEBRTC_LINUX)
    638     Window testWindow;
    639     Display* display;
    640     WebRtcCreateWindow(&testWindow, &display, 0, 352, 288);
    641     VideoRenderType windowType = kRenderX11;
    642     window = (void*)testWindow;
    643 #endif // WEBRTC_LINUX
    644 
    645     RunVideoRenderTests(window, windowType);
    646     return 0;
    647 }
    648 #endif  // !WEBRTC_MAC
    649