Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(805)

Side by Side Diff: webrtc/modules/video_render/mac/video_render_nsopengl.mm

Issue 1929223003: Reland of Delete video_render module. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 "webrtc/engine_configurations.h"
12 #if defined(COCOA_RENDERING)
13
14 #include "webrtc/base/platform_thread.h"
15 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
16 #include "webrtc/modules/video_render/mac/video_render_nsopengl.h"
17 #include "webrtc/system_wrappers/include/critical_section_wrapper.h"
18 #include "webrtc/system_wrappers/include/event_wrapper.h"
19 #include "webrtc/system_wrappers/include/trace.h"
20
21 namespace webrtc {
22
23 VideoChannelNSOpenGL::VideoChannelNSOpenGL(NSOpenGLContext *nsglContext, int iId , VideoRenderNSOpenGL* owner) :
24 _nsglContext( nsglContext),
25 _id( iId),
26 _owner( owner),
27 _width( 0),
28 _height( 0),
29 _startWidth( 0.0f),
30 _startHeight( 0.0f),
31 _stopWidth( 0.0f),
32 _stopHeight( 0.0f),
33 _stretchedWidth( 0),
34 _stretchedHeight( 0),
35 _oldStretchedHeight( 0),
36 _oldStretchedWidth( 0),
37 _buffer( 0),
38 _bufferSize( 0),
39 _incomingBufferSize( 0),
40 _bufferIsUpdated( false),
41 _numberOfStreams( 0),
42 _pixelFormat( GL_RGBA),
43 _pixelDataType( GL_UNSIGNED_INT_8_8_8_8),
44 _texture( 0)
45 {
46
47 }
48
49 VideoChannelNSOpenGL::~VideoChannelNSOpenGL()
50 {
51 if (_buffer)
52 {
53 delete [] _buffer;
54 _buffer = NULL;
55 }
56
57 if (_texture != 0)
58 {
59 [_nsglContext makeCurrentContext];
60 glDeleteTextures(1, (const GLuint*) &_texture);
61 _texture = 0;
62 }
63 }
64
65 int VideoChannelNSOpenGL::ChangeContext(NSOpenGLContext *nsglContext)
66 {
67 _owner->LockAGLCntx();
68
69 _nsglContext = nsglContext;
70 [_nsglContext makeCurrentContext];
71
72 _owner->UnlockAGLCntx();
73 return 0;
74
75 }
76
77 int32_t VideoChannelNSOpenGL::GetChannelProperties(float& left, float& top,
78 float& right, float& bottom)
79 {
80
81 _owner->LockAGLCntx();
82
83 left = _startWidth;
84 top = _startHeight;
85 right = _stopWidth;
86 bottom = _stopHeight;
87
88 _owner->UnlockAGLCntx();
89 return 0;
90 }
91
92 int32_t VideoChannelNSOpenGL::RenderFrame(const uint32_t /*streamId*/,
93 const VideoFrame& videoFrame) {
94 _owner->LockAGLCntx();
95
96 if(_width != videoFrame.width() ||
97 _height != videoFrame.height()) {
98 if(FrameSizeChange(videoFrame.width(), videoFrame.height(), 1) == -1) {
99 _owner->UnlockAGLCntx();
100 return -1;
101 }
102 }
103 int ret = DeliverFrame(videoFrame);
104
105 _owner->UnlockAGLCntx();
106 return ret;
107 }
108
109 int VideoChannelNSOpenGL::UpdateSize(int width, int height)
110 {
111 _owner->LockAGLCntx();
112 _width = width;
113 _height = height;
114 _owner->UnlockAGLCntx();
115 return 0;
116 }
117
118 int VideoChannelNSOpenGL::UpdateStretchSize(int stretchHeight, int stretchWidth)
119 {
120
121 _owner->LockAGLCntx();
122 _stretchedHeight = stretchHeight;
123 _stretchedWidth = stretchWidth;
124 _owner->UnlockAGLCntx();
125 return 0;
126 }
127
128 int VideoChannelNSOpenGL::FrameSizeChange(int width, int height, int numberOfStr eams)
129 {
130 // We got a new frame size from VideoAPI, prepare the buffer
131
132 _owner->LockAGLCntx();
133
134 if (width == _width && _height == height)
135 {
136 // We already have a correct buffer size
137 _numberOfStreams = numberOfStreams;
138 _owner->UnlockAGLCntx();
139 return 0;
140 }
141
142 _width = width;
143 _height = height;
144
145 // Delete the old buffer, create a new one with correct size.
146 if (_buffer)
147 {
148 delete [] _buffer;
149 _bufferSize = 0;
150 }
151
152 _incomingBufferSize = CalcBufferSize(kI420, _width, _height);
153 _bufferSize = CalcBufferSize(kARGB, _width, _height);
154 _buffer = new unsigned char [_bufferSize];
155 memset(_buffer, 0, _bufferSize * sizeof(unsigned char));
156
157 [_nsglContext makeCurrentContext];
158
159 if(glIsTexture(_texture))
160 {
161 glDeleteTextures(1, (const GLuint*) &_texture);
162 _texture = 0;
163 }
164
165 // Create a new texture
166 glGenTextures(1, (GLuint *) &_texture);
167
168 GLenum glErr = glGetError();
169
170 if (glErr != GL_NO_ERROR)
171 {
172
173 }
174
175 glBindTexture(GL_TEXTURE_RECTANGLE_EXT, _texture);
176
177 GLint texSize;
178 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texSize);
179
180 if (texSize < _width || texSize < _height)
181 {
182 _owner->UnlockAGLCntx();
183 return -1;
184 }
185
186 // Set up th texture type and size
187 glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, // target
188 0, // level
189 GL_RGBA, // internal format
190 _width, // width
191 _height, // height
192 0, // border 0/1 = off/on
193 _pixelFormat, // format, GL_RGBA
194 _pixelDataType, // data type, GL_UNSIGNED_INT_8_8_8_8
195 _buffer); // pixel data
196
197 glErr = glGetError();
198 if (glErr != GL_NO_ERROR)
199 {
200 _owner->UnlockAGLCntx();
201 return -1;
202 }
203
204 _owner->UnlockAGLCntx();
205 return 0;
206 }
207
208 int VideoChannelNSOpenGL::DeliverFrame(const VideoFrame& videoFrame) {
209 _owner->LockAGLCntx();
210
211 if (_texture == 0) {
212 _owner->UnlockAGLCntx();
213 return 0;
214 }
215
216 if (CalcBufferSize(kI420, videoFrame.width(), videoFrame.height()) !=
217 _incomingBufferSize) {
218 _owner->UnlockAGLCntx();
219 return -1;
220 }
221
222 // Using the VideoFrame for YV12: YV12 is YVU; I420 assumes
223 // YUV.
224 // TODO(mikhal) : Use appropriate functionality.
225 // TODO(wu): See if we are using glTexSubImage2D correctly.
226 int rgbRet = ConvertFromYV12(videoFrame, kBGRA, 0, _buffer);
227 if (rgbRet < 0) {
228 _owner->UnlockAGLCntx();
229 return -1;
230 }
231
232 [_nsglContext makeCurrentContext];
233
234 // Make sure this texture is the active one
235 glBindTexture(GL_TEXTURE_RECTANGLE_EXT, _texture);
236 GLenum glErr = glGetError();
237 if (glErr != GL_NO_ERROR) {
238 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
239 "ERROR %d while calling glBindTexture", glErr);
240 _owner->UnlockAGLCntx();
241 return -1;
242 }
243
244 glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT,
245 0, // Level, not use
246 0, // start point x, (low left of pic)
247 0, // start point y,
248 _width, // width
249 _height, // height
250 _pixelFormat, // pictue format for _buffer
251 _pixelDataType, // data type of _buffer
252 (const GLvoid*) _buffer); // the pixel data
253
254 glErr = glGetError();
255 if (glErr != GL_NO_ERROR) {
256 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
257 "ERROR %d while calling glTexSubImage2d", glErr);
258 _owner->UnlockAGLCntx();
259 return -1;
260 }
261
262 _bufferIsUpdated = true;
263
264 _owner->UnlockAGLCntx();
265 return 0;
266 }
267
268 int VideoChannelNSOpenGL::RenderOffScreenBuffer()
269 {
270
271 _owner->LockAGLCntx();
272
273 if (_texture == 0)
274 {
275 _owner->UnlockAGLCntx();
276 return 0;
277 }
278
279 // if(_fullscreen)
280 // {
281 // NSRect mainDisplayRect = [[NSScreen mainScreen] frame];
282 // _width = mainDisplayRect.size.width;
283 // _height = mainDisplayRect.size.height;
284 // glViewport(0, 0, mainDisplayRect.size.width, mainDisplayRect.siz e.height);
285 // float newX = mainDisplayRect.size.width/_width;
286 // float newY = mainDisplayRect.size.height/_height;
287
288 // convert from 0.0 <= size <= 1.0 to
289 // open gl world -1.0 < size < 1.0
290 GLfloat xStart = 2.0f * _startWidth - 1.0f;
291 GLfloat xStop = 2.0f * _stopWidth - 1.0f;
292 GLfloat yStart = 1.0f - 2.0f * _stopHeight;
293 GLfloat yStop = 1.0f - 2.0f * _startHeight;
294
295 [_nsglContext makeCurrentContext];
296
297 glBindTexture(GL_TEXTURE_RECTANGLE_EXT, _texture);
298 _oldStretchedHeight = _stretchedHeight;
299 _oldStretchedWidth = _stretchedWidth;
300
301 glLoadIdentity();
302 glEnable(GL_TEXTURE_RECTANGLE_EXT);
303 glBegin(GL_POLYGON);
304 {
305 glTexCoord2f(0.0, 0.0); glVertex2f(xStart, yStop);
306 glTexCoord2f(_width, 0.0); glVertex2f(xStop, yStop);
307 glTexCoord2f(_width, _height); glVertex2f(xStop, yStart);
308 glTexCoord2f(0.0, _height); glVertex2f(xStart, yStart);
309 }
310 glEnd();
311
312 glDisable(GL_TEXTURE_RECTANGLE_EXT);
313
314 _bufferIsUpdated = false;
315
316 _owner->UnlockAGLCntx();
317 return 0;
318 }
319
320 int VideoChannelNSOpenGL::IsUpdated(bool& isUpdated)
321 {
322 _owner->LockAGLCntx();
323
324 isUpdated = _bufferIsUpdated;
325
326 _owner->UnlockAGLCntx();
327 return 0;
328 }
329
330 int VideoChannelNSOpenGL::SetStreamSettings(int /*streamId*/, float startWidth, float startHeight, float stopWidth, float stopHeight)
331 {
332 _owner->LockAGLCntx();
333
334 _startWidth = startWidth;
335 _stopWidth = stopWidth;
336 _startHeight = startHeight;
337 _stopHeight = stopHeight;
338
339 int oldWidth = _width;
340 int oldHeight = _height;
341 int oldNumberOfStreams = _numberOfStreams;
342
343 _width = 0;
344 _height = 0;
345
346 int retVal = FrameSizeChange(oldWidth, oldHeight, oldNumberOfStreams);
347
348 _owner->UnlockAGLCntx();
349 return retVal;
350 }
351
352 int VideoChannelNSOpenGL::SetStreamCropSettings(int /*streamId*/, float /*startW idth*/, float /*startHeight*/, float /*stopWidth*/, float /*stopHeight*/)
353 {
354 return -1;
355 }
356
357 /*
358 *
359 * VideoRenderNSOpenGL
360 *
361 */
362
363 VideoRenderNSOpenGL::VideoRenderNSOpenGL(CocoaRenderView *windowRef, bool fullSc reen, int iId) :
364 _windowRef( (CocoaRenderView*)windowRef),
365 _fullScreen( fullScreen),
366 _id( iId),
367 _nsglContextCritSec( *CriticalSectionWrapper::CreateCriticalSection()),
368 _screenUpdateEvent(EventTimerWrapper::Create()),
369 _nsglContext( 0),
370 _nsglFullScreenContext( 0),
371 _fullScreenWindow( nil),
372 _windowRect( ),
373 _windowWidth( 0),
374 _windowHeight( 0),
375 _nsglChannels( ),
376 _zOrderToChannel( ),
377 _renderingIsPaused (FALSE),
378 _windowRefSuperView(NULL),
379 _windowRefSuperViewFrame(NSMakeRect(0,0,0,0))
380 {
381 _screenUpdateThread.reset(new rtc::PlatformThread(
382 ScreenUpdateThreadProc, this, "ScreenUpdateNSOpenGL"));
383 }
384
385 int VideoRenderNSOpenGL::ChangeWindow(CocoaRenderView* newWindowRef)
386 {
387
388 LockAGLCntx();
389
390 _windowRef = newWindowRef;
391
392 if(CreateMixingContext() == -1)
393 {
394 UnlockAGLCntx();
395 return -1;
396 }
397
398 int error = 0;
399 std::map<int, VideoChannelNSOpenGL*>::iterator it = _nsglChannels.begin();
400 while (it!= _nsglChannels.end())
401 {
402 error |= (it->second)->ChangeContext(_nsglContext);
403 it++;
404 }
405 if(error != 0)
406 {
407 UnlockAGLCntx();
408 return -1;
409 }
410
411 UnlockAGLCntx();
412 return 0;
413 }
414
415 /* Check if the thread and event already exist.
416 * If so then they will simply be restarted
417 * If not then create them and continue
418 */
419 int32_t VideoRenderNSOpenGL::StartRender()
420 {
421
422 LockAGLCntx();
423
424 const unsigned int MONITOR_FREQ = 60;
425 if(TRUE == _renderingIsPaused)
426 {
427 WEBRTC_TRACE(kTraceDebug, kTraceVideoRenderer, _id, "Restarting screenUp dateThread");
428
429 // we already have the thread. Most likely StopRender() was called and t hey were paused
430 _screenUpdateThread->Start();
431 if (FALSE ==
432 _screenUpdateEvent->StartTimer(true, 1000 / MONITOR_FREQ)) {
433 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, "Failed to resta rt screenUpdateThread or screenUpdateEvent");
434 UnlockAGLCntx();
435 return -1;
436 }
437
438 _screenUpdateThread->SetPriority(rtc::kRealtimePriority);
439
440 UnlockAGLCntx();
441 return 0;
442 }
443
444
445 if (!_screenUpdateThread)
446 {
447 WEBRTC_TRACE(kTraceDebug, kTraceVideoRenderer, _id, "failed start screen UpdateThread");
448 UnlockAGLCntx();
449 return -1;
450 }
451
452
453 UnlockAGLCntx();
454 return 0;
455 }
456 int32_t VideoRenderNSOpenGL::StopRender()
457 {
458
459 LockAGLCntx();
460
461 /* The code below is functional
462 * but it pauses for several seconds
463 */
464
465 // pause the update thread and the event timer
466 if(!_screenUpdateThread || !_screenUpdateEvent)
467 {
468 _renderingIsPaused = TRUE;
469
470 UnlockAGLCntx();
471 return 0;
472 }
473
474 _screenUpdateThread->Stop();
475 if (FALSE == _screenUpdateEvent->StopTimer()) {
476 _renderingIsPaused = FALSE;
477
478 UnlockAGLCntx();
479 return -1;
480 }
481
482 _renderingIsPaused = TRUE;
483
484 UnlockAGLCntx();
485 return 0;
486 }
487
488 int VideoRenderNSOpenGL::configureNSOpenGLView()
489 {
490 return 0;
491
492 }
493
494 int VideoRenderNSOpenGL::configureNSOpenGLEngine()
495 {
496
497 LockAGLCntx();
498
499 // Disable not needed functionality to increase performance
500 glDisable(GL_DITHER);
501 glDisable(GL_ALPHA_TEST);
502 glDisable(GL_STENCIL_TEST);
503 glDisable(GL_FOG);
504 glDisable(GL_TEXTURE_2D);
505 glPixelZoom(1.0, 1.0);
506 glDisable(GL_BLEND);
507 glDisable(GL_DEPTH_TEST);
508 glDepthMask(GL_FALSE);
509 glDisable(GL_CULL_FACE);
510
511 // Set texture parameters
512 glTexParameterf(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_PRIORITY, 1.0);
513 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDG E);
514 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDG E);
515 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
516 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
517 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
518 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
519 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_STORAGE_HINT_APPLE, GL_ STORAGE_SHARED_APPLE);
520
521 if (GetWindowRect(_windowRect) == -1)
522 {
523 UnlockAGLCntx();
524 return true;
525 }
526
527 if (_windowWidth != (_windowRect.right - _windowRect.left)
528 || _windowHeight != (_windowRect.bottom - _windowRect.top))
529 {
530 _windowWidth = _windowRect.right - _windowRect.left;
531 _windowHeight = _windowRect.bottom - _windowRect.top;
532 }
533 glViewport(0, 0, _windowWidth, _windowHeight);
534
535 // Synchronize buffer swaps with vertical refresh rate
536 GLint swapInt = 1;
537 [_nsglContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
538
539 UnlockAGLCntx();
540 return 0;
541 }
542
543 int VideoRenderNSOpenGL::setRenderTargetWindow()
544 {
545 LockAGLCntx();
546
547
548 GLuint attribs[] =
549 {
550 NSOpenGLPFAColorSize, 24,
551 NSOpenGLPFAAlphaSize, 8,
552 NSOpenGLPFADepthSize, 16,
553 NSOpenGLPFAAccelerated,
554 0
555 };
556
557 NSOpenGLPixelFormat* fmt = [[[NSOpenGLPixelFormat alloc] initWithAttributes:
558 (NSOpenGLPixelFormatAttribute*) attribs] autorelease];
559
560 if(_windowRef)
561 {
562 [_windowRef initCocoaRenderView:fmt];
563 }
564 else
565 {
566 UnlockAGLCntx();
567 return -1;
568 }
569
570 _nsglContext = [_windowRef nsOpenGLContext];
571 [_nsglContext makeCurrentContext];
572
573 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
574 glClear(GL_COLOR_BUFFER_BIT);
575
576
577 DisplayBuffers();
578
579 UnlockAGLCntx();
580 return 0;
581 }
582
583 int VideoRenderNSOpenGL::setRenderTargetFullScreen()
584 {
585 LockAGLCntx();
586
587
588 GLuint attribs[] =
589 {
590 NSOpenGLPFAColorSize, 24,
591 NSOpenGLPFAAlphaSize, 8,
592 NSOpenGLPFADepthSize, 16,
593 NSOpenGLPFAAccelerated,
594 0
595 };
596
597 NSOpenGLPixelFormat* fmt = [[[NSOpenGLPixelFormat alloc] initWithAttributes:
598 (NSOpenGLPixelFormatAttribute*) attribs] autorelease];
599
600 // Store original superview and frame for use when exiting full screens
601 _windowRefSuperViewFrame = [_windowRef frame];
602 _windowRefSuperView = [_windowRef superview];
603
604
605 // create new fullscreen window
606 NSRect screenRect = [[NSScreen mainScreen]frame];
607 [_windowRef setFrame:screenRect];
608 [_windowRef setBounds:screenRect];
609
610
611 _fullScreenWindow = [[CocoaFullScreenWindow alloc]init];
612 [_fullScreenWindow grabFullScreen];
613 [[[_fullScreenWindow window] contentView] addSubview:_windowRef];
614
615 if(_windowRef)
616 {
617 [_windowRef initCocoaRenderViewFullScreen:fmt];
618 }
619 else
620 {
621 UnlockAGLCntx();
622 return -1;
623 }
624
625 _nsglContext = [_windowRef nsOpenGLContext];
626 [_nsglContext makeCurrentContext];
627
628 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
629 glClear(GL_COLOR_BUFFER_BIT);
630
631 DisplayBuffers();
632
633 UnlockAGLCntx();
634 return 0;
635 }
636
637 VideoRenderNSOpenGL::~VideoRenderNSOpenGL()
638 {
639
640 if(_fullScreen)
641 {
642 if(_fullScreenWindow)
643 {
644 // Detach CocoaRenderView from full screen view back to
645 // it's original parent.
646 [_windowRef removeFromSuperview];
647 if(_windowRefSuperView)
648 {
649 [_windowRefSuperView addSubview:_windowRef];
650 [_windowRef setFrame:_windowRefSuperViewFrame];
651 }
652
653 WEBRTC_TRACE(kTraceDebug, kTraceVideoRenderer, 0, "%s:%d Attempting to release fullscreen window", __FUNCTION__, __LINE__);
654 [_fullScreenWindow releaseFullScreen];
655
656 }
657 }
658
659 // Signal event to exit thread, then delete it
660 rtc::PlatformThread* tmpPtr = _screenUpdateThread.release();
661
662 if (tmpPtr)
663 {
664 _screenUpdateEvent->Set();
665 _screenUpdateEvent->StopTimer();
666
667 tmpPtr->Stop();
668 delete tmpPtr;
669 delete _screenUpdateEvent;
670 _screenUpdateEvent = NULL;
671 }
672
673 if (_nsglContext != 0)
674 {
675 [_nsglContext makeCurrentContext];
676 _nsglContext = nil;
677 }
678
679 // Delete all channels
680 std::map<int, VideoChannelNSOpenGL*>::iterator it = _nsglChannels.begin();
681 while (it!= _nsglChannels.end())
682 {
683 delete it->second;
684 _nsglChannels.erase(it);
685 it = _nsglChannels.begin();
686 }
687 _nsglChannels.clear();
688
689 // Clean the zOrder map
690 std::multimap<int, int>::iterator zIt = _zOrderToChannel.begin();
691 while(zIt != _zOrderToChannel.end())
692 {
693 _zOrderToChannel.erase(zIt);
694 zIt = _zOrderToChannel.begin();
695 }
696 _zOrderToChannel.clear();
697
698 }
699
700 /* static */
701 int VideoRenderNSOpenGL::GetOpenGLVersion(int& /*nsglMajor*/, int& /*nsglMinor*/ )
702 {
703 return -1;
704 }
705
706 int VideoRenderNSOpenGL::Init()
707 {
708
709 LockAGLCntx();
710 if (!_screenUpdateThread)
711 {
712 UnlockAGLCntx();
713 return -1;
714 }
715
716 _screenUpdateThread->Start();
717 _screenUpdateThread->SetPriority(rtc::kRealtimePriority);
718
719 // Start the event triggering the render process
720 unsigned int monitorFreq = 60;
721 _screenUpdateEvent->StartTimer(true, 1000/monitorFreq);
722
723 if (CreateMixingContext() == -1)
724 {
725 UnlockAGLCntx();
726 return -1;
727 }
728
729 UnlockAGLCntx();
730 return 0;
731 }
732
733 VideoChannelNSOpenGL* VideoRenderNSOpenGL::CreateNSGLChannel(int channel, int zO rder, float startWidth, float startHeight, float stopWidth, float stopHeight)
734 {
735 CriticalSectionScoped cs(&_nsglContextCritSec);
736
737 if (HasChannel(channel))
738 {
739 return NULL;
740 }
741
742 if (_zOrderToChannel.find(zOrder) != _zOrderToChannel.end())
743 {
744
745 }
746
747 VideoChannelNSOpenGL* newAGLChannel = new VideoChannelNSOpenGL(_nsglContext, _id, this);
748 if (newAGLChannel->SetStreamSettings(0, startWidth, startHeight, stopWidth, stopHeight) == -1)
749 {
750 if (newAGLChannel)
751 {
752 delete newAGLChannel;
753 newAGLChannel = NULL;
754 }
755
756 return NULL;
757 }
758
759 _nsglChannels[channel] = newAGLChannel;
760 _zOrderToChannel.insert(std::pair<int, int>(zOrder, channel));
761
762 WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _id, "%s successfully created NSGL channel number %d", __FUNCTION__, channel);
763
764 return newAGLChannel;
765 }
766
767 int VideoRenderNSOpenGL::DeleteAllNSGLChannels()
768 {
769
770 CriticalSectionScoped cs(&_nsglContextCritSec);
771
772 std::map<int, VideoChannelNSOpenGL*>::iterator it;
773 it = _nsglChannels.begin();
774
775 while (it != _nsglChannels.end())
776 {
777 VideoChannelNSOpenGL* channel = it->second;
778 WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _id, "%s Deleting channel %d", __FUNCTION__, channel);
779 delete channel;
780 it++;
781 }
782 _nsglChannels.clear();
783 return 0;
784 }
785
786 int32_t VideoRenderNSOpenGL::DeleteNSGLChannel(const uint32_t channel)
787 {
788
789 CriticalSectionScoped cs(&_nsglContextCritSec);
790
791 std::map<int, VideoChannelNSOpenGL*>::iterator it;
792 it = _nsglChannels.find(channel);
793 if (it != _nsglChannels.end())
794 {
795 delete it->second;
796 _nsglChannels.erase(it);
797 }
798 else
799 {
800 return -1;
801 }
802
803 std::multimap<int, int>::iterator zIt = _zOrderToChannel.begin();
804 while( zIt != _zOrderToChannel.end())
805 {
806 if (zIt->second == (int)channel)
807 {
808 _zOrderToChannel.erase(zIt);
809 break;
810 }
811 zIt++;
812 }
813
814 return 0;
815 }
816
817 int32_t VideoRenderNSOpenGL::GetChannelProperties(const uint16_t streamId,
818 uint32_t& zOrder,
819 float& left,
820 float& top,
821 float& right,
822 float& bottom)
823 {
824
825 CriticalSectionScoped cs(&_nsglContextCritSec);
826
827 bool channelFound = false;
828
829 // Loop through all channels until we find a match.
830 // From that, get zorder.
831 // From that, get T, L, R, B
832 for (std::multimap<int, int>::reverse_iterator rIt = _zOrderToChannel.rbegin ();
833 rIt != _zOrderToChannel.rend();
834 rIt++)
835 {
836 if(streamId == rIt->second)
837 {
838 channelFound = true;
839
840 zOrder = rIt->second;
841
842 std::map<int, VideoChannelNSOpenGL*>::iterator rIt = _nsglChannels.f ind(streamId);
843 VideoChannelNSOpenGL* tempChannel = rIt->second;
844
845 if(-1 == tempChannel->GetChannelProperties(left, top, right, bottom) )
846 {
847 return -1;
848 }
849 break;
850 }
851 }
852
853 if(false == channelFound)
854 {
855
856 return -1;
857 }
858
859 return 0;
860 }
861
862 int VideoRenderNSOpenGL::StopThread()
863 {
864
865 rtc::PlatformThread* tmpPtr = _screenUpdateThread.release();
866 WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _id,
867 "%s Stopping thread ", __FUNCTION__, tmpPtr);
868
869 if (tmpPtr)
870 {
871 _screenUpdateEvent->Set();
872 tmpPtr->Stop();
873 delete tmpPtr;
874 }
875
876 delete _screenUpdateEvent;
877 _screenUpdateEvent = NULL;
878
879 return 0;
880 }
881
882 bool VideoRenderNSOpenGL::IsFullScreen()
883 {
884
885 CriticalSectionScoped cs(&_nsglContextCritSec);
886 return _fullScreen;
887 }
888
889 bool VideoRenderNSOpenGL::HasChannels()
890 {
891 CriticalSectionScoped cs(&_nsglContextCritSec);
892
893 if (_nsglChannels.begin() != _nsglChannels.end())
894 {
895 return true;
896 }
897 return false;
898 }
899
900 bool VideoRenderNSOpenGL::HasChannel(int channel)
901 {
902
903 CriticalSectionScoped cs(&_nsglContextCritSec);
904
905 std::map<int, VideoChannelNSOpenGL*>::iterator it = _nsglChannels.find(chann el);
906
907 if (it != _nsglChannels.end())
908 {
909 return true;
910 }
911 return false;
912 }
913
914 int VideoRenderNSOpenGL::GetChannels(std::list<int>& channelList)
915 {
916
917 CriticalSectionScoped cs(&_nsglContextCritSec);
918
919 std::map<int, VideoChannelNSOpenGL*>::iterator it = _nsglChannels.begin();
920
921 while (it != _nsglChannels.end())
922 {
923 channelList.push_back(it->first);
924 it++;
925 }
926
927 return 0;
928 }
929
930 VideoChannelNSOpenGL* VideoRenderNSOpenGL::ConfigureNSGLChannel(int channel, int zOrder, float startWidth, float startHeight, float stopWidth, float stopHeight)
931 {
932
933 CriticalSectionScoped cs(&_nsglContextCritSec);
934
935 std::map<int, VideoChannelNSOpenGL*>::iterator it = _nsglChannels.find(chann el);
936
937 if (it != _nsglChannels.end())
938 {
939 VideoChannelNSOpenGL* aglChannel = it->second;
940 if (aglChannel->SetStreamSettings(0, startWidth, startHeight, stopWidth, stopHeight) == -1)
941 {
942 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, "%s failed to se t stream settings: channel %d. channel=%d zOrder=%d startWidth=%d startHeight=%d stopWidth=%d stopHeight=%d",
943 __FUNCTION__, channel, zOrder, startWidth, startHeight, stop Width, stopHeight);
944 return NULL;
945 }
946 WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _id, "%s Configuring chann el %d. channel=%d zOrder=%d startWidth=%d startHeight=%d stopWidth=%d stopHeight =%d",
947 __FUNCTION__, channel, zOrder, startWidth, startHeight, stopWidt h, stopHeight);
948
949 std::multimap<int, int>::iterator it = _zOrderToChannel.begin();
950 while(it != _zOrderToChannel.end())
951 {
952 if (it->second == channel)
953 {
954 if (it->first != zOrder)
955 {
956 _zOrderToChannel.erase(it);
957 _zOrderToChannel.insert(std::pair<int, int>(zOrder, channel) );
958 }
959 break;
960 }
961 it++;
962 }
963 return aglChannel;
964 }
965
966 return NULL;
967 }
968
969 /*
970 *
971 * Rendering process
972 *
973 */
974
975 bool VideoRenderNSOpenGL::ScreenUpdateThreadProc(void* obj)
976 {
977 return static_cast<VideoRenderNSOpenGL*>(obj)->ScreenUpdateProcess();
978 }
979
980 bool VideoRenderNSOpenGL::ScreenUpdateProcess()
981 {
982
983 _screenUpdateEvent->Wait(10);
984 LockAGLCntx();
985
986 if (!_screenUpdateThread)
987 {
988 WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, _id, "%s no screen upda te thread", __FUNCTION__);
989 UnlockAGLCntx();
990 return false;
991 }
992
993 [_nsglContext makeCurrentContext];
994
995 if (GetWindowRect(_windowRect) == -1)
996 {
997 UnlockAGLCntx();
998 return true;
999 }
1000
1001 if (_windowWidth != (_windowRect.right - _windowRect.left)
1002 || _windowHeight != (_windowRect.bottom - _windowRect.top))
1003 {
1004 _windowWidth = _windowRect.right - _windowRect.left;
1005 _windowHeight = _windowRect.bottom - _windowRect.top;
1006 glViewport(0, 0, _windowWidth, _windowHeight);
1007 }
1008
1009 // Check if there are any updated buffers
1010 bool updated = false;
1011 std::map<int, VideoChannelNSOpenGL*>::iterator it = _nsglChannels.begin();
1012 while (it != _nsglChannels.end())
1013 {
1014
1015 VideoChannelNSOpenGL* aglChannel = it->second;
1016 aglChannel->UpdateStretchSize(_windowHeight, _windowWidth);
1017 aglChannel->IsUpdated(updated);
1018 if (updated)
1019 {
1020 break;
1021 }
1022 it++;
1023 }
1024
1025 if (updated)
1026 {
1027
1028 // At least on buffers is updated, we need to repaint the texture
1029 if (RenderOffScreenBuffers() != -1)
1030 {
1031 UnlockAGLCntx();
1032 return true;
1033 }
1034 }
1035 // }
1036 UnlockAGLCntx();
1037 return true;
1038 }
1039
1040 /*
1041 *
1042 * Functions for creating mixing buffers and screen settings
1043 *
1044 */
1045
1046 int VideoRenderNSOpenGL::CreateMixingContext()
1047 {
1048
1049 CriticalSectionScoped cs(&_nsglContextCritSec);
1050
1051 if(_fullScreen)
1052 {
1053 if(-1 == setRenderTargetFullScreen())
1054 {
1055 return -1;
1056 }
1057 }
1058 else
1059 {
1060
1061 if(-1 == setRenderTargetWindow())
1062 {
1063 return -1;
1064 }
1065 }
1066
1067 configureNSOpenGLEngine();
1068
1069 DisplayBuffers();
1070
1071 GLenum glErr = glGetError();
1072 if (glErr)
1073 {
1074 }
1075
1076 return 0;
1077 }
1078
1079 /*
1080 *
1081 * Rendering functions
1082 *
1083 */
1084
1085 int VideoRenderNSOpenGL::RenderOffScreenBuffers()
1086 {
1087 LockAGLCntx();
1088
1089 // Get the current window size, it might have changed since last render.
1090 if (GetWindowRect(_windowRect) == -1)
1091 {
1092 UnlockAGLCntx();
1093 return -1;
1094 }
1095
1096 [_nsglContext makeCurrentContext];
1097 glClear(GL_COLOR_BUFFER_BIT);
1098
1099 // Loop through all channels starting highest zOrder ending with lowest.
1100 for (std::multimap<int, int>::reverse_iterator rIt = _zOrderToChannel.rbegin ();
1101 rIt != _zOrderToChannel.rend();
1102 rIt++)
1103 {
1104 int channelId = rIt->second;
1105 std::map<int, VideoChannelNSOpenGL*>::iterator it = _nsglChannels.find(c hannelId);
1106
1107 VideoChannelNSOpenGL* aglChannel = it->second;
1108
1109 aglChannel->RenderOffScreenBuffer();
1110 }
1111
1112 DisplayBuffers();
1113
1114 UnlockAGLCntx();
1115 return 0;
1116 }
1117
1118 /*
1119 *
1120 * Help functions
1121 *
1122 * All help functions assumes external protections
1123 *
1124 */
1125
1126 int VideoRenderNSOpenGL::DisplayBuffers()
1127 {
1128
1129 LockAGLCntx();
1130
1131 glFinish();
1132 [_nsglContext flushBuffer];
1133
1134 WEBRTC_TRACE(kTraceDebug, kTraceVideoRenderer, _id, "%s glFinish and [_nsglC ontext flushBuffer]", __FUNCTION__);
1135
1136 UnlockAGLCntx();
1137 return 0;
1138 }
1139
1140 int VideoRenderNSOpenGL::GetWindowRect(Rect& rect)
1141 {
1142
1143 CriticalSectionScoped cs(&_nsglContextCritSec);
1144
1145 if (_windowRef)
1146 {
1147 if(_fullScreen)
1148 {
1149 NSRect mainDisplayRect = [[NSScreen mainScreen] frame];
1150 rect.bottom = 0;
1151 rect.left = 0;
1152 rect.right = mainDisplayRect.size.width;
1153 rect.top = mainDisplayRect.size.height;
1154 }
1155 else
1156 {
1157 rect.top = [_windowRef frame].origin.y;
1158 rect.left = [_windowRef frame].origin.x;
1159 rect.bottom = [_windowRef frame].origin.y + [_windowRef frame].size. height;
1160 rect.right = [_windowRef frame].origin.x + [_windowRef frame].size.w idth;
1161 }
1162
1163 return 0;
1164 }
1165 else
1166 {
1167 return -1;
1168 }
1169 }
1170
1171 int32_t VideoRenderNSOpenGL::SetText(const uint8_t /*textId*/,
1172 const uint8_t* /*text*/,
1173 const int32_t /*textLength*/,
1174 const uint32_t /*textColorRef*/,
1175 const uint32_t /*backgroundColorRef*/,
1176 const float /*left*/,
1177 const float /*top*/,
1178 const float /*right*/,
1179 const float /*bottom*/)
1180 {
1181
1182 return 0;
1183
1184 }
1185
1186 void VideoRenderNSOpenGL::LockAGLCntx()
1187 {
1188 _nsglContextCritSec.Enter();
1189 }
1190 void VideoRenderNSOpenGL::UnlockAGLCntx()
1191 {
1192 _nsglContextCritSec.Leave();
1193 }
1194
1195 /*
1196
1197 bool VideoRenderNSOpenGL::SetFullScreen(bool fullscreen)
1198 {
1199 NSRect mainDisplayRect, viewRect;
1200
1201 // Create a screen-sized window on the display you want to take over
1202 // Note, mainDisplayRect has a non-zero origin if the key window is on a second ary display
1203 mainDisplayRect = [[NSScreen mainScreen] frame];
1204 fullScreenWindow = [[NSWindow alloc] initWithContentRect:mainDisplayRect styleM ask:NSBorderlessWindowMask
1205 backing:NSBackingStoreBuffered defer:YES];
1206
1207 // Set the window level to be above the menu bar
1208 [fullScreenWindow setLevel:NSMainMenuWindowLevel+1];
1209
1210 // Perform any other window configuration you desire
1211 [fullScreenWindow setOpaque:YES];
1212 [fullScreenWindow setHidesOnDeactivate:YES];
1213
1214 // Create a view with a double-buffered OpenGL context and attach it to the win dow
1215 // By specifying the non-fullscreen context as the shareContext, we automatical ly inherit the OpenGL objects (textures, etc) it has defined
1216 viewRect = NSMakeRect(0.0, 0.0, mainDisplayRect.size.width, mainDisplayRect.siz e.height);
1217 fullScreenView = [[MyOpenGLView alloc] initWithFrame:viewRect shareContext:[ope nGLView openGLContext]];
1218 [fullScreenWindow setContentView:fullScreenView];
1219
1220 // Show the window
1221 [fullScreenWindow makeKeyAndOrderFront:self];
1222
1223 // Set the scene with the full-screen viewport and viewing transformation
1224 [scene setViewportRect:viewRect];
1225
1226 // Assign the view's MainController to self
1227 [fullScreenView setMainController:self];
1228
1229 if (!isAnimating) {
1230 // Mark the view as needing drawing to initalize its contents
1231 [fullScreenView setNeedsDisplay:YES];
1232 }
1233 else {
1234 // Start playing the animation
1235 [fullScreenView startAnimation];
1236 }
1237
1238 }
1239
1240
1241
1242 */
1243
1244
1245 } // namespace webrtc
1246
1247 #endif // COCOA_RENDERING
OLDNEW
« no previous file with comments | « webrtc/modules/video_render/mac/video_render_nsopengl.h ('k') | webrtc/modules/video_render/test/testAPI/renderStartImage.bmp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698