video_render_impl.cc revision ab071daab89462db77158e637ba059dba8c9ece7
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 22namespace webrtc { 23 24VideoRender* 25VideoRender::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 39void VideoRender::DestroyVideoRender( 40 VideoRender* module) 41{ 42 if (module) 43 { 44 delete module; 45 } 46} 47 48ModuleVideoRenderImpl::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 83ModuleVideoRenderImpl::~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 117int32_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 132int32_t ModuleVideoRenderImpl::TimeUntilNextProcess() 133{ 134 // Not used 135 return 50; 136} 137int32_t ModuleVideoRenderImpl::Process() 138{ 139 // Not used 140 return 0; 141} 142 143void* 144ModuleVideoRenderImpl::Window() 145{ 146 CriticalSectionScoped cs(&_moduleCrit); 147 return _ptrWindow; 148} 149 150int32_t ModuleVideoRenderImpl::ChangeWindow(void* window) 151{ 152 return -1; 153} 154 155int32_t ModuleVideoRenderImpl::Id() 156{ 157 CriticalSectionScoped cs(&_moduleCrit); 158 return _id; 159} 160 161uint32_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 179VideoRenderCallback* 180ModuleVideoRenderImpl::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 243int32_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 272int32_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 294int32_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 315uint32_t ModuleVideoRenderImpl::GetNumIncomingRenderStreams() const 316{ 317 CriticalSectionScoped cs(&_moduleCrit); 318 319 return static_cast<uint32_t>(_streamRenderMap.size()); 320} 321 322bool ModuleVideoRenderImpl::HasIncomingRenderStream( 323 const uint32_t streamId) const { 324 CriticalSectionScoped cs(&_moduleCrit); 325 326 return _streamRenderMap.find(streamId) != _streamRenderMap.end(); 327} 328 329int32_t ModuleVideoRenderImpl::RegisterRawFrameCallback( 330 const uint32_t streamId, 331 VideoRenderCallback* callbackObj) { 332 return -1; 333} 334 335int32_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 367int32_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 394int32_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 409RawVideoType 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 421bool 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 434int32_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 449uint32_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 463int32_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 481int32_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 494int32_t ModuleVideoRenderImpl::FullScreenRender(void* window, const bool enable) 495{ 496 return -1; 497} 498 499int32_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 521int32_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 541int32_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 568int32_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 592int32_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 612int32_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 639int32_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 666int32_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