Home | History | Annotate | Download | only in video_render
      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 <assert.h>
     12 
     13 #include "webrtc/engine_configurations.h"
     14 #include "webrtc/modules/video_render/i_video_render.h"
     15 #include "webrtc/modules/video_render/include/video_render_defines.h"
     16 #include "webrtc/modules/video_render/incoming_video_stream.h"
     17 #include "webrtc/modules/video_render/video_render_impl.h"
     18 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
     19 #include "webrtc/system_wrappers/interface/trace.h"
     20 
     21 #if defined (_WIN32)
     22 #include "webrtc/modules/video_render/windows/video_render_windows_impl.h"
     23 #define STANDARD_RENDERING kRenderWindows
     24 
     25 // WEBRTC_IOS should go before WEBRTC_MAC because WEBRTC_MAC
     26 // gets defined if WEBRTC_IOS is defined
     27 #elif defined(WEBRTC_IOS)
     28 #define STANDARD_RENDERING kRenderiOS
     29 #include "webrtc/modules/video_render/ios/video_render_ios_impl.h"
     30 #elif defined(WEBRTC_MAC)
     31 #if defined(COCOA_RENDERING)
     32 #define STANDARD_RENDERING kRenderCocoa
     33 #include "webrtc/modules/video_render/mac/video_render_mac_cocoa_impl.h"
     34 #elif defined(CARBON_RENDERING)
     35 #define STANDARD_RENDERING kRenderCarbon
     36 #include "webrtc/modules/video_render/mac/video_render_mac_carbon_impl.h"
     37 #endif
     38 
     39 #elif defined(WEBRTC_ANDROID)
     40 #include "webrtc/modules/video_render/android/video_render_android_impl.h"
     41 #include "webrtc/modules/video_render/android/video_render_android_native_opengl2.h"
     42 #include "webrtc/modules/video_render/android/video_render_android_surface_view.h"
     43 #define STANDARD_RENDERING kRenderAndroid
     44 
     45 #elif defined(WEBRTC_LINUX)
     46 #include "webrtc/modules/video_render/linux/video_render_linux_impl.h"
     47 #define STANDARD_RENDERING kRenderX11
     48 
     49 #else
     50 //Other platforms
     51 #endif
     52 
     53 // For external rendering
     54 #include "webrtc/modules/video_render/external/video_render_external_impl.h"
     55 #ifndef STANDARD_RENDERING
     56 #define STANDARD_RENDERING kRenderExternal
     57 #endif  // STANDARD_RENDERING
     58 
     59 namespace webrtc {
     60 
     61 VideoRender*
     62 VideoRender::CreateVideoRender(const int32_t id,
     63                                void* window,
     64                                const bool fullscreen,
     65                                const VideoRenderType videoRenderType/*=kRenderDefault*/)
     66 {
     67     VideoRenderType resultVideoRenderType = videoRenderType;
     68     if (videoRenderType == kRenderDefault)
     69     {
     70         resultVideoRenderType = STANDARD_RENDERING;
     71     }
     72     return new ModuleVideoRenderImpl(id, resultVideoRenderType, window,
     73                                      fullscreen);
     74 }
     75 
     76 void VideoRender::DestroyVideoRender(
     77                                                          VideoRender* module)
     78 {
     79     if (module)
     80     {
     81         delete module;
     82     }
     83 }
     84 
     85 ModuleVideoRenderImpl::ModuleVideoRenderImpl(
     86                                              const int32_t id,
     87                                              const VideoRenderType videoRenderType,
     88                                              void* window,
     89                                              const bool fullscreen) :
     90     _id(id), _moduleCrit(*CriticalSectionWrapper::CreateCriticalSection()),
     91     _ptrWindow(window), _fullScreen(fullscreen), _ptrRenderer(NULL)
     92 {
     93 
     94     // Create platform specific renderer
     95     switch (videoRenderType)
     96     {
     97 #if defined(_WIN32)
     98         case kRenderWindows:
     99         {
    100             VideoRenderWindowsImpl* ptrRenderer;
    101             ptrRenderer = new VideoRenderWindowsImpl(_id, videoRenderType, window, _fullScreen);
    102             if (ptrRenderer)
    103             {
    104                 _ptrRenderer = reinterpret_cast<IVideoRender*>(ptrRenderer);
    105             }
    106         }
    107         break;
    108 
    109 #elif defined(WEBRTC_IOS)
    110         case kRenderiOS:
    111         {
    112             VideoRenderIosImpl* ptrRenderer = new VideoRenderIosImpl(_id, window, _fullScreen);
    113             if(ptrRenderer)
    114             {
    115                 _ptrRenderer = reinterpret_cast<IVideoRender*>(ptrRenderer);
    116             }
    117         }
    118         break;
    119 
    120 #elif defined(WEBRTC_MAC)
    121 
    122 #if defined(COCOA_RENDERING)
    123         case kRenderCocoa:
    124         {
    125             VideoRenderMacCocoaImpl* ptrRenderer = new VideoRenderMacCocoaImpl(_id, videoRenderType, window, _fullScreen);
    126             if(ptrRenderer)
    127             {
    128                 _ptrRenderer = reinterpret_cast<IVideoRender*>(ptrRenderer);
    129             }
    130         }
    131 
    132         break;
    133 #elif defined(CARBON_RENDERING)
    134         case kRenderCarbon:
    135         {
    136             VideoRenderMacCarbonImpl* ptrRenderer = new VideoRenderMacCarbonImpl(_id, videoRenderType, window, _fullScreen);
    137             if(ptrRenderer)
    138             {
    139                 _ptrRenderer = reinterpret_cast<IVideoRender*>(ptrRenderer);
    140             }
    141         }
    142         break;
    143 #endif
    144 
    145 #elif defined(WEBRTC_ANDROID)
    146         case kRenderAndroid:
    147         {
    148             if(AndroidNativeOpenGl2Renderer::UseOpenGL2(window))
    149             {
    150                 AndroidNativeOpenGl2Renderer* ptrRenderer = NULL;
    151                 ptrRenderer = new AndroidNativeOpenGl2Renderer(_id, videoRenderType, window, _fullScreen);
    152                 if (ptrRenderer)
    153                 {
    154                     _ptrRenderer = reinterpret_cast<IVideoRender*> (ptrRenderer);
    155                 }
    156             }
    157             else
    158             {
    159                 AndroidSurfaceViewRenderer* ptrRenderer = NULL;
    160                 ptrRenderer = new AndroidSurfaceViewRenderer(_id, videoRenderType, window, _fullScreen);
    161                 if (ptrRenderer)
    162                 {
    163                     _ptrRenderer = reinterpret_cast<IVideoRender*> (ptrRenderer);
    164                 }
    165             }
    166 
    167         }
    168         break;
    169 #elif defined(WEBRTC_LINUX)
    170         case kRenderX11:
    171         {
    172             VideoRenderLinuxImpl* ptrRenderer = NULL;
    173             ptrRenderer = new VideoRenderLinuxImpl(_id, videoRenderType, window, _fullScreen);
    174             if ( ptrRenderer )
    175             {
    176                 _ptrRenderer = reinterpret_cast<IVideoRender*> (ptrRenderer);
    177             }
    178         }
    179         break;
    180 
    181 #else
    182         // Other platforms
    183 #endif
    184         case kRenderExternal:
    185         {
    186             VideoRenderExternalImpl* ptrRenderer(NULL);
    187             ptrRenderer = new VideoRenderExternalImpl(_id, videoRenderType,
    188                                                       window, _fullScreen);
    189             if (ptrRenderer)
    190             {
    191                 _ptrRenderer = reinterpret_cast<IVideoRender*> (ptrRenderer);
    192             }
    193         }
    194             break;
    195         default:
    196             // Error...
    197             break;
    198     }
    199     if (_ptrRenderer)
    200     {
    201         if (_ptrRenderer->Init() == -1)
    202         {
    203         }
    204     }
    205 }
    206 
    207 ModuleVideoRenderImpl::~ModuleVideoRenderImpl()
    208 {
    209     delete &_moduleCrit;
    210 
    211     for (IncomingVideoStreamMap::iterator it = _streamRenderMap.begin();
    212          it != _streamRenderMap.end();
    213          ++it) {
    214       delete it->second;
    215     }
    216 
    217     // Delete platform specific renderer
    218     if (_ptrRenderer)
    219     {
    220         VideoRenderType videoRenderType = _ptrRenderer->RenderType();
    221 
    222         switch (videoRenderType)
    223         {
    224             case kRenderExternal:
    225             {
    226                 VideoRenderExternalImpl
    227                         * ptrRenderer =
    228                                 reinterpret_cast<VideoRenderExternalImpl*> (_ptrRenderer);
    229                 _ptrRenderer = NULL;
    230                 delete ptrRenderer;
    231             }
    232             break;
    233 #if defined(_WIN32)
    234             case kRenderWindows:
    235             {
    236                 VideoRenderWindowsImpl* ptrRenderer = reinterpret_cast<VideoRenderWindowsImpl*>(_ptrRenderer);
    237                 _ptrRenderer = NULL;
    238                 delete ptrRenderer;
    239             }
    240             break;
    241 #elif defined(WEBRTC_IOS)
    242             case kRenderiOS:
    243             {
    244               VideoRenderIosImpl* ptrRenderer = reinterpret_cast<VideoRenderIosImpl*> (_ptrRenderer);
    245               _ptrRenderer = NULL;
    246               delete ptrRenderer;
    247             }
    248             break;
    249 #elif defined(WEBRTC_MAC)
    250 
    251 #if defined(COCOA_RENDERING)
    252             case kRenderCocoa:
    253             {
    254                 VideoRenderMacCocoaImpl* ptrRenderer = reinterpret_cast<VideoRenderMacCocoaImpl*> (_ptrRenderer);
    255                 _ptrRenderer = NULL;
    256                 delete ptrRenderer;
    257             }
    258             break;
    259 #elif defined(CARBON_RENDERING)
    260             case kRenderCarbon:
    261             {
    262                 VideoRenderMacCarbonImpl* ptrRenderer = reinterpret_cast<VideoRenderMacCarbonImpl*> (_ptrRenderer);
    263                 _ptrRenderer = NULL;
    264                 delete ptrRenderer;
    265             }
    266             break;
    267 #endif
    268 
    269 #elif defined(WEBRTC_ANDROID)
    270             case kRenderAndroid:
    271             {
    272                 VideoRenderAndroid* ptrRenderer = reinterpret_cast<VideoRenderAndroid*> (_ptrRenderer);
    273                 _ptrRenderer = NULL;
    274                 delete ptrRenderer;
    275             }
    276             break;
    277 
    278 #elif defined(WEBRTC_LINUX)
    279             case kRenderX11:
    280             {
    281                 VideoRenderLinuxImpl* ptrRenderer = reinterpret_cast<VideoRenderLinuxImpl*> (_ptrRenderer);
    282                 _ptrRenderer = NULL;
    283                 delete ptrRenderer;
    284             }
    285             break;
    286 #else
    287             //other platforms
    288 #endif
    289 
    290             default:
    291                 // Error...
    292                 break;
    293         }
    294     }
    295 }
    296 
    297 int32_t ModuleVideoRenderImpl::ChangeUniqueId(const int32_t id)
    298 {
    299 
    300     CriticalSectionScoped cs(&_moduleCrit);
    301 
    302     _id = id;
    303 
    304     if (_ptrRenderer)
    305     {
    306         _ptrRenderer->ChangeUniqueId(_id);
    307     }
    308 
    309     return 0;
    310 }
    311 
    312 int32_t ModuleVideoRenderImpl::TimeUntilNextProcess()
    313 {
    314     // Not used
    315     return 50;
    316 }
    317 int32_t ModuleVideoRenderImpl::Process()
    318 {
    319     // Not used
    320     return 0;
    321 }
    322 
    323 void*
    324 ModuleVideoRenderImpl::Window()
    325 {
    326     CriticalSectionScoped cs(&_moduleCrit);
    327     return _ptrWindow;
    328 }
    329 
    330 int32_t ModuleVideoRenderImpl::ChangeWindow(void* window)
    331 {
    332 
    333     CriticalSectionScoped cs(&_moduleCrit);
    334 
    335 #if defined(WEBRTC_IOS) // WEBRTC_IOS must go before WEBRTC_MAC
    336     _ptrRenderer = NULL;
    337     delete _ptrRenderer;
    338 
    339     VideoRenderIosImpl* ptrRenderer;
    340     ptrRenderer = new VideoRenderIosImpl(_id, window, _fullScreen);
    341     if (!ptrRenderer)
    342     {
    343         return -1;
    344     }
    345     _ptrRenderer = reinterpret_cast<IVideoRender*>(ptrRenderer);
    346     return _ptrRenderer->ChangeWindow(window);
    347 #elif defined(WEBRTC_MAC)
    348 
    349     _ptrRenderer = NULL;
    350     delete _ptrRenderer;
    351 
    352 #if defined(COCOA_RENDERING)
    353     VideoRenderMacCocoaImpl* ptrRenderer;
    354     ptrRenderer = new VideoRenderMacCocoaImpl(_id, kRenderCocoa, window, _fullScreen);
    355 #elif defined(CARBON_RENDERING)
    356     VideoRenderMacCarbonImpl* ptrRenderer;
    357     ptrRenderer = new VideoRenderMacCarbonImpl(_id, kRenderCarbon, window, _fullScreen);
    358 #endif
    359     if (!ptrRenderer)
    360     {
    361         return -1;
    362     }
    363     _ptrRenderer = reinterpret_cast<IVideoRender*>(ptrRenderer);
    364     return _ptrRenderer->ChangeWindow(window);
    365 
    366 #else
    367     if (!_ptrRenderer)
    368     {
    369         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    370                      "%s: No renderer", __FUNCTION__);
    371         return -1;
    372     }
    373     return _ptrRenderer->ChangeWindow(window);
    374 
    375 #endif
    376 }
    377 
    378 int32_t ModuleVideoRenderImpl::Id()
    379 {
    380     CriticalSectionScoped cs(&_moduleCrit);
    381     return _id;
    382 }
    383 
    384 uint32_t ModuleVideoRenderImpl::GetIncomingFrameRate(const uint32_t streamId) {
    385   CriticalSectionScoped cs(&_moduleCrit);
    386 
    387   IncomingVideoStreamMap::iterator it = _streamRenderMap.find(streamId);
    388 
    389   if (it == _streamRenderMap.end()) {
    390     // This stream doesn't exist
    391     WEBRTC_TRACE(kTraceError,
    392                  kTraceVideoRenderer,
    393                  _id,
    394                  "%s: stream doesn't exist",
    395                  __FUNCTION__);
    396     return 0;
    397   }
    398   assert(it->second != NULL);
    399   return it->second->IncomingRate();
    400 }
    401 
    402 VideoRenderCallback*
    403 ModuleVideoRenderImpl::AddIncomingRenderStream(const uint32_t streamId,
    404                                                const uint32_t zOrder,
    405                                                const float left,
    406                                                const float top,
    407                                                const float right,
    408                                                const float bottom)
    409 {
    410     CriticalSectionScoped cs(&_moduleCrit);
    411 
    412     if (!_ptrRenderer)
    413     {
    414         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    415                      "%s: No renderer", __FUNCTION__);
    416         return NULL;
    417     }
    418 
    419     if (_streamRenderMap.find(streamId) != _streamRenderMap.end()) {
    420         // The stream already exists...
    421         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    422                      "%s: stream already exists", __FUNCTION__);
    423         return NULL;
    424     }
    425 
    426     VideoRenderCallback* ptrRenderCallback =
    427             _ptrRenderer->AddIncomingRenderStream(streamId, zOrder, left, top,
    428                                                   right, bottom);
    429     if (ptrRenderCallback == NULL)
    430     {
    431         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    432                      "%s: Can't create incoming stream in renderer",
    433                      __FUNCTION__);
    434         return NULL;
    435     }
    436 
    437     // Create platform independant code
    438     IncomingVideoStream* ptrIncomingStream = new IncomingVideoStream(_id,
    439                                                                      streamId);
    440     if (ptrIncomingStream == NULL)
    441     {
    442         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    443                      "%s: Can't create incoming stream", __FUNCTION__);
    444         return NULL;
    445     }
    446 
    447 
    448     if (ptrIncomingStream->SetRenderCallback(ptrRenderCallback) == -1)
    449     {
    450         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    451                      "%s: Can't set render callback", __FUNCTION__);
    452         delete ptrIncomingStream;
    453         _ptrRenderer->DeleteIncomingRenderStream(streamId);
    454         return NULL;
    455     }
    456 
    457     VideoRenderCallback* moduleCallback =
    458             ptrIncomingStream->ModuleCallback();
    459 
    460     // Store the stream
    461     _streamRenderMap[streamId] = ptrIncomingStream;
    462 
    463     return moduleCallback;
    464 }
    465 
    466 int32_t ModuleVideoRenderImpl::DeleteIncomingRenderStream(
    467                                                                 const uint32_t streamId)
    468 {
    469     CriticalSectionScoped cs(&_moduleCrit);
    470 
    471     if (!_ptrRenderer)
    472     {
    473         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    474                      "%s: No renderer", __FUNCTION__);
    475         return -1;
    476     }
    477 
    478     IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
    479     if (item == _streamRenderMap.end())
    480     {
    481         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    482                      "%s: stream doesn't exist", __FUNCTION__);
    483         return -1;
    484     }
    485 
    486     delete item->second;
    487 
    488     _ptrRenderer->DeleteIncomingRenderStream(streamId);
    489 
    490     _streamRenderMap.erase(item);
    491 
    492     return 0;
    493 }
    494 
    495 int32_t ModuleVideoRenderImpl::AddExternalRenderCallback(
    496     const uint32_t streamId,
    497     VideoRenderCallback* renderObject) {
    498     CriticalSectionScoped cs(&_moduleCrit);
    499 
    500     IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
    501 
    502     if (item == _streamRenderMap.end())
    503     {
    504         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    505                      "%s: stream doesn't exist", __FUNCTION__);
    506         return -1;
    507     }
    508 
    509     if (item->second == NULL) {
    510         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    511                      "%s: could not get stream", __FUNCTION__);
    512         return -1;
    513     }
    514     return item->second->SetExternalCallback(renderObject);
    515 }
    516 
    517 int32_t ModuleVideoRenderImpl::GetIncomingRenderStreamProperties(
    518     const uint32_t streamId,
    519     uint32_t& zOrder,
    520     float& left,
    521     float& top,
    522     float& right,
    523     float& bottom) const {
    524     CriticalSectionScoped cs(&_moduleCrit);
    525 
    526     if (!_ptrRenderer)
    527     {
    528         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    529                      "%s: No renderer", __FUNCTION__);
    530         return -1;
    531     }
    532 
    533     return _ptrRenderer->GetIncomingRenderStreamProperties(streamId, zOrder,
    534                                                            left, top, right,
    535                                                            bottom);
    536 }
    537 
    538 uint32_t ModuleVideoRenderImpl::GetNumIncomingRenderStreams() const
    539 {
    540     CriticalSectionScoped cs(&_moduleCrit);
    541 
    542     return static_cast<uint32_t>(_streamRenderMap.size());
    543 }
    544 
    545 bool ModuleVideoRenderImpl::HasIncomingRenderStream(
    546     const uint32_t streamId) const {
    547   CriticalSectionScoped cs(&_moduleCrit);
    548 
    549   return _streamRenderMap.find(streamId) != _streamRenderMap.end();
    550 }
    551 
    552 int32_t ModuleVideoRenderImpl::RegisterRawFrameCallback(
    553     const uint32_t streamId,
    554     VideoRenderCallback* callbackObj) {
    555   return -1;
    556 }
    557 
    558 int32_t ModuleVideoRenderImpl::StartRender(const uint32_t streamId)
    559 {
    560     CriticalSectionScoped cs(&_moduleCrit);
    561 
    562     if (!_ptrRenderer)
    563     {
    564         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    565                      "%s: No renderer", __FUNCTION__);
    566         return -1;
    567     }
    568 
    569     // Start the stream
    570     IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
    571 
    572     if (item == _streamRenderMap.end())
    573     {
    574         return -1;
    575     }
    576 
    577     if (item->second->Start() == -1)
    578     {
    579         return -1;
    580     }
    581 
    582     // Start the HW renderer
    583     if (_ptrRenderer->StartRender() == -1)
    584     {
    585         return -1;
    586     }
    587     return 0;
    588 }
    589 
    590 int32_t ModuleVideoRenderImpl::StopRender(const uint32_t streamId)
    591 {
    592     CriticalSectionScoped cs(&_moduleCrit);
    593 
    594     if (!_ptrRenderer)
    595     {
    596         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    597                      "%s(%d): No renderer", __FUNCTION__, streamId);
    598         return -1;
    599     }
    600 
    601     // Stop the incoming stream
    602     IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
    603 
    604     if (item == _streamRenderMap.end())
    605     {
    606         return -1;
    607     }
    608 
    609     if (item->second->Stop() == -1)
    610     {
    611         return -1;
    612     }
    613 
    614     return 0;
    615 }
    616 
    617 int32_t ModuleVideoRenderImpl::ResetRender()
    618 {
    619     CriticalSectionScoped cs(&_moduleCrit);
    620 
    621     int32_t ret = 0;
    622     // Loop through all incoming streams and reset them
    623     for (IncomingVideoStreamMap::iterator it = _streamRenderMap.begin();
    624          it != _streamRenderMap.end();
    625          ++it) {
    626       if (it->second->Reset() == -1)
    627         ret = -1;
    628     }
    629     return ret;
    630 }
    631 
    632 RawVideoType ModuleVideoRenderImpl::PreferredVideoType() const
    633 {
    634     CriticalSectionScoped cs(&_moduleCrit);
    635 
    636     if (_ptrRenderer == NULL)
    637     {
    638         return kVideoI420;
    639     }
    640 
    641     return _ptrRenderer->PerferedVideoType();
    642 }
    643 
    644 bool ModuleVideoRenderImpl::IsFullScreen()
    645 {
    646     CriticalSectionScoped cs(&_moduleCrit);
    647 
    648     if (!_ptrRenderer)
    649     {
    650         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    651                      "%s: No renderer", __FUNCTION__);
    652         return false;
    653     }
    654     return _ptrRenderer->FullScreen();
    655 }
    656 
    657 int32_t ModuleVideoRenderImpl::GetScreenResolution(
    658                                                          uint32_t& screenWidth,
    659                                                          uint32_t& screenHeight) const
    660 {
    661     CriticalSectionScoped cs(&_moduleCrit);
    662 
    663     if (!_ptrRenderer)
    664     {
    665         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    666                      "%s: No renderer", __FUNCTION__);
    667         return false;
    668     }
    669     return _ptrRenderer->GetScreenResolution(screenWidth, screenHeight);
    670 }
    671 
    672 uint32_t ModuleVideoRenderImpl::RenderFrameRate(
    673                                                       const uint32_t streamId)
    674 {
    675     CriticalSectionScoped cs(&_moduleCrit);
    676 
    677     if (!_ptrRenderer)
    678     {
    679         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    680                      "%s: No renderer", __FUNCTION__);
    681         return false;
    682     }
    683     return _ptrRenderer->RenderFrameRate(streamId);
    684 }
    685 
    686 int32_t ModuleVideoRenderImpl::SetStreamCropping(
    687                                                        const uint32_t streamId,
    688                                                        const float left,
    689                                                        const float top,
    690                                                        const float right,
    691                                                        const float bottom)
    692 {
    693     CriticalSectionScoped cs(&_moduleCrit);
    694 
    695     if (!_ptrRenderer)
    696     {
    697         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    698                      "%s: No renderer", __FUNCTION__);
    699         return false;
    700     }
    701     return _ptrRenderer->SetStreamCropping(streamId, left, top, right, bottom);
    702 }
    703 
    704 int32_t ModuleVideoRenderImpl::SetTransparentBackground(const bool enable)
    705 {
    706     CriticalSectionScoped cs(&_moduleCrit);
    707 
    708     if (!_ptrRenderer)
    709     {
    710         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    711                      "%s: No renderer", __FUNCTION__);
    712         return false;
    713     }
    714     return _ptrRenderer->SetTransparentBackground(enable);
    715 }
    716 
    717 int32_t ModuleVideoRenderImpl::FullScreenRender(void* window, const bool enable)
    718 {
    719     return -1;
    720 }
    721 
    722 int32_t ModuleVideoRenderImpl::SetText(
    723                                              const uint8_t textId,
    724                                              const uint8_t* text,
    725                                              const int32_t textLength,
    726                                              const uint32_t textColorRef,
    727                                              const uint32_t backgroundColorRef,
    728                                              const float left, const float top,
    729                                              const float right,
    730                                              const float bottom)
    731 {
    732     CriticalSectionScoped cs(&_moduleCrit);
    733 
    734     if (!_ptrRenderer)
    735     {
    736         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    737                      "%s: No renderer", __FUNCTION__);
    738         return -1;
    739     }
    740     return _ptrRenderer->SetText(textId, text, textLength, textColorRef,
    741                                  backgroundColorRef, left, top, right, bottom);
    742 }
    743 
    744 int32_t ModuleVideoRenderImpl::SetBitmap(const void* bitMap,
    745                                          const uint8_t pictureId,
    746                                          const void* colorKey,
    747                                          const float left,
    748                                          const float top,
    749                                          const float right,
    750                                          const float bottom)
    751 {
    752     CriticalSectionScoped cs(&_moduleCrit);
    753 
    754     if (!_ptrRenderer)
    755     {
    756         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    757                      "%s: No renderer", __FUNCTION__);
    758         return -1;
    759     }
    760     return _ptrRenderer->SetBitmap(bitMap, pictureId, colorKey, left, top,
    761                                    right, bottom);
    762 }
    763 
    764 int32_t ModuleVideoRenderImpl::GetLastRenderedFrame(
    765     const uint32_t streamId,
    766     I420VideoFrame &frame) const
    767 {
    768     CriticalSectionScoped cs(&_moduleCrit);
    769 
    770     if (!_ptrRenderer)
    771     {
    772         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    773                      "%s: No renderer", __FUNCTION__);
    774         return -1;
    775     }
    776 
    777     IncomingVideoStreamMap::const_iterator item =
    778         _streamRenderMap.find(streamId);
    779     if (item == _streamRenderMap.end())
    780     {
    781         // This stream doesn't exist
    782         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    783                      "%s: stream doesn't exist", __FUNCTION__);
    784         return 0;
    785     }
    786 
    787     assert(item->second != NULL);
    788     return item->second->GetLastRenderedFrame(frame);
    789 }
    790 
    791 int32_t ModuleVideoRenderImpl::SetExpectedRenderDelay(
    792     uint32_t stream_id, int32_t delay_ms) {
    793   CriticalSectionScoped cs(&_moduleCrit);
    794 
    795   if (!_ptrRenderer) {
    796     WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    797                  "%s: No renderer", __FUNCTION__);
    798     return false;
    799   }
    800 
    801   IncomingVideoStreamMap::const_iterator item =
    802       _streamRenderMap.find(stream_id);
    803   if (item == _streamRenderMap.end()) {
    804     // This stream doesn't exist
    805     WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    806                  "%s(%u, %d): stream doesn't exist", __FUNCTION__, stream_id,
    807                  delay_ms);
    808     return -1;
    809   }
    810 
    811   assert(item->second != NULL);
    812   return item->second->SetExpectedRenderDelay(delay_ms);
    813 }
    814 
    815 int32_t ModuleVideoRenderImpl::ConfigureRenderer(
    816                                                        const uint32_t streamId,
    817                                                        const unsigned int zOrder,
    818                                                        const float left,
    819                                                        const float top,
    820                                                        const float right,
    821                                                        const float bottom)
    822 {
    823     CriticalSectionScoped cs(&_moduleCrit);
    824 
    825     if (!_ptrRenderer)
    826     {
    827         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    828                      "%s: No renderer", __FUNCTION__);
    829         return false;
    830     }
    831     return _ptrRenderer->ConfigureRenderer(streamId, zOrder, left, top, right,
    832                                            bottom);
    833 }
    834 
    835 int32_t ModuleVideoRenderImpl::SetStartImage(
    836     const uint32_t streamId,
    837     const I420VideoFrame& videoFrame)
    838 {
    839     CriticalSectionScoped cs(&_moduleCrit);
    840 
    841     if (!_ptrRenderer)
    842     {
    843         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    844                      "%s: No renderer", __FUNCTION__);
    845         return -1;
    846     }
    847 
    848     IncomingVideoStreamMap::const_iterator item =
    849         _streamRenderMap.find(streamId);
    850     if (item == _streamRenderMap.end())
    851     {
    852         // This stream doesn't exist
    853         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    854                      "%s: stream doesn't exist", __FUNCTION__);
    855         return -1;
    856     }
    857     assert (item->second != NULL);
    858     return item->second->SetStartImage(videoFrame);
    859 
    860 }
    861 
    862 int32_t ModuleVideoRenderImpl::SetTimeoutImage(
    863     const uint32_t streamId,
    864     const I420VideoFrame& videoFrame,
    865     const uint32_t timeout)
    866 {
    867     CriticalSectionScoped cs(&_moduleCrit);
    868 
    869     if (!_ptrRenderer)
    870     {
    871         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    872                      "%s: No renderer", __FUNCTION__);
    873         return -1;
    874     }
    875 
    876     IncomingVideoStreamMap::const_iterator item =
    877         _streamRenderMap.find(streamId);
    878     if (item == _streamRenderMap.end())
    879     {
    880         // This stream doesn't exist
    881         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    882                      "%s: stream doesn't exist", __FUNCTION__);
    883         return -1;
    884     }
    885     assert(item->second != NULL);
    886     return item->second->SetTimeoutImage(videoFrame, timeout);
    887 }
    888 
    889 int32_t ModuleVideoRenderImpl::MirrorRenderStream(const int renderId,
    890                                                   const bool enable,
    891                                                   const bool mirrorXAxis,
    892                                                   const bool mirrorYAxis)
    893 {
    894     CriticalSectionScoped cs(&_moduleCrit);
    895 
    896     if (!_ptrRenderer)
    897     {
    898         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    899                      "%s: No renderer", __FUNCTION__);
    900         return -1;
    901     }
    902 
    903     IncomingVideoStreamMap::const_iterator item =
    904         _streamRenderMap.find(renderId);
    905     if (item == _streamRenderMap.end())
    906     {
    907         // This stream doesn't exist
    908         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    909                      "%s: stream doesn't exist", __FUNCTION__);
    910         return 0;
    911     }
    912     assert(item->second != NULL);
    913 
    914     return item->second->EnableMirroring(enable, mirrorXAxis, mirrorYAxis);
    915 }
    916 
    917 }  // namespace webrtc
    918