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/external/video_render_external_impl.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/i_video_render.h"
     18 #include "webrtc/modules/video_render/video_render_impl.h"
     19 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
     20 #include "webrtc/system_wrappers/interface/trace.h"
     21 
     22 namespace webrtc {
     23 
     24 VideoRender*
     25 VideoRender::CreateVideoRender(const int32_t id,
     26                                void* window,
     27                                const bool fullscreen,
     28                                const VideoRenderType videoRenderType/*=kRenderDefault*/)
     29 {
     30     VideoRenderType resultVideoRenderType = videoRenderType;
     31     if (videoRenderType == kRenderDefault)
     32     {
     33         resultVideoRenderType = kRenderExternal;
     34     }
     35     return new ModuleVideoRenderImpl(id, resultVideoRenderType, window,
     36                                      fullscreen);
     37 }
     38 
     39 void VideoRender::DestroyVideoRender(
     40                                                          VideoRender* module)
     41 {
     42     if (module)
     43     {
     44         delete module;
     45     }
     46 }
     47 
     48 ModuleVideoRenderImpl::ModuleVideoRenderImpl(
     49                                              const int32_t id,
     50                                              const VideoRenderType videoRenderType,
     51                                              void* window,
     52                                              const bool fullscreen) :
     53     _id(id), _moduleCrit(*CriticalSectionWrapper::CreateCriticalSection()),
     54     _ptrWindow(window), _fullScreen(fullscreen), _ptrRenderer(NULL)
     55 {
     56 
     57     // Create platform specific renderer
     58     switch (videoRenderType)
     59     {
     60         case kRenderExternal:
     61         {
     62             VideoRenderExternalImpl* ptrRenderer(NULL);
     63             ptrRenderer = new VideoRenderExternalImpl(_id, videoRenderType,
     64                                                       window, _fullScreen);
     65             if (ptrRenderer)
     66             {
     67                 _ptrRenderer = reinterpret_cast<IVideoRender*> (ptrRenderer);
     68             }
     69         }
     70             break;
     71         default:
     72             // Error...
     73             break;
     74     }
     75     if (_ptrRenderer)
     76     {
     77         if (_ptrRenderer->Init() == -1)
     78         {
     79         }
     80     }
     81 }
     82 
     83 ModuleVideoRenderImpl::~ModuleVideoRenderImpl()
     84 {
     85     delete &_moduleCrit;
     86 
     87     for (IncomingVideoStreamMap::iterator it = _streamRenderMap.begin();
     88          it != _streamRenderMap.end();
     89          ++it) {
     90       delete it->second;
     91     }
     92 
     93     // Delete platform specific renderer
     94     if (_ptrRenderer)
     95     {
     96         VideoRenderType videoRenderType = _ptrRenderer->RenderType();
     97 
     98         switch (videoRenderType)
     99         {
    100             case kRenderExternal:
    101             {
    102                 VideoRenderExternalImpl
    103                         * ptrRenderer =
    104                                 reinterpret_cast<VideoRenderExternalImpl*> (_ptrRenderer);
    105                 _ptrRenderer = NULL;
    106                 delete ptrRenderer;
    107             }
    108             break;
    109 
    110             default:
    111                 // Error...
    112                 break;
    113         }
    114     }
    115 }
    116 
    117 int32_t ModuleVideoRenderImpl::ChangeUniqueId(const int32_t id)
    118 {
    119 
    120     CriticalSectionScoped cs(&_moduleCrit);
    121 
    122     _id = id;
    123 
    124     if (_ptrRenderer)
    125     {
    126         _ptrRenderer->ChangeUniqueId(_id);
    127     }
    128 
    129     return 0;
    130 }
    131 
    132 int32_t ModuleVideoRenderImpl::TimeUntilNextProcess()
    133 {
    134     // Not used
    135     return 50;
    136 }
    137 int32_t ModuleVideoRenderImpl::Process()
    138 {
    139     // Not used
    140     return 0;
    141 }
    142 
    143 void*
    144 ModuleVideoRenderImpl::Window()
    145 {
    146     CriticalSectionScoped cs(&_moduleCrit);
    147     return _ptrWindow;
    148 }
    149 
    150 int32_t ModuleVideoRenderImpl::ChangeWindow(void* window)
    151 {
    152     return -1;
    153 }
    154 
    155 int32_t ModuleVideoRenderImpl::Id()
    156 {
    157     CriticalSectionScoped cs(&_moduleCrit);
    158     return _id;
    159 }
    160 
    161 uint32_t ModuleVideoRenderImpl::GetIncomingFrameRate(const uint32_t streamId) {
    162   CriticalSectionScoped cs(&_moduleCrit);
    163 
    164   IncomingVideoStreamMap::iterator it = _streamRenderMap.find(streamId);
    165 
    166   if (it == _streamRenderMap.end()) {
    167     // This stream doesn't exist
    168     WEBRTC_TRACE(kTraceError,
    169                  kTraceVideoRenderer,
    170                  _id,
    171                  "%s: stream doesn't exist",
    172                  __FUNCTION__);
    173     return 0;
    174   }
    175   assert(it->second != NULL);
    176   return it->second->IncomingRate();
    177 }
    178 
    179 VideoRenderCallback*
    180 ModuleVideoRenderImpl::AddIncomingRenderStream(const uint32_t streamId,
    181                                                const uint32_t zOrder,
    182                                                const float left,
    183                                                const float top,
    184                                                const float right,
    185                                                const float bottom)
    186 {
    187     CriticalSectionScoped cs(&_moduleCrit);
    188 
    189     if (!_ptrRenderer)
    190     {
    191         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    192                      "%s: No renderer", __FUNCTION__);
    193         return NULL;
    194     }
    195 
    196     if (_streamRenderMap.find(streamId) != _streamRenderMap.end()) {
    197         // The stream already exists...
    198         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    199                      "%s: stream already exists", __FUNCTION__);
    200         return NULL;
    201     }
    202 
    203     VideoRenderCallback* ptrRenderCallback =
    204             _ptrRenderer->AddIncomingRenderStream(streamId, zOrder, left, top,
    205                                                   right, bottom);
    206     if (ptrRenderCallback == NULL)
    207     {
    208         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    209                      "%s: Can't create incoming stream in renderer",
    210                      __FUNCTION__);
    211         return NULL;
    212     }
    213 
    214     // Create platform independant code
    215     IncomingVideoStream* ptrIncomingStream = new IncomingVideoStream(_id,
    216                                                                      streamId);
    217     if (ptrIncomingStream == NULL)
    218     {
    219         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    220                      "%s: Can't create incoming stream", __FUNCTION__);
    221         return NULL;
    222     }
    223 
    224 
    225     if (ptrIncomingStream->SetRenderCallback(ptrRenderCallback) == -1)
    226     {
    227         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    228                      "%s: Can't set render callback", __FUNCTION__);
    229         delete ptrIncomingStream;
    230         _ptrRenderer->DeleteIncomingRenderStream(streamId);
    231         return NULL;
    232     }
    233 
    234     VideoRenderCallback* moduleCallback =
    235             ptrIncomingStream->ModuleCallback();
    236 
    237     // Store the stream
    238     _streamRenderMap[streamId] = ptrIncomingStream;
    239 
    240     return moduleCallback;
    241 }
    242 
    243 int32_t ModuleVideoRenderImpl::DeleteIncomingRenderStream(
    244                                                                 const uint32_t streamId)
    245 {
    246     CriticalSectionScoped cs(&_moduleCrit);
    247 
    248     if (!_ptrRenderer)
    249     {
    250         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    251                      "%s: No renderer", __FUNCTION__);
    252         return -1;
    253     }
    254 
    255     IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
    256     if (item == _streamRenderMap.end())
    257     {
    258         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    259                      "%s: stream doesn't exist", __FUNCTION__);
    260         return -1;
    261     }
    262 
    263     delete item->second;
    264 
    265     _ptrRenderer->DeleteIncomingRenderStream(streamId);
    266 
    267     _streamRenderMap.erase(item);
    268 
    269     return 0;
    270 }
    271 
    272 int32_t ModuleVideoRenderImpl::AddExternalRenderCallback(
    273     const uint32_t streamId,
    274     VideoRenderCallback* renderObject) {
    275     CriticalSectionScoped cs(&_moduleCrit);
    276 
    277     IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
    278 
    279     if (item == _streamRenderMap.end())
    280     {
    281         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    282                      "%s: stream doesn't exist", __FUNCTION__);
    283         return -1;
    284     }
    285 
    286     if (item->second == NULL) {
    287         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    288                      "%s: could not get stream", __FUNCTION__);
    289         return -1;
    290     }
    291     return item->second->SetExternalCallback(renderObject);
    292 }
    293 
    294 int32_t ModuleVideoRenderImpl::GetIncomingRenderStreamProperties(
    295     const uint32_t streamId,
    296     uint32_t& zOrder,
    297     float& left,
    298     float& top,
    299     float& right,
    300     float& bottom) const {
    301     CriticalSectionScoped cs(&_moduleCrit);
    302 
    303     if (!_ptrRenderer)
    304     {
    305         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    306                      "%s: No renderer", __FUNCTION__);
    307         return -1;
    308     }
    309 
    310     return _ptrRenderer->GetIncomingRenderStreamProperties(streamId, zOrder,
    311                                                            left, top, right,
    312                                                            bottom);
    313 }
    314 
    315 uint32_t ModuleVideoRenderImpl::GetNumIncomingRenderStreams() const
    316 {
    317     CriticalSectionScoped cs(&_moduleCrit);
    318 
    319     return static_cast<uint32_t>(_streamRenderMap.size());
    320 }
    321 
    322 bool ModuleVideoRenderImpl::HasIncomingRenderStream(
    323     const uint32_t streamId) const {
    324   CriticalSectionScoped cs(&_moduleCrit);
    325 
    326   return _streamRenderMap.find(streamId) != _streamRenderMap.end();
    327 }
    328 
    329 int32_t ModuleVideoRenderImpl::RegisterRawFrameCallback(
    330     const uint32_t streamId,
    331     VideoRenderCallback* callbackObj) {
    332   return -1;
    333 }
    334 
    335 int32_t ModuleVideoRenderImpl::StartRender(const uint32_t streamId)
    336 {
    337     CriticalSectionScoped cs(&_moduleCrit);
    338 
    339     if (!_ptrRenderer)
    340     {
    341         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    342                      "%s: No renderer", __FUNCTION__);
    343         return -1;
    344     }
    345 
    346     // Start the stream
    347     IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
    348 
    349     if (item == _streamRenderMap.end())
    350     {
    351         return -1;
    352     }
    353 
    354     if (item->second->Start() == -1)
    355     {
    356         return -1;
    357     }
    358 
    359     // Start the HW renderer
    360     if (_ptrRenderer->StartRender() == -1)
    361     {
    362         return -1;
    363     }
    364     return 0;
    365 }
    366 
    367 int32_t ModuleVideoRenderImpl::StopRender(const uint32_t streamId)
    368 {
    369     CriticalSectionScoped cs(&_moduleCrit);
    370 
    371     if (!_ptrRenderer)
    372     {
    373         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    374                      "%s(%d): No renderer", __FUNCTION__, streamId);
    375         return -1;
    376     }
    377 
    378     // Stop the incoming stream
    379     IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId);
    380 
    381     if (item == _streamRenderMap.end())
    382     {
    383         return -1;
    384     }
    385 
    386     if (item->second->Stop() == -1)
    387     {
    388         return -1;
    389     }
    390 
    391     return 0;
    392 }
    393 
    394 int32_t ModuleVideoRenderImpl::ResetRender()
    395 {
    396     CriticalSectionScoped cs(&_moduleCrit);
    397 
    398     int32_t ret = 0;
    399     // Loop through all incoming streams and reset them
    400     for (IncomingVideoStreamMap::iterator it = _streamRenderMap.begin();
    401          it != _streamRenderMap.end();
    402          ++it) {
    403       if (it->second->Reset() == -1)
    404         ret = -1;
    405     }
    406     return ret;
    407 }
    408 
    409 RawVideoType ModuleVideoRenderImpl::PreferredVideoType() const
    410 {
    411     CriticalSectionScoped cs(&_moduleCrit);
    412 
    413     if (_ptrRenderer == NULL)
    414     {
    415         return kVideoI420;
    416     }
    417 
    418     return _ptrRenderer->PerferedVideoType();
    419 }
    420 
    421 bool ModuleVideoRenderImpl::IsFullScreen()
    422 {
    423     CriticalSectionScoped cs(&_moduleCrit);
    424 
    425     if (!_ptrRenderer)
    426     {
    427         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    428                      "%s: No renderer", __FUNCTION__);
    429         return false;
    430     }
    431     return _ptrRenderer->FullScreen();
    432 }
    433 
    434 int32_t ModuleVideoRenderImpl::GetScreenResolution(
    435                                                          uint32_t& screenWidth,
    436                                                          uint32_t& screenHeight) const
    437 {
    438     CriticalSectionScoped cs(&_moduleCrit);
    439 
    440     if (!_ptrRenderer)
    441     {
    442         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    443                      "%s: No renderer", __FUNCTION__);
    444         return false;
    445     }
    446     return _ptrRenderer->GetScreenResolution(screenWidth, screenHeight);
    447 }
    448 
    449 uint32_t ModuleVideoRenderImpl::RenderFrameRate(
    450                                                       const uint32_t streamId)
    451 {
    452     CriticalSectionScoped cs(&_moduleCrit);
    453 
    454     if (!_ptrRenderer)
    455     {
    456         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    457                      "%s: No renderer", __FUNCTION__);
    458         return false;
    459     }
    460     return _ptrRenderer->RenderFrameRate(streamId);
    461 }
    462 
    463 int32_t ModuleVideoRenderImpl::SetStreamCropping(
    464                                                        const uint32_t streamId,
    465                                                        const float left,
    466                                                        const float top,
    467                                                        const float right,
    468                                                        const float bottom)
    469 {
    470     CriticalSectionScoped cs(&_moduleCrit);
    471 
    472     if (!_ptrRenderer)
    473     {
    474         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    475                      "%s: No renderer", __FUNCTION__);
    476         return false;
    477     }
    478     return _ptrRenderer->SetStreamCropping(streamId, left, top, right, bottom);
    479 }
    480 
    481 int32_t ModuleVideoRenderImpl::SetTransparentBackground(const bool enable)
    482 {
    483     CriticalSectionScoped cs(&_moduleCrit);
    484 
    485     if (!_ptrRenderer)
    486     {
    487         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    488                      "%s: No renderer", __FUNCTION__);
    489         return false;
    490     }
    491     return _ptrRenderer->SetTransparentBackground(enable);
    492 }
    493 
    494 int32_t ModuleVideoRenderImpl::FullScreenRender(void* window, const bool enable)
    495 {
    496     return -1;
    497 }
    498 
    499 int32_t ModuleVideoRenderImpl::SetText(
    500                                              const uint8_t textId,
    501                                              const uint8_t* text,
    502                                              const int32_t textLength,
    503                                              const uint32_t textColorRef,
    504                                              const uint32_t backgroundColorRef,
    505                                              const float left, const float top,
    506                                              const float right,
    507                                              const float bottom)
    508 {
    509     CriticalSectionScoped cs(&_moduleCrit);
    510 
    511     if (!_ptrRenderer)
    512     {
    513         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    514                      "%s: No renderer", __FUNCTION__);
    515         return -1;
    516     }
    517     return _ptrRenderer->SetText(textId, text, textLength, textColorRef,
    518                                  backgroundColorRef, left, top, right, bottom);
    519 }
    520 
    521 int32_t ModuleVideoRenderImpl::SetBitmap(const void* bitMap,
    522                                          const uint8_t pictureId,
    523                                          const void* colorKey,
    524                                          const float left,
    525                                          const float top,
    526                                          const float right,
    527                                          const float bottom)
    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     return _ptrRenderer->SetBitmap(bitMap, pictureId, colorKey, left, top,
    538                                    right, bottom);
    539 }
    540 
    541 int32_t ModuleVideoRenderImpl::GetLastRenderedFrame(
    542     const uint32_t streamId,
    543     I420VideoFrame &frame) const
    544 {
    545     CriticalSectionScoped cs(&_moduleCrit);
    546 
    547     if (!_ptrRenderer)
    548     {
    549         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    550                      "%s: No renderer", __FUNCTION__);
    551         return -1;
    552     }
    553 
    554     IncomingVideoStreamMap::const_iterator item =
    555         _streamRenderMap.find(streamId);
    556     if (item == _streamRenderMap.end())
    557     {
    558         // This stream doesn't exist
    559         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    560                      "%s: stream doesn't exist", __FUNCTION__);
    561         return 0;
    562     }
    563 
    564     assert(item->second != NULL);
    565     return item->second->GetLastRenderedFrame(frame);
    566 }
    567 
    568 int32_t ModuleVideoRenderImpl::SetExpectedRenderDelay(
    569     uint32_t stream_id, int32_t delay_ms) {
    570   CriticalSectionScoped cs(&_moduleCrit);
    571 
    572   if (!_ptrRenderer) {
    573     WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    574                  "%s: No renderer", __FUNCTION__);
    575     return false;
    576   }
    577 
    578   IncomingVideoStreamMap::const_iterator item =
    579       _streamRenderMap.find(stream_id);
    580   if (item == _streamRenderMap.end()) {
    581     // This stream doesn't exist
    582     WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    583                  "%s(%u, %d): stream doesn't exist", __FUNCTION__, stream_id,
    584                  delay_ms);
    585     return -1;
    586   }
    587 
    588   assert(item->second != NULL);
    589   return item->second->SetExpectedRenderDelay(delay_ms);
    590 }
    591 
    592 int32_t ModuleVideoRenderImpl::ConfigureRenderer(
    593                                                        const uint32_t streamId,
    594                                                        const unsigned int zOrder,
    595                                                        const float left,
    596                                                        const float top,
    597                                                        const float right,
    598                                                        const float bottom)
    599 {
    600     CriticalSectionScoped cs(&_moduleCrit);
    601 
    602     if (!_ptrRenderer)
    603     {
    604         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    605                      "%s: No renderer", __FUNCTION__);
    606         return false;
    607     }
    608     return _ptrRenderer->ConfigureRenderer(streamId, zOrder, left, top, right,
    609                                            bottom);
    610 }
    611 
    612 int32_t ModuleVideoRenderImpl::SetStartImage(
    613     const uint32_t streamId,
    614     const I420VideoFrame& videoFrame)
    615 {
    616     CriticalSectionScoped cs(&_moduleCrit);
    617 
    618     if (!_ptrRenderer)
    619     {
    620         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    621                      "%s: No renderer", __FUNCTION__);
    622         return -1;
    623     }
    624 
    625     IncomingVideoStreamMap::const_iterator item =
    626         _streamRenderMap.find(streamId);
    627     if (item == _streamRenderMap.end())
    628     {
    629         // This stream doesn't exist
    630         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    631                      "%s: stream doesn't exist", __FUNCTION__);
    632         return -1;
    633     }
    634     assert (item->second != NULL);
    635     return item->second->SetStartImage(videoFrame);
    636 
    637 }
    638 
    639 int32_t ModuleVideoRenderImpl::SetTimeoutImage(
    640     const uint32_t streamId,
    641     const I420VideoFrame& videoFrame,
    642     const uint32_t timeout)
    643 {
    644     CriticalSectionScoped cs(&_moduleCrit);
    645 
    646     if (!_ptrRenderer)
    647     {
    648         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    649                      "%s: No renderer", __FUNCTION__);
    650         return -1;
    651     }
    652 
    653     IncomingVideoStreamMap::const_iterator item =
    654         _streamRenderMap.find(streamId);
    655     if (item == _streamRenderMap.end())
    656     {
    657         // This stream doesn't exist
    658         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    659                      "%s: stream doesn't exist", __FUNCTION__);
    660         return -1;
    661     }
    662     assert(item->second != NULL);
    663     return item->second->SetTimeoutImage(videoFrame, timeout);
    664 }
    665 
    666 int32_t ModuleVideoRenderImpl::MirrorRenderStream(const int renderId,
    667                                                   const bool enable,
    668                                                   const bool mirrorXAxis,
    669                                                   const bool mirrorYAxis)
    670 {
    671     CriticalSectionScoped cs(&_moduleCrit);
    672 
    673     if (!_ptrRenderer)
    674     {
    675         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    676                      "%s: No renderer", __FUNCTION__);
    677         return -1;
    678     }
    679 
    680     IncomingVideoStreamMap::const_iterator item =
    681         _streamRenderMap.find(renderId);
    682     if (item == _streamRenderMap.end())
    683     {
    684         // This stream doesn't exist
    685         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
    686                      "%s: stream doesn't exist", __FUNCTION__);
    687         return 0;
    688     }
    689     assert(item->second != NULL);
    690 
    691     return item->second->EnableMirroring(enable, mirrorXAxis, mirrorYAxis);
    692 }
    693 
    694 }  // namespace webrtc
    695