video_render_impl.cc revision 4052d881620f3f79a63df3d779f93d6124a5dc63
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 117int64_t ModuleVideoRenderImpl::TimeUntilNextProcess() 118{ 119 // Not used 120 return 50; 121} 122int32_t ModuleVideoRenderImpl::Process() 123{ 124 // Not used 125 return 0; 126} 127 128void* 129ModuleVideoRenderImpl::Window() 130{ 131 CriticalSectionScoped cs(&_moduleCrit); 132 return _ptrWindow; 133} 134 135int32_t ModuleVideoRenderImpl::ChangeWindow(void* window) 136{ 137 return -1; 138} 139 140int32_t ModuleVideoRenderImpl::Id() 141{ 142 CriticalSectionScoped cs(&_moduleCrit); 143 return _id; 144} 145 146uint32_t ModuleVideoRenderImpl::GetIncomingFrameRate(const uint32_t streamId) { 147 CriticalSectionScoped cs(&_moduleCrit); 148 149 IncomingVideoStreamMap::iterator it = _streamRenderMap.find(streamId); 150 151 if (it == _streamRenderMap.end()) { 152 // This stream doesn't exist 153 WEBRTC_TRACE(kTraceError, 154 kTraceVideoRenderer, 155 _id, 156 "%s: stream doesn't exist", 157 __FUNCTION__); 158 return 0; 159 } 160 assert(it->second != NULL); 161 return it->second->IncomingRate(); 162} 163 164VideoRenderCallback* 165ModuleVideoRenderImpl::AddIncomingRenderStream(const uint32_t streamId, 166 const uint32_t zOrder, 167 const float left, 168 const float top, 169 const float right, 170 const float bottom) 171{ 172 CriticalSectionScoped cs(&_moduleCrit); 173 174 if (!_ptrRenderer) 175 { 176 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, 177 "%s: No renderer", __FUNCTION__); 178 return NULL; 179 } 180 181 if (_streamRenderMap.find(streamId) != _streamRenderMap.end()) { 182 // The stream already exists... 183 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, 184 "%s: stream already exists", __FUNCTION__); 185 return NULL; 186 } 187 188 VideoRenderCallback* ptrRenderCallback = 189 _ptrRenderer->AddIncomingRenderStream(streamId, zOrder, left, top, 190 right, bottom); 191 if (ptrRenderCallback == NULL) 192 { 193 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, 194 "%s: Can't create incoming stream in renderer", 195 __FUNCTION__); 196 return NULL; 197 } 198 199 // Create platform independant code 200 IncomingVideoStream* ptrIncomingStream = new IncomingVideoStream(_id, 201 streamId); 202 if (ptrIncomingStream == NULL) 203 { 204 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, 205 "%s: Can't create incoming stream", __FUNCTION__); 206 return NULL; 207 } 208 209 210 if (ptrIncomingStream->SetRenderCallback(ptrRenderCallback) == -1) 211 { 212 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, 213 "%s: Can't set render callback", __FUNCTION__); 214 delete ptrIncomingStream; 215 _ptrRenderer->DeleteIncomingRenderStream(streamId); 216 return NULL; 217 } 218 219 VideoRenderCallback* moduleCallback = 220 ptrIncomingStream->ModuleCallback(); 221 222 // Store the stream 223 _streamRenderMap[streamId] = ptrIncomingStream; 224 225 return moduleCallback; 226} 227 228int32_t ModuleVideoRenderImpl::DeleteIncomingRenderStream( 229 const uint32_t streamId) 230{ 231 CriticalSectionScoped cs(&_moduleCrit); 232 233 if (!_ptrRenderer) 234 { 235 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, 236 "%s: No renderer", __FUNCTION__); 237 return -1; 238 } 239 240 IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId); 241 if (item == _streamRenderMap.end()) 242 { 243 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, 244 "%s: stream doesn't exist", __FUNCTION__); 245 return -1; 246 } 247 248 delete item->second; 249 250 _ptrRenderer->DeleteIncomingRenderStream(streamId); 251 252 _streamRenderMap.erase(item); 253 254 return 0; 255} 256 257int32_t ModuleVideoRenderImpl::AddExternalRenderCallback( 258 const uint32_t streamId, 259 VideoRenderCallback* renderObject) { 260 CriticalSectionScoped cs(&_moduleCrit); 261 262 IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId); 263 264 if (item == _streamRenderMap.end()) 265 { 266 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, 267 "%s: stream doesn't exist", __FUNCTION__); 268 return -1; 269 } 270 271 if (item->second == NULL) { 272 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, 273 "%s: could not get stream", __FUNCTION__); 274 return -1; 275 } 276 return item->second->SetExternalCallback(renderObject); 277} 278 279int32_t ModuleVideoRenderImpl::GetIncomingRenderStreamProperties( 280 const uint32_t streamId, 281 uint32_t& zOrder, 282 float& left, 283 float& top, 284 float& right, 285 float& bottom) const { 286 CriticalSectionScoped cs(&_moduleCrit); 287 288 if (!_ptrRenderer) 289 { 290 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, 291 "%s: No renderer", __FUNCTION__); 292 return -1; 293 } 294 295 return _ptrRenderer->GetIncomingRenderStreamProperties(streamId, zOrder, 296 left, top, right, 297 bottom); 298} 299 300uint32_t ModuleVideoRenderImpl::GetNumIncomingRenderStreams() const 301{ 302 CriticalSectionScoped cs(&_moduleCrit); 303 304 return static_cast<uint32_t>(_streamRenderMap.size()); 305} 306 307bool ModuleVideoRenderImpl::HasIncomingRenderStream( 308 const uint32_t streamId) const { 309 CriticalSectionScoped cs(&_moduleCrit); 310 311 return _streamRenderMap.find(streamId) != _streamRenderMap.end(); 312} 313 314int32_t ModuleVideoRenderImpl::RegisterRawFrameCallback( 315 const uint32_t streamId, 316 VideoRenderCallback* callbackObj) { 317 return -1; 318} 319 320int32_t ModuleVideoRenderImpl::StartRender(const uint32_t streamId) 321{ 322 CriticalSectionScoped cs(&_moduleCrit); 323 324 if (!_ptrRenderer) 325 { 326 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, 327 "%s: No renderer", __FUNCTION__); 328 return -1; 329 } 330 331 // Start the stream 332 IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId); 333 334 if (item == _streamRenderMap.end()) 335 { 336 return -1; 337 } 338 339 if (item->second->Start() == -1) 340 { 341 return -1; 342 } 343 344 // Start the HW renderer 345 if (_ptrRenderer->StartRender() == -1) 346 { 347 return -1; 348 } 349 return 0; 350} 351 352int32_t ModuleVideoRenderImpl::StopRender(const uint32_t streamId) 353{ 354 CriticalSectionScoped cs(&_moduleCrit); 355 356 if (!_ptrRenderer) 357 { 358 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, 359 "%s(%d): No renderer", __FUNCTION__, streamId); 360 return -1; 361 } 362 363 // Stop the incoming stream 364 IncomingVideoStreamMap::iterator item = _streamRenderMap.find(streamId); 365 366 if (item == _streamRenderMap.end()) 367 { 368 return -1; 369 } 370 371 if (item->second->Stop() == -1) 372 { 373 return -1; 374 } 375 376 return 0; 377} 378 379int32_t ModuleVideoRenderImpl::ResetRender() 380{ 381 CriticalSectionScoped cs(&_moduleCrit); 382 383 int32_t ret = 0; 384 // Loop through all incoming streams and reset them 385 for (IncomingVideoStreamMap::iterator it = _streamRenderMap.begin(); 386 it != _streamRenderMap.end(); 387 ++it) { 388 if (it->second->Reset() == -1) 389 ret = -1; 390 } 391 return ret; 392} 393 394RawVideoType ModuleVideoRenderImpl::PreferredVideoType() const 395{ 396 CriticalSectionScoped cs(&_moduleCrit); 397 398 if (_ptrRenderer == NULL) 399 { 400 return kVideoI420; 401 } 402 403 return _ptrRenderer->PerferedVideoType(); 404} 405 406bool ModuleVideoRenderImpl::IsFullScreen() 407{ 408 CriticalSectionScoped cs(&_moduleCrit); 409 410 if (!_ptrRenderer) 411 { 412 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, 413 "%s: No renderer", __FUNCTION__); 414 return false; 415 } 416 return _ptrRenderer->FullScreen(); 417} 418 419int32_t ModuleVideoRenderImpl::GetScreenResolution( 420 uint32_t& screenWidth, 421 uint32_t& screenHeight) const 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->GetScreenResolution(screenWidth, screenHeight); 432} 433 434uint32_t ModuleVideoRenderImpl::RenderFrameRate( 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 false; 444 } 445 return _ptrRenderer->RenderFrameRate(streamId); 446} 447 448int32_t ModuleVideoRenderImpl::SetStreamCropping( 449 const uint32_t streamId, 450 const float left, 451 const float top, 452 const float right, 453 const float bottom) 454{ 455 CriticalSectionScoped cs(&_moduleCrit); 456 457 if (!_ptrRenderer) 458 { 459 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, 460 "%s: No renderer", __FUNCTION__); 461 return false; 462 } 463 return _ptrRenderer->SetStreamCropping(streamId, left, top, right, bottom); 464} 465 466int32_t ModuleVideoRenderImpl::SetTransparentBackground(const bool enable) 467{ 468 CriticalSectionScoped cs(&_moduleCrit); 469 470 if (!_ptrRenderer) 471 { 472 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, 473 "%s: No renderer", __FUNCTION__); 474 return false; 475 } 476 return _ptrRenderer->SetTransparentBackground(enable); 477} 478 479int32_t ModuleVideoRenderImpl::FullScreenRender(void* window, const bool enable) 480{ 481 return -1; 482} 483 484int32_t ModuleVideoRenderImpl::SetText( 485 const uint8_t textId, 486 const uint8_t* text, 487 const int32_t textLength, 488 const uint32_t textColorRef, 489 const uint32_t backgroundColorRef, 490 const float left, const float top, 491 const float right, 492 const float bottom) 493{ 494 CriticalSectionScoped cs(&_moduleCrit); 495 496 if (!_ptrRenderer) 497 { 498 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, 499 "%s: No renderer", __FUNCTION__); 500 return -1; 501 } 502 return _ptrRenderer->SetText(textId, text, textLength, textColorRef, 503 backgroundColorRef, left, top, right, bottom); 504} 505 506int32_t ModuleVideoRenderImpl::SetBitmap(const void* bitMap, 507 const uint8_t pictureId, 508 const void* colorKey, 509 const float left, 510 const float top, 511 const float right, 512 const float bottom) 513{ 514 CriticalSectionScoped cs(&_moduleCrit); 515 516 if (!_ptrRenderer) 517 { 518 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, 519 "%s: No renderer", __FUNCTION__); 520 return -1; 521 } 522 return _ptrRenderer->SetBitmap(bitMap, pictureId, colorKey, left, top, 523 right, bottom); 524} 525 526int32_t ModuleVideoRenderImpl::SetExpectedRenderDelay( 527 uint32_t stream_id, int32_t delay_ms) { 528 CriticalSectionScoped cs(&_moduleCrit); 529 530 if (!_ptrRenderer) { 531 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, 532 "%s: No renderer", __FUNCTION__); 533 return false; 534 } 535 536 IncomingVideoStreamMap::const_iterator item = 537 _streamRenderMap.find(stream_id); 538 if (item == _streamRenderMap.end()) { 539 // This stream doesn't exist 540 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, 541 "%s(%u, %d): stream doesn't exist", __FUNCTION__, stream_id, 542 delay_ms); 543 return -1; 544 } 545 546 assert(item->second != NULL); 547 return item->second->SetExpectedRenderDelay(delay_ms); 548} 549 550int32_t ModuleVideoRenderImpl::ConfigureRenderer( 551 const uint32_t streamId, 552 const unsigned int zOrder, 553 const float left, 554 const float top, 555 const float right, 556 const float bottom) 557{ 558 CriticalSectionScoped cs(&_moduleCrit); 559 560 if (!_ptrRenderer) 561 { 562 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, 563 "%s: No renderer", __FUNCTION__); 564 return false; 565 } 566 return _ptrRenderer->ConfigureRenderer(streamId, zOrder, left, top, right, 567 bottom); 568} 569 570int32_t ModuleVideoRenderImpl::SetStartImage( 571 const uint32_t streamId, 572 const I420VideoFrame& videoFrame) 573{ 574 CriticalSectionScoped cs(&_moduleCrit); 575 576 if (!_ptrRenderer) 577 { 578 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, 579 "%s: No renderer", __FUNCTION__); 580 return -1; 581 } 582 583 IncomingVideoStreamMap::const_iterator item = 584 _streamRenderMap.find(streamId); 585 if (item == _streamRenderMap.end()) 586 { 587 // This stream doesn't exist 588 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, 589 "%s: stream doesn't exist", __FUNCTION__); 590 return -1; 591 } 592 assert (item->second != NULL); 593 return item->second->SetStartImage(videoFrame); 594 595} 596 597int32_t ModuleVideoRenderImpl::SetTimeoutImage( 598 const uint32_t streamId, 599 const I420VideoFrame& videoFrame, 600 const uint32_t timeout) 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 IncomingVideoStreamMap::const_iterator item = 612 _streamRenderMap.find(streamId); 613 if (item == _streamRenderMap.end()) 614 { 615 // This stream doesn't exist 616 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, 617 "%s: stream doesn't exist", __FUNCTION__); 618 return -1; 619 } 620 assert(item->second != NULL); 621 return item->second->SetTimeoutImage(videoFrame, timeout); 622} 623 624} // namespace webrtc 625