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/common_video/include/incoming_video_stream.h"
14#include "webrtc/engine_configurations.h"
15#include "webrtc/modules/video_render/i_video_render.h"
16#include "webrtc/modules/video_render/video_render_defines.h"
17#include "webrtc/modules/video_render/video_render_impl.h"
18#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
19#include "webrtc/system_wrappers/include/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
297int64_t ModuleVideoRenderImpl::TimeUntilNextProcess()
298{
299    // Not used
300    return 50;
301}
302int32_t ModuleVideoRenderImpl::Process()
303{
304    // Not used
305    return 0;
306}
307
308void*
309ModuleVideoRenderImpl::Window()
310{
311    CriticalSectionScoped cs(&_moduleCrit);
312    return _ptrWindow;
313}
314
315int32_t ModuleVideoRenderImpl::ChangeWindow(void* window)
316{
317
318    CriticalSectionScoped cs(&_moduleCrit);
319
320#if defined(WEBRTC_IOS) // WEBRTC_IOS must go before WEBRTC_MAC
321    _ptrRenderer = NULL;
322    delete _ptrRenderer;
323
324    VideoRenderIosImpl* ptrRenderer;
325    ptrRenderer = new VideoRenderIosImpl(_id, window, _fullScreen);
326    if (!ptrRenderer)
327    {
328        return -1;
329    }
330    _ptrRenderer = reinterpret_cast<IVideoRender*>(ptrRenderer);
331    return _ptrRenderer->ChangeWindow(window);
332#elif defined(WEBRTC_MAC)
333
334    _ptrRenderer = NULL;
335    delete _ptrRenderer;
336
337#if defined(COCOA_RENDERING)
338    VideoRenderMacCocoaImpl* ptrRenderer;
339    ptrRenderer = new VideoRenderMacCocoaImpl(_id, kRenderCocoa, window, _fullScreen);
340#elif defined(CARBON_RENDERING)
341    VideoRenderMacCarbonImpl* ptrRenderer;
342    ptrRenderer = new VideoRenderMacCarbonImpl(_id, kRenderCarbon, window, _fullScreen);
343#endif
344    if (!ptrRenderer)
345    {
346        return -1;
347    }
348    _ptrRenderer = reinterpret_cast<IVideoRender*>(ptrRenderer);
349    return _ptrRenderer->ChangeWindow(window);
350
351#else
352    if (!_ptrRenderer)
353    {
354        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
355                     "%s: No renderer", __FUNCTION__);
356        return -1;
357    }
358    return _ptrRenderer->ChangeWindow(window);
359
360#endif
361}
362
363int32_t ModuleVideoRenderImpl::Id()
364{
365    CriticalSectionScoped cs(&_moduleCrit);
366    return _id;
367}
368
369uint32_t ModuleVideoRenderImpl::GetIncomingFrameRate(const uint32_t streamId) {
370  CriticalSectionScoped cs(&_moduleCrit);
371
372  IncomingVideoStreamMap::iterator it = _streamRenderMap.find(streamId);
373
374  if (it == _streamRenderMap.end()) {
375    // This stream doesn't exist
376    WEBRTC_TRACE(kTraceError,
377                 kTraceVideoRenderer,
378                 _id,
379                 "%s: stream doesn't exist",
380                 __FUNCTION__);
381    return 0;
382  }
383  assert(it->second != NULL);
384  return it->second->IncomingRate();
385}
386
387VideoRenderCallback*
388ModuleVideoRenderImpl::AddIncomingRenderStream(const uint32_t streamId,
389                                               const uint32_t zOrder,
390                                               const float left,
391                                               const float top,
392                                               const float right,
393                                               const float bottom)
394{
395    CriticalSectionScoped cs(&_moduleCrit);
396
397    if (!_ptrRenderer)
398    {
399        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
400                     "%s: No renderer", __FUNCTION__);
401        return NULL;
402    }
403
404    if (_streamRenderMap.find(streamId) != _streamRenderMap.end()) {
405        // The stream already exists...
406        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
407                     "%s: stream already exists", __FUNCTION__);
408        return NULL;
409    }
410
411    VideoRenderCallback* ptrRenderCallback =
412            _ptrRenderer->AddIncomingRenderStream(streamId, zOrder, left, top,
413                                                  right, bottom);
414    if (ptrRenderCallback == NULL)
415    {
416        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
417                     "%s: Can't create incoming stream in renderer",
418                     __FUNCTION__);
419        return NULL;
420    }
421
422    // Create platform independant code
423    IncomingVideoStream* ptrIncomingStream =
424        new IncomingVideoStream(streamId, false);
425    ptrIncomingStream->SetRenderCallback(ptrRenderCallback);
426    VideoRenderCallback* moduleCallback = ptrIncomingStream->ModuleCallback();
427
428    // Store the stream
429    _streamRenderMap[streamId] = ptrIncomingStream;
430
431    return moduleCallback;
432}
433
434int32_t ModuleVideoRenderImpl::DeleteIncomingRenderStream(
435                                                                const uint32_t streamId)
436{
437    CriticalSectionScoped cs(&_moduleCrit);
438
439    if (!_ptrRenderer)
440    {
441        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
442                     "%s: No renderer", __FUNCTION__);
443        return -1;
444    }
445
446    IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
447    if (item == _streamRenderMap.end())
448    {
449        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
450                     "%s: stream doesn't exist", __FUNCTION__);
451        return -1;
452    }
453
454    delete item->second;
455
456    _ptrRenderer->DeleteIncomingRenderStream(streamId);
457
458    _streamRenderMap.erase(item);
459
460    return 0;
461}
462
463int32_t ModuleVideoRenderImpl::AddExternalRenderCallback(
464    const uint32_t streamId,
465    VideoRenderCallback* renderObject) {
466    CriticalSectionScoped cs(&_moduleCrit);
467
468    IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
469
470    if (item == _streamRenderMap.end())
471    {
472        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
473                     "%s: stream doesn't exist", __FUNCTION__);
474        return -1;
475    }
476
477    if (item->second == NULL) {
478        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
479                     "%s: could not get stream", __FUNCTION__);
480        return -1;
481    }
482    item->second->SetExternalCallback(renderObject);
483    return 0;
484}
485
486int32_t ModuleVideoRenderImpl::GetIncomingRenderStreamProperties(
487    const uint32_t streamId,
488    uint32_t& zOrder,
489    float& left,
490    float& top,
491    float& right,
492    float& bottom) const {
493    CriticalSectionScoped cs(&_moduleCrit);
494
495    if (!_ptrRenderer)
496    {
497        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
498                     "%s: No renderer", __FUNCTION__);
499        return -1;
500    }
501
502    return _ptrRenderer->GetIncomingRenderStreamProperties(streamId, zOrder,
503                                                           left, top, right,
504                                                           bottom);
505}
506
507uint32_t ModuleVideoRenderImpl::GetNumIncomingRenderStreams() const
508{
509    CriticalSectionScoped cs(&_moduleCrit);
510
511    return static_cast<uint32_t>(_streamRenderMap.size());
512}
513
514bool ModuleVideoRenderImpl::HasIncomingRenderStream(
515    const uint32_t streamId) const {
516  CriticalSectionScoped cs(&_moduleCrit);
517
518  return _streamRenderMap.find(streamId) != _streamRenderMap.end();
519}
520
521int32_t ModuleVideoRenderImpl::RegisterRawFrameCallback(
522    const uint32_t streamId,
523    VideoRenderCallback* callbackObj) {
524  return -1;
525}
526
527int32_t ModuleVideoRenderImpl::StartRender(const uint32_t streamId)
528{
529    CriticalSectionScoped cs(&_moduleCrit);
530
531    if (!_ptrRenderer)
532    {
533        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
534                     "%s: No renderer", __FUNCTION__);
535        return -1;
536    }
537
538    // Start the stream
539    IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
540
541    if (item == _streamRenderMap.end())
542    {
543        return -1;
544    }
545
546    if (item->second->Start() == -1)
547    {
548        return -1;
549    }
550
551    // Start the HW renderer
552    if (_ptrRenderer->StartRender() == -1)
553    {
554        return -1;
555    }
556    return 0;
557}
558
559int32_t ModuleVideoRenderImpl::StopRender(const uint32_t streamId)
560{
561    CriticalSectionScoped cs(&_moduleCrit);
562
563    if (!_ptrRenderer)
564    {
565        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
566                     "%s(%d): No renderer", __FUNCTION__, streamId);
567        return -1;
568    }
569
570    // Stop the incoming stream
571    IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
572
573    if (item == _streamRenderMap.end())
574    {
575        return -1;
576    }
577
578    if (item->second->Stop() == -1)
579    {
580        return -1;
581    }
582
583    return 0;
584}
585
586int32_t ModuleVideoRenderImpl::ResetRender()
587{
588    CriticalSectionScoped cs(&_moduleCrit);
589
590    int32_t ret = 0;
591    // Loop through all incoming streams and reset them
592    for (IncomingVideoStreamMap::iterator it = _streamRenderMap.begin();
593         it != _streamRenderMap.end();
594         ++it) {
595      if (it->second->Reset() == -1)
596        ret = -1;
597    }
598    return ret;
599}
600
601RawVideoType ModuleVideoRenderImpl::PreferredVideoType() const
602{
603    CriticalSectionScoped cs(&_moduleCrit);
604
605    if (_ptrRenderer == NULL)
606    {
607        return kVideoI420;
608    }
609
610    return _ptrRenderer->PerferedVideoType();
611}
612
613bool ModuleVideoRenderImpl::IsFullScreen()
614{
615    CriticalSectionScoped cs(&_moduleCrit);
616
617    if (!_ptrRenderer)
618    {
619        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
620                     "%s: No renderer", __FUNCTION__);
621        return false;
622    }
623    return _ptrRenderer->FullScreen();
624}
625
626int32_t ModuleVideoRenderImpl::GetScreenResolution(
627                                                         uint32_t& screenWidth,
628                                                         uint32_t& screenHeight) const
629{
630    CriticalSectionScoped cs(&_moduleCrit);
631
632    if (!_ptrRenderer)
633    {
634        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
635                     "%s: No renderer", __FUNCTION__);
636        return false;
637    }
638    return _ptrRenderer->GetScreenResolution(screenWidth, screenHeight);
639}
640
641uint32_t ModuleVideoRenderImpl::RenderFrameRate(
642                                                      const uint32_t streamId)
643{
644    CriticalSectionScoped cs(&_moduleCrit);
645
646    if (!_ptrRenderer)
647    {
648        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
649                     "%s: No renderer", __FUNCTION__);
650        return false;
651    }
652    return _ptrRenderer->RenderFrameRate(streamId);
653}
654
655int32_t ModuleVideoRenderImpl::SetStreamCropping(
656                                                       const uint32_t streamId,
657                                                       const float left,
658                                                       const float top,
659                                                       const float right,
660                                                       const float bottom)
661{
662    CriticalSectionScoped cs(&_moduleCrit);
663
664    if (!_ptrRenderer)
665    {
666        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
667                     "%s: No renderer", __FUNCTION__);
668        return false;
669    }
670    return _ptrRenderer->SetStreamCropping(streamId, left, top, right, bottom);
671}
672
673int32_t ModuleVideoRenderImpl::SetTransparentBackground(const bool enable)
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->SetTransparentBackground(enable);
684}
685
686int32_t ModuleVideoRenderImpl::FullScreenRender(void* window, const bool enable)
687{
688    return -1;
689}
690
691int32_t ModuleVideoRenderImpl::SetText(
692                                             const uint8_t textId,
693                                             const uint8_t* text,
694                                             const int32_t textLength,
695                                             const uint32_t textColorRef,
696                                             const uint32_t backgroundColorRef,
697                                             const float left, const float top,
698                                             const float right,
699                                             const float bottom)
700{
701    CriticalSectionScoped cs(&_moduleCrit);
702
703    if (!_ptrRenderer)
704    {
705        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
706                     "%s: No renderer", __FUNCTION__);
707        return -1;
708    }
709    return _ptrRenderer->SetText(textId, text, textLength, textColorRef,
710                                 backgroundColorRef, left, top, right, bottom);
711}
712
713int32_t ModuleVideoRenderImpl::SetBitmap(const void* bitMap,
714                                         const uint8_t pictureId,
715                                         const void* colorKey,
716                                         const float left,
717                                         const float top,
718                                         const float right,
719                                         const float bottom)
720{
721    CriticalSectionScoped cs(&_moduleCrit);
722
723    if (!_ptrRenderer)
724    {
725        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
726                     "%s: No renderer", __FUNCTION__);
727        return -1;
728    }
729    return _ptrRenderer->SetBitmap(bitMap, pictureId, colorKey, left, top,
730                                   right, bottom);
731}
732
733int32_t ModuleVideoRenderImpl::SetExpectedRenderDelay(
734    uint32_t stream_id, int32_t delay_ms) {
735  CriticalSectionScoped cs(&_moduleCrit);
736
737  if (!_ptrRenderer) {
738    WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
739                 "%s: No renderer", __FUNCTION__);
740    return false;
741  }
742
743  IncomingVideoStreamMap::const_iterator item =
744      _streamRenderMap.find(stream_id);
745  if (item == _streamRenderMap.end()) {
746    // This stream doesn't exist
747    WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
748                 "%s(%u, %d): stream doesn't exist", __FUNCTION__, stream_id,
749                 delay_ms);
750    return -1;
751  }
752
753  assert(item->second != NULL);
754  return item->second->SetExpectedRenderDelay(delay_ms);
755}
756
757int32_t ModuleVideoRenderImpl::ConfigureRenderer(
758                                                       const uint32_t streamId,
759                                                       const unsigned int zOrder,
760                                                       const float left,
761                                                       const float top,
762                                                       const float right,
763                                                       const float bottom)
764{
765    CriticalSectionScoped cs(&_moduleCrit);
766
767    if (!_ptrRenderer)
768    {
769        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
770                     "%s: No renderer", __FUNCTION__);
771        return false;
772    }
773    return _ptrRenderer->ConfigureRenderer(streamId, zOrder, left, top, right,
774                                           bottom);
775}
776
777int32_t ModuleVideoRenderImpl::SetStartImage(const uint32_t streamId,
778                                             const VideoFrame& videoFrame) {
779    CriticalSectionScoped cs(&_moduleCrit);
780
781    if (!_ptrRenderer)
782    {
783        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
784                     "%s: No renderer", __FUNCTION__);
785        return -1;
786    }
787
788    IncomingVideoStreamMap::const_iterator item =
789        _streamRenderMap.find(streamId);
790    if (item == _streamRenderMap.end())
791    {
792        // This stream doesn't exist
793        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
794                     "%s: stream doesn't exist", __FUNCTION__);
795        return -1;
796    }
797    assert (item->second != NULL);
798    return item->second->SetStartImage(videoFrame);
799
800}
801
802int32_t ModuleVideoRenderImpl::SetTimeoutImage(const uint32_t streamId,
803                                               const VideoFrame& videoFrame,
804                                               const uint32_t timeout) {
805    CriticalSectionScoped cs(&_moduleCrit);
806
807    if (!_ptrRenderer)
808    {
809        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
810                     "%s: No renderer", __FUNCTION__);
811        return -1;
812    }
813
814    IncomingVideoStreamMap::const_iterator item =
815        _streamRenderMap.find(streamId);
816    if (item == _streamRenderMap.end())
817    {
818        // This stream doesn't exist
819        WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
820                     "%s: stream doesn't exist", __FUNCTION__);
821        return -1;
822    }
823    assert(item->second != NULL);
824    return item->second->SetTimeoutImage(videoFrame, timeout);
825}
826
827}  // namespace webrtc
828