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
59namespace webrtc {
60
61VideoRender*
62VideoRender::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
76void VideoRender::DestroyVideoRender(
77                                                         VideoRender* module)
78{
79    if (module)
80    {
81        delete module;
82    }
83}
84
85ModuleVideoRenderImpl::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
207ModuleVideoRenderImpl::~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
297int32_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
312int32_t ModuleVideoRenderImpl::TimeUntilNextProcess()
313{
314    // Not used
315    return 50;
316}
317int32_t ModuleVideoRenderImpl::Process()
318{
319    // Not used
320    return 0;
321}
322
323void*
324ModuleVideoRenderImpl::Window()
325{
326    CriticalSectionScoped cs(&_moduleCrit);
327    return _ptrWindow;
328}
329
330int32_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
378int32_t ModuleVideoRenderImpl::Id()
379{
380    CriticalSectionScoped cs(&_moduleCrit);
381    return _id;
382}
383
384uint32_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
402VideoRenderCallback*
403ModuleVideoRenderImpl::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
466int32_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
495int32_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
517int32_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
538uint32_t ModuleVideoRenderImpl::GetNumIncomingRenderStreams() const
539{
540    CriticalSectionScoped cs(&_moduleCrit);
541
542    return static_cast<uint32_t>(_streamRenderMap.size());
543}
544
545bool ModuleVideoRenderImpl::HasIncomingRenderStream(
546    const uint32_t streamId) const {
547  CriticalSectionScoped cs(&_moduleCrit);
548
549  return _streamRenderMap.find(streamId) != _streamRenderMap.end();
550}
551
552int32_t ModuleVideoRenderImpl::RegisterRawFrameCallback(
553    const uint32_t streamId,
554    VideoRenderCallback* callbackObj) {
555  return -1;
556}
557
558int32_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
590int32_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
617int32_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
632RawVideoType 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
644bool 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
657int32_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
672uint32_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
686int32_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
704int32_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
717int32_t ModuleVideoRenderImpl::FullScreenRender(void* window, const bool enable)
718{
719    return -1;
720}
721
722int32_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
744int32_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
764int32_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
791int32_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
815int32_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
835int32_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
862int32_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
889int32_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