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