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

Unified Diff: webrtc/modules/video_render/mac/video_render_nsopengl.mm

Issue 1923613003: Revert of Delete video_render module. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 8 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 side-by-side diff with in-line comments
Download patch
Index: webrtc/modules/video_render/mac/video_render_nsopengl.mm
diff --git a/webrtc/modules/video_render/mac/video_render_nsopengl.mm b/webrtc/modules/video_render/mac/video_render_nsopengl.mm
new file mode 100644
index 0000000000000000000000000000000000000000..b7683a96af4895b078de5d9b4323e15f4da3d37b
--- /dev/null
+++ b/webrtc/modules/video_render/mac/video_render_nsopengl.mm
@@ -0,0 +1,1247 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/engine_configurations.h"
+#if defined(COCOA_RENDERING)
+
+#include "webrtc/base/platform_thread.h"
+#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
+#include "webrtc/modules/video_render/mac/video_render_nsopengl.h"
+#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
+#include "webrtc/system_wrappers/include/event_wrapper.h"
+#include "webrtc/system_wrappers/include/trace.h"
+
+namespace webrtc {
+
+VideoChannelNSOpenGL::VideoChannelNSOpenGL(NSOpenGLContext *nsglContext, int iId, VideoRenderNSOpenGL* owner) :
+_nsglContext( nsglContext),
+_id( iId),
+_owner( owner),
+_width( 0),
+_height( 0),
+_startWidth( 0.0f),
+_startHeight( 0.0f),
+_stopWidth( 0.0f),
+_stopHeight( 0.0f),
+_stretchedWidth( 0),
+_stretchedHeight( 0),
+_oldStretchedHeight( 0),
+_oldStretchedWidth( 0),
+_buffer( 0),
+_bufferSize( 0),
+_incomingBufferSize( 0),
+_bufferIsUpdated( false),
+_numberOfStreams( 0),
+_pixelFormat( GL_RGBA),
+_pixelDataType( GL_UNSIGNED_INT_8_8_8_8),
+_texture( 0)
+{
+
+}
+
+VideoChannelNSOpenGL::~VideoChannelNSOpenGL()
+{
+ if (_buffer)
+ {
+ delete [] _buffer;
+ _buffer = NULL;
+ }
+
+ if (_texture != 0)
+ {
+ [_nsglContext makeCurrentContext];
+ glDeleteTextures(1, (const GLuint*) &_texture);
+ _texture = 0;
+ }
+}
+
+int VideoChannelNSOpenGL::ChangeContext(NSOpenGLContext *nsglContext)
+{
+ _owner->LockAGLCntx();
+
+ _nsglContext = nsglContext;
+ [_nsglContext makeCurrentContext];
+
+ _owner->UnlockAGLCntx();
+ return 0;
+
+}
+
+int32_t VideoChannelNSOpenGL::GetChannelProperties(float& left, float& top,
+ float& right, float& bottom)
+{
+
+ _owner->LockAGLCntx();
+
+ left = _startWidth;
+ top = _startHeight;
+ right = _stopWidth;
+ bottom = _stopHeight;
+
+ _owner->UnlockAGLCntx();
+ return 0;
+}
+
+int32_t VideoChannelNSOpenGL::RenderFrame(const uint32_t /*streamId*/,
+ const VideoFrame& videoFrame) {
+ _owner->LockAGLCntx();
+
+ if(_width != videoFrame.width() ||
+ _height != videoFrame.height()) {
+ if(FrameSizeChange(videoFrame.width(), videoFrame.height(), 1) == -1) {
+ _owner->UnlockAGLCntx();
+ return -1;
+ }
+ }
+ int ret = DeliverFrame(videoFrame);
+
+ _owner->UnlockAGLCntx();
+ return ret;
+}
+
+int VideoChannelNSOpenGL::UpdateSize(int width, int height)
+{
+ _owner->LockAGLCntx();
+ _width = width;
+ _height = height;
+ _owner->UnlockAGLCntx();
+ return 0;
+}
+
+int VideoChannelNSOpenGL::UpdateStretchSize(int stretchHeight, int stretchWidth)
+{
+
+ _owner->LockAGLCntx();
+ _stretchedHeight = stretchHeight;
+ _stretchedWidth = stretchWidth;
+ _owner->UnlockAGLCntx();
+ return 0;
+}
+
+int VideoChannelNSOpenGL::FrameSizeChange(int width, int height, int numberOfStreams)
+{
+ // We got a new frame size from VideoAPI, prepare the buffer
+
+ _owner->LockAGLCntx();
+
+ if (width == _width && _height == height)
+ {
+ // We already have a correct buffer size
+ _numberOfStreams = numberOfStreams;
+ _owner->UnlockAGLCntx();
+ return 0;
+ }
+
+ _width = width;
+ _height = height;
+
+ // Delete the old buffer, create a new one with correct size.
+ if (_buffer)
+ {
+ delete [] _buffer;
+ _bufferSize = 0;
+ }
+
+ _incomingBufferSize = CalcBufferSize(kI420, _width, _height);
+ _bufferSize = CalcBufferSize(kARGB, _width, _height);
+ _buffer = new unsigned char [_bufferSize];
+ memset(_buffer, 0, _bufferSize * sizeof(unsigned char));
+
+ [_nsglContext makeCurrentContext];
+
+ if(glIsTexture(_texture))
+ {
+ glDeleteTextures(1, (const GLuint*) &_texture);
+ _texture = 0;
+ }
+
+ // Create a new texture
+ glGenTextures(1, (GLuint *) &_texture);
+
+ GLenum glErr = glGetError();
+
+ if (glErr != GL_NO_ERROR)
+ {
+
+ }
+
+ glBindTexture(GL_TEXTURE_RECTANGLE_EXT, _texture);
+
+ GLint texSize;
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texSize);
+
+ if (texSize < _width || texSize < _height)
+ {
+ _owner->UnlockAGLCntx();
+ return -1;
+ }
+
+ // Set up th texture type and size
+ glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, // target
+ 0, // level
+ GL_RGBA, // internal format
+ _width, // width
+ _height, // height
+ 0, // border 0/1 = off/on
+ _pixelFormat, // format, GL_RGBA
+ _pixelDataType, // data type, GL_UNSIGNED_INT_8_8_8_8
+ _buffer); // pixel data
+
+ glErr = glGetError();
+ if (glErr != GL_NO_ERROR)
+ {
+ _owner->UnlockAGLCntx();
+ return -1;
+ }
+
+ _owner->UnlockAGLCntx();
+ return 0;
+}
+
+int VideoChannelNSOpenGL::DeliverFrame(const VideoFrame& videoFrame) {
+ _owner->LockAGLCntx();
+
+ if (_texture == 0) {
+ _owner->UnlockAGLCntx();
+ return 0;
+ }
+
+ if (CalcBufferSize(kI420, videoFrame.width(), videoFrame.height()) !=
+ _incomingBufferSize) {
+ _owner->UnlockAGLCntx();
+ return -1;
+ }
+
+ // Using the VideoFrame for YV12: YV12 is YVU; I420 assumes
+ // YUV.
+ // TODO(mikhal) : Use appropriate functionality.
+ // TODO(wu): See if we are using glTexSubImage2D correctly.
+ int rgbRet = ConvertFromYV12(videoFrame, kBGRA, 0, _buffer);
+ if (rgbRet < 0) {
+ _owner->UnlockAGLCntx();
+ return -1;
+ }
+
+ [_nsglContext makeCurrentContext];
+
+ // Make sure this texture is the active one
+ glBindTexture(GL_TEXTURE_RECTANGLE_EXT, _texture);
+ GLenum glErr = glGetError();
+ if (glErr != GL_NO_ERROR) {
+ WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
+ "ERROR %d while calling glBindTexture", glErr);
+ _owner->UnlockAGLCntx();
+ return -1;
+ }
+
+ glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT,
+ 0, // Level, not use
+ 0, // start point x, (low left of pic)
+ 0, // start point y,
+ _width, // width
+ _height, // height
+ _pixelFormat, // pictue format for _buffer
+ _pixelDataType, // data type of _buffer
+ (const GLvoid*) _buffer); // the pixel data
+
+ glErr = glGetError();
+ if (glErr != GL_NO_ERROR) {
+ WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,
+ "ERROR %d while calling glTexSubImage2d", glErr);
+ _owner->UnlockAGLCntx();
+ return -1;
+ }
+
+ _bufferIsUpdated = true;
+
+ _owner->UnlockAGLCntx();
+ return 0;
+}
+
+int VideoChannelNSOpenGL::RenderOffScreenBuffer()
+{
+
+ _owner->LockAGLCntx();
+
+ if (_texture == 0)
+ {
+ _owner->UnlockAGLCntx();
+ return 0;
+ }
+
+ // if(_fullscreen)
+ // {
+ // NSRect mainDisplayRect = [[NSScreen mainScreen] frame];
+ // _width = mainDisplayRect.size.width;
+ // _height = mainDisplayRect.size.height;
+ // glViewport(0, 0, mainDisplayRect.size.width, mainDisplayRect.size.height);
+ // float newX = mainDisplayRect.size.width/_width;
+ // float newY = mainDisplayRect.size.height/_height;
+
+ // convert from 0.0 <= size <= 1.0 to
+ // open gl world -1.0 < size < 1.0
+ GLfloat xStart = 2.0f * _startWidth - 1.0f;
+ GLfloat xStop = 2.0f * _stopWidth - 1.0f;
+ GLfloat yStart = 1.0f - 2.0f * _stopHeight;
+ GLfloat yStop = 1.0f - 2.0f * _startHeight;
+
+ [_nsglContext makeCurrentContext];
+
+ glBindTexture(GL_TEXTURE_RECTANGLE_EXT, _texture);
+ _oldStretchedHeight = _stretchedHeight;
+ _oldStretchedWidth = _stretchedWidth;
+
+ glLoadIdentity();
+ glEnable(GL_TEXTURE_RECTANGLE_EXT);
+ glBegin(GL_POLYGON);
+ {
+ glTexCoord2f(0.0, 0.0); glVertex2f(xStart, yStop);
+ glTexCoord2f(_width, 0.0); glVertex2f(xStop, yStop);
+ glTexCoord2f(_width, _height); glVertex2f(xStop, yStart);
+ glTexCoord2f(0.0, _height); glVertex2f(xStart, yStart);
+ }
+ glEnd();
+
+ glDisable(GL_TEXTURE_RECTANGLE_EXT);
+
+ _bufferIsUpdated = false;
+
+ _owner->UnlockAGLCntx();
+ return 0;
+}
+
+int VideoChannelNSOpenGL::IsUpdated(bool& isUpdated)
+{
+ _owner->LockAGLCntx();
+
+ isUpdated = _bufferIsUpdated;
+
+ _owner->UnlockAGLCntx();
+ return 0;
+}
+
+int VideoChannelNSOpenGL::SetStreamSettings(int /*streamId*/, float startWidth, float startHeight, float stopWidth, float stopHeight)
+{
+ _owner->LockAGLCntx();
+
+ _startWidth = startWidth;
+ _stopWidth = stopWidth;
+ _startHeight = startHeight;
+ _stopHeight = stopHeight;
+
+ int oldWidth = _width;
+ int oldHeight = _height;
+ int oldNumberOfStreams = _numberOfStreams;
+
+ _width = 0;
+ _height = 0;
+
+ int retVal = FrameSizeChange(oldWidth, oldHeight, oldNumberOfStreams);
+
+ _owner->UnlockAGLCntx();
+ return retVal;
+}
+
+int VideoChannelNSOpenGL::SetStreamCropSettings(int /*streamId*/, float /*startWidth*/, float /*startHeight*/, float /*stopWidth*/, float /*stopHeight*/)
+{
+ return -1;
+}
+
+/*
+ *
+ * VideoRenderNSOpenGL
+ *
+ */
+
+VideoRenderNSOpenGL::VideoRenderNSOpenGL(CocoaRenderView *windowRef, bool fullScreen, int iId) :
+_windowRef( (CocoaRenderView*)windowRef),
+_fullScreen( fullScreen),
+_id( iId),
+_nsglContextCritSec( *CriticalSectionWrapper::CreateCriticalSection()),
+_screenUpdateEvent(EventTimerWrapper::Create()),
+_nsglContext( 0),
+_nsglFullScreenContext( 0),
+_fullScreenWindow( nil),
+_windowRect( ),
+_windowWidth( 0),
+_windowHeight( 0),
+_nsglChannels( ),
+_zOrderToChannel( ),
+_renderingIsPaused (FALSE),
+_windowRefSuperView(NULL),
+_windowRefSuperViewFrame(NSMakeRect(0,0,0,0))
+{
+ _screenUpdateThread.reset(new rtc::PlatformThread(
+ ScreenUpdateThreadProc, this, "ScreenUpdateNSOpenGL"));
+}
+
+int VideoRenderNSOpenGL::ChangeWindow(CocoaRenderView* newWindowRef)
+{
+
+ LockAGLCntx();
+
+ _windowRef = newWindowRef;
+
+ if(CreateMixingContext() == -1)
+ {
+ UnlockAGLCntx();
+ return -1;
+ }
+
+ int error = 0;
+ std::map<int, VideoChannelNSOpenGL*>::iterator it = _nsglChannels.begin();
+ while (it!= _nsglChannels.end())
+ {
+ error |= (it->second)->ChangeContext(_nsglContext);
+ it++;
+ }
+ if(error != 0)
+ {
+ UnlockAGLCntx();
+ return -1;
+ }
+
+ UnlockAGLCntx();
+ return 0;
+}
+
+/* Check if the thread and event already exist.
+ * If so then they will simply be restarted
+ * If not then create them and continue
+ */
+int32_t VideoRenderNSOpenGL::StartRender()
+{
+
+ LockAGLCntx();
+
+ const unsigned int MONITOR_FREQ = 60;
+ if(TRUE == _renderingIsPaused)
+ {
+ WEBRTC_TRACE(kTraceDebug, kTraceVideoRenderer, _id, "Restarting screenUpdateThread");
+
+ // we already have the thread. Most likely StopRender() was called and they were paused
+ _screenUpdateThread->Start();
+ if (FALSE ==
+ _screenUpdateEvent->StartTimer(true, 1000 / MONITOR_FREQ)) {
+ WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, "Failed to restart screenUpdateThread or screenUpdateEvent");
+ UnlockAGLCntx();
+ return -1;
+ }
+
+ _screenUpdateThread->SetPriority(rtc::kRealtimePriority);
+
+ UnlockAGLCntx();
+ return 0;
+ }
+
+
+ if (!_screenUpdateThread)
+ {
+ WEBRTC_TRACE(kTraceDebug, kTraceVideoRenderer, _id, "failed start screenUpdateThread");
+ UnlockAGLCntx();
+ return -1;
+ }
+
+
+ UnlockAGLCntx();
+ return 0;
+}
+int32_t VideoRenderNSOpenGL::StopRender()
+{
+
+ LockAGLCntx();
+
+ /* The code below is functional
+ * but it pauses for several seconds
+ */
+
+ // pause the update thread and the event timer
+ if(!_screenUpdateThread || !_screenUpdateEvent)
+ {
+ _renderingIsPaused = TRUE;
+
+ UnlockAGLCntx();
+ return 0;
+ }
+
+ _screenUpdateThread->Stop();
+ if (FALSE == _screenUpdateEvent->StopTimer()) {
+ _renderingIsPaused = FALSE;
+
+ UnlockAGLCntx();
+ return -1;
+ }
+
+ _renderingIsPaused = TRUE;
+
+ UnlockAGLCntx();
+ return 0;
+}
+
+int VideoRenderNSOpenGL::configureNSOpenGLView()
+{
+ return 0;
+
+}
+
+int VideoRenderNSOpenGL::configureNSOpenGLEngine()
+{
+
+ LockAGLCntx();
+
+ // Disable not needed functionality to increase performance
+ glDisable(GL_DITHER);
+ glDisable(GL_ALPHA_TEST);
+ glDisable(GL_STENCIL_TEST);
+ glDisable(GL_FOG);
+ glDisable(GL_TEXTURE_2D);
+ glPixelZoom(1.0, 1.0);
+ glDisable(GL_BLEND);
+ glDisable(GL_DEPTH_TEST);
+ glDepthMask(GL_FALSE);
+ glDisable(GL_CULL_FACE);
+
+ // Set texture parameters
+ glTexParameterf(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_PRIORITY, 1.0);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE);
+
+ if (GetWindowRect(_windowRect) == -1)
+ {
+ UnlockAGLCntx();
+ return true;
+ }
+
+ if (_windowWidth != (_windowRect.right - _windowRect.left)
+ || _windowHeight != (_windowRect.bottom - _windowRect.top))
+ {
+ _windowWidth = _windowRect.right - _windowRect.left;
+ _windowHeight = _windowRect.bottom - _windowRect.top;
+ }
+ glViewport(0, 0, _windowWidth, _windowHeight);
+
+ // Synchronize buffer swaps with vertical refresh rate
+ GLint swapInt = 1;
+ [_nsglContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
+
+ UnlockAGLCntx();
+ return 0;
+}
+
+int VideoRenderNSOpenGL::setRenderTargetWindow()
+{
+ LockAGLCntx();
+
+
+ GLuint attribs[] =
+ {
+ NSOpenGLPFAColorSize, 24,
+ NSOpenGLPFAAlphaSize, 8,
+ NSOpenGLPFADepthSize, 16,
+ NSOpenGLPFAAccelerated,
+ 0
+ };
+
+ NSOpenGLPixelFormat* fmt = [[[NSOpenGLPixelFormat alloc] initWithAttributes:
+ (NSOpenGLPixelFormatAttribute*) attribs] autorelease];
+
+ if(_windowRef)
+ {
+ [_windowRef initCocoaRenderView:fmt];
+ }
+ else
+ {
+ UnlockAGLCntx();
+ return -1;
+ }
+
+ _nsglContext = [_windowRef nsOpenGLContext];
+ [_nsglContext makeCurrentContext];
+
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+
+ DisplayBuffers();
+
+ UnlockAGLCntx();
+ return 0;
+}
+
+int VideoRenderNSOpenGL::setRenderTargetFullScreen()
+{
+ LockAGLCntx();
+
+
+ GLuint attribs[] =
+ {
+ NSOpenGLPFAColorSize, 24,
+ NSOpenGLPFAAlphaSize, 8,
+ NSOpenGLPFADepthSize, 16,
+ NSOpenGLPFAAccelerated,
+ 0
+ };
+
+ NSOpenGLPixelFormat* fmt = [[[NSOpenGLPixelFormat alloc] initWithAttributes:
+ (NSOpenGLPixelFormatAttribute*) attribs] autorelease];
+
+ // Store original superview and frame for use when exiting full screens
+ _windowRefSuperViewFrame = [_windowRef frame];
+ _windowRefSuperView = [_windowRef superview];
+
+
+ // create new fullscreen window
+ NSRect screenRect = [[NSScreen mainScreen]frame];
+ [_windowRef setFrame:screenRect];
+ [_windowRef setBounds:screenRect];
+
+
+ _fullScreenWindow = [[CocoaFullScreenWindow alloc]init];
+ [_fullScreenWindow grabFullScreen];
+ [[[_fullScreenWindow window] contentView] addSubview:_windowRef];
+
+ if(_windowRef)
+ {
+ [_windowRef initCocoaRenderViewFullScreen:fmt];
+ }
+ else
+ {
+ UnlockAGLCntx();
+ return -1;
+ }
+
+ _nsglContext = [_windowRef nsOpenGLContext];
+ [_nsglContext makeCurrentContext];
+
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ DisplayBuffers();
+
+ UnlockAGLCntx();
+ return 0;
+}
+
+VideoRenderNSOpenGL::~VideoRenderNSOpenGL()
+{
+
+ if(_fullScreen)
+ {
+ if(_fullScreenWindow)
+ {
+ // Detach CocoaRenderView from full screen view back to
+ // it's original parent.
+ [_windowRef removeFromSuperview];
+ if(_windowRefSuperView)
+ {
+ [_windowRefSuperView addSubview:_windowRef];
+ [_windowRef setFrame:_windowRefSuperViewFrame];
+ }
+
+ WEBRTC_TRACE(kTraceDebug, kTraceVideoRenderer, 0, "%s:%d Attempting to release fullscreen window", __FUNCTION__, __LINE__);
+ [_fullScreenWindow releaseFullScreen];
+
+ }
+ }
+
+ // Signal event to exit thread, then delete it
+ rtc::PlatformThread* tmpPtr = _screenUpdateThread.release();
+
+ if (tmpPtr)
+ {
+ _screenUpdateEvent->Set();
+ _screenUpdateEvent->StopTimer();
+
+ tmpPtr->Stop();
+ delete tmpPtr;
+ delete _screenUpdateEvent;
+ _screenUpdateEvent = NULL;
+ }
+
+ if (_nsglContext != 0)
+ {
+ [_nsglContext makeCurrentContext];
+ _nsglContext = nil;
+ }
+
+ // Delete all channels
+ std::map<int, VideoChannelNSOpenGL*>::iterator it = _nsglChannels.begin();
+ while (it!= _nsglChannels.end())
+ {
+ delete it->second;
+ _nsglChannels.erase(it);
+ it = _nsglChannels.begin();
+ }
+ _nsglChannels.clear();
+
+ // Clean the zOrder map
+ std::multimap<int, int>::iterator zIt = _zOrderToChannel.begin();
+ while(zIt != _zOrderToChannel.end())
+ {
+ _zOrderToChannel.erase(zIt);
+ zIt = _zOrderToChannel.begin();
+ }
+ _zOrderToChannel.clear();
+
+}
+
+/* static */
+int VideoRenderNSOpenGL::GetOpenGLVersion(int& /*nsglMajor*/, int& /*nsglMinor*/)
+{
+ return -1;
+}
+
+int VideoRenderNSOpenGL::Init()
+{
+
+ LockAGLCntx();
+ if (!_screenUpdateThread)
+ {
+ UnlockAGLCntx();
+ return -1;
+ }
+
+ _screenUpdateThread->Start();
+ _screenUpdateThread->SetPriority(rtc::kRealtimePriority);
+
+ // Start the event triggering the render process
+ unsigned int monitorFreq = 60;
+ _screenUpdateEvent->StartTimer(true, 1000/monitorFreq);
+
+ if (CreateMixingContext() == -1)
+ {
+ UnlockAGLCntx();
+ return -1;
+ }
+
+ UnlockAGLCntx();
+ return 0;
+}
+
+VideoChannelNSOpenGL* VideoRenderNSOpenGL::CreateNSGLChannel(int channel, int zOrder, float startWidth, float startHeight, float stopWidth, float stopHeight)
+{
+ CriticalSectionScoped cs(&_nsglContextCritSec);
+
+ if (HasChannel(channel))
+ {
+ return NULL;
+ }
+
+ if (_zOrderToChannel.find(zOrder) != _zOrderToChannel.end())
+ {
+
+ }
+
+ VideoChannelNSOpenGL* newAGLChannel = new VideoChannelNSOpenGL(_nsglContext, _id, this);
+ if (newAGLChannel->SetStreamSettings(0, startWidth, startHeight, stopWidth, stopHeight) == -1)
+ {
+ if (newAGLChannel)
+ {
+ delete newAGLChannel;
+ newAGLChannel = NULL;
+ }
+
+ return NULL;
+ }
+
+ _nsglChannels[channel] = newAGLChannel;
+ _zOrderToChannel.insert(std::pair<int, int>(zOrder, channel));
+
+ WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _id, "%s successfully created NSGL channel number %d", __FUNCTION__, channel);
+
+ return newAGLChannel;
+}
+
+int VideoRenderNSOpenGL::DeleteAllNSGLChannels()
+{
+
+ CriticalSectionScoped cs(&_nsglContextCritSec);
+
+ std::map<int, VideoChannelNSOpenGL*>::iterator it;
+ it = _nsglChannels.begin();
+
+ while (it != _nsglChannels.end())
+ {
+ VideoChannelNSOpenGL* channel = it->second;
+ WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _id, "%s Deleting channel %d", __FUNCTION__, channel);
+ delete channel;
+ it++;
+ }
+ _nsglChannels.clear();
+ return 0;
+}
+
+int32_t VideoRenderNSOpenGL::DeleteNSGLChannel(const uint32_t channel)
+{
+
+ CriticalSectionScoped cs(&_nsglContextCritSec);
+
+ std::map<int, VideoChannelNSOpenGL*>::iterator it;
+ it = _nsglChannels.find(channel);
+ if (it != _nsglChannels.end())
+ {
+ delete it->second;
+ _nsglChannels.erase(it);
+ }
+ else
+ {
+ return -1;
+ }
+
+ std::multimap<int, int>::iterator zIt = _zOrderToChannel.begin();
+ while( zIt != _zOrderToChannel.end())
+ {
+ if (zIt->second == (int)channel)
+ {
+ _zOrderToChannel.erase(zIt);
+ break;
+ }
+ zIt++;
+ }
+
+ return 0;
+}
+
+int32_t VideoRenderNSOpenGL::GetChannelProperties(const uint16_t streamId,
+ uint32_t& zOrder,
+ float& left,
+ float& top,
+ float& right,
+ float& bottom)
+{
+
+ CriticalSectionScoped cs(&_nsglContextCritSec);
+
+ bool channelFound = false;
+
+ // Loop through all channels until we find a match.
+ // From that, get zorder.
+ // From that, get T, L, R, B
+ for (std::multimap<int, int>::reverse_iterator rIt = _zOrderToChannel.rbegin();
+ rIt != _zOrderToChannel.rend();
+ rIt++)
+ {
+ if(streamId == rIt->second)
+ {
+ channelFound = true;
+
+ zOrder = rIt->second;
+
+ std::map<int, VideoChannelNSOpenGL*>::iterator rIt = _nsglChannels.find(streamId);
+ VideoChannelNSOpenGL* tempChannel = rIt->second;
+
+ if(-1 == tempChannel->GetChannelProperties(left, top, right, bottom) )
+ {
+ return -1;
+ }
+ break;
+ }
+ }
+
+ if(false == channelFound)
+ {
+
+ return -1;
+ }
+
+ return 0;
+}
+
+int VideoRenderNSOpenGL::StopThread()
+{
+
+ rtc::PlatformThread* tmpPtr = _screenUpdateThread.release();
+ WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _id,
+ "%s Stopping thread ", __FUNCTION__, tmpPtr);
+
+ if (tmpPtr)
+ {
+ _screenUpdateEvent->Set();
+ tmpPtr->Stop();
+ delete tmpPtr;
+ }
+
+ delete _screenUpdateEvent;
+ _screenUpdateEvent = NULL;
+
+ return 0;
+}
+
+bool VideoRenderNSOpenGL::IsFullScreen()
+{
+
+ CriticalSectionScoped cs(&_nsglContextCritSec);
+ return _fullScreen;
+}
+
+bool VideoRenderNSOpenGL::HasChannels()
+{
+ CriticalSectionScoped cs(&_nsglContextCritSec);
+
+ if (_nsglChannels.begin() != _nsglChannels.end())
+ {
+ return true;
+ }
+ return false;
+}
+
+bool VideoRenderNSOpenGL::HasChannel(int channel)
+{
+
+ CriticalSectionScoped cs(&_nsglContextCritSec);
+
+ std::map<int, VideoChannelNSOpenGL*>::iterator it = _nsglChannels.find(channel);
+
+ if (it != _nsglChannels.end())
+ {
+ return true;
+ }
+ return false;
+}
+
+int VideoRenderNSOpenGL::GetChannels(std::list<int>& channelList)
+{
+
+ CriticalSectionScoped cs(&_nsglContextCritSec);
+
+ std::map<int, VideoChannelNSOpenGL*>::iterator it = _nsglChannels.begin();
+
+ while (it != _nsglChannels.end())
+ {
+ channelList.push_back(it->first);
+ it++;
+ }
+
+ return 0;
+}
+
+VideoChannelNSOpenGL* VideoRenderNSOpenGL::ConfigureNSGLChannel(int channel, int zOrder, float startWidth, float startHeight, float stopWidth, float stopHeight)
+{
+
+ CriticalSectionScoped cs(&_nsglContextCritSec);
+
+ std::map<int, VideoChannelNSOpenGL*>::iterator it = _nsglChannels.find(channel);
+
+ if (it != _nsglChannels.end())
+ {
+ VideoChannelNSOpenGL* aglChannel = it->second;
+ if (aglChannel->SetStreamSettings(0, startWidth, startHeight, stopWidth, stopHeight) == -1)
+ {
+ WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id, "%s failed to set stream settings: channel %d. channel=%d zOrder=%d startWidth=%d startHeight=%d stopWidth=%d stopHeight=%d",
+ __FUNCTION__, channel, zOrder, startWidth, startHeight, stopWidth, stopHeight);
+ return NULL;
+ }
+ WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _id, "%s Configuring channel %d. channel=%d zOrder=%d startWidth=%d startHeight=%d stopWidth=%d stopHeight=%d",
+ __FUNCTION__, channel, zOrder, startWidth, startHeight, stopWidth, stopHeight);
+
+ std::multimap<int, int>::iterator it = _zOrderToChannel.begin();
+ while(it != _zOrderToChannel.end())
+ {
+ if (it->second == channel)
+ {
+ if (it->first != zOrder)
+ {
+ _zOrderToChannel.erase(it);
+ _zOrderToChannel.insert(std::pair<int, int>(zOrder, channel));
+ }
+ break;
+ }
+ it++;
+ }
+ return aglChannel;
+ }
+
+ return NULL;
+}
+
+/*
+ *
+ * Rendering process
+ *
+ */
+
+bool VideoRenderNSOpenGL::ScreenUpdateThreadProc(void* obj)
+{
+ return static_cast<VideoRenderNSOpenGL*>(obj)->ScreenUpdateProcess();
+}
+
+bool VideoRenderNSOpenGL::ScreenUpdateProcess()
+{
+
+ _screenUpdateEvent->Wait(10);
+ LockAGLCntx();
+
+ if (!_screenUpdateThread)
+ {
+ WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, _id, "%s no screen update thread", __FUNCTION__);
+ UnlockAGLCntx();
+ return false;
+ }
+
+ [_nsglContext makeCurrentContext];
+
+ if (GetWindowRect(_windowRect) == -1)
+ {
+ UnlockAGLCntx();
+ return true;
+ }
+
+ if (_windowWidth != (_windowRect.right - _windowRect.left)
+ || _windowHeight != (_windowRect.bottom - _windowRect.top))
+ {
+ _windowWidth = _windowRect.right - _windowRect.left;
+ _windowHeight = _windowRect.bottom - _windowRect.top;
+ glViewport(0, 0, _windowWidth, _windowHeight);
+ }
+
+ // Check if there are any updated buffers
+ bool updated = false;
+ std::map<int, VideoChannelNSOpenGL*>::iterator it = _nsglChannels.begin();
+ while (it != _nsglChannels.end())
+ {
+
+ VideoChannelNSOpenGL* aglChannel = it->second;
+ aglChannel->UpdateStretchSize(_windowHeight, _windowWidth);
+ aglChannel->IsUpdated(updated);
+ if (updated)
+ {
+ break;
+ }
+ it++;
+ }
+
+ if (updated)
+ {
+
+ // At least on buffers is updated, we need to repaint the texture
+ if (RenderOffScreenBuffers() != -1)
+ {
+ UnlockAGLCntx();
+ return true;
+ }
+ }
+ // }
+ UnlockAGLCntx();
+ return true;
+}
+
+/*
+ *
+ * Functions for creating mixing buffers and screen settings
+ *
+ */
+
+int VideoRenderNSOpenGL::CreateMixingContext()
+{
+
+ CriticalSectionScoped cs(&_nsglContextCritSec);
+
+ if(_fullScreen)
+ {
+ if(-1 == setRenderTargetFullScreen())
+ {
+ return -1;
+ }
+ }
+ else
+ {
+
+ if(-1 == setRenderTargetWindow())
+ {
+ return -1;
+ }
+ }
+
+ configureNSOpenGLEngine();
+
+ DisplayBuffers();
+
+ GLenum glErr = glGetError();
+ if (glErr)
+ {
+ }
+
+ return 0;
+}
+
+/*
+ *
+ * Rendering functions
+ *
+ */
+
+int VideoRenderNSOpenGL::RenderOffScreenBuffers()
+{
+ LockAGLCntx();
+
+ // Get the current window size, it might have changed since last render.
+ if (GetWindowRect(_windowRect) == -1)
+ {
+ UnlockAGLCntx();
+ return -1;
+ }
+
+ [_nsglContext makeCurrentContext];
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ // Loop through all channels starting highest zOrder ending with lowest.
+ for (std::multimap<int, int>::reverse_iterator rIt = _zOrderToChannel.rbegin();
+ rIt != _zOrderToChannel.rend();
+ rIt++)
+ {
+ int channelId = rIt->second;
+ std::map<int, VideoChannelNSOpenGL*>::iterator it = _nsglChannels.find(channelId);
+
+ VideoChannelNSOpenGL* aglChannel = it->second;
+
+ aglChannel->RenderOffScreenBuffer();
+ }
+
+ DisplayBuffers();
+
+ UnlockAGLCntx();
+ return 0;
+}
+
+/*
+ *
+ * Help functions
+ *
+ * All help functions assumes external protections
+ *
+ */
+
+int VideoRenderNSOpenGL::DisplayBuffers()
+{
+
+ LockAGLCntx();
+
+ glFinish();
+ [_nsglContext flushBuffer];
+
+ WEBRTC_TRACE(kTraceDebug, kTraceVideoRenderer, _id, "%s glFinish and [_nsglContext flushBuffer]", __FUNCTION__);
+
+ UnlockAGLCntx();
+ return 0;
+}
+
+int VideoRenderNSOpenGL::GetWindowRect(Rect& rect)
+{
+
+ CriticalSectionScoped cs(&_nsglContextCritSec);
+
+ if (_windowRef)
+ {
+ if(_fullScreen)
+ {
+ NSRect mainDisplayRect = [[NSScreen mainScreen] frame];
+ rect.bottom = 0;
+ rect.left = 0;
+ rect.right = mainDisplayRect.size.width;
+ rect.top = mainDisplayRect.size.height;
+ }
+ else
+ {
+ rect.top = [_windowRef frame].origin.y;
+ rect.left = [_windowRef frame].origin.x;
+ rect.bottom = [_windowRef frame].origin.y + [_windowRef frame].size.height;
+ rect.right = [_windowRef frame].origin.x + [_windowRef frame].size.width;
+ }
+
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+int32_t VideoRenderNSOpenGL::SetText(const uint8_t /*textId*/,
+ const uint8_t* /*text*/,
+ const int32_t /*textLength*/,
+ const uint32_t /*textColorRef*/,
+ const uint32_t /*backgroundColorRef*/,
+ const float /*left*/,
+ const float /*top*/,
+ const float /*right*/,
+ const float /*bottom*/)
+{
+
+ return 0;
+
+}
+
+void VideoRenderNSOpenGL::LockAGLCntx()
+{
+ _nsglContextCritSec.Enter();
+}
+void VideoRenderNSOpenGL::UnlockAGLCntx()
+{
+ _nsglContextCritSec.Leave();
+}
+
+/*
+
+ bool VideoRenderNSOpenGL::SetFullScreen(bool fullscreen)
+ {
+ NSRect mainDisplayRect, viewRect;
+
+ // Create a screen-sized window on the display you want to take over
+ // Note, mainDisplayRect has a non-zero origin if the key window is on a secondary display
+ mainDisplayRect = [[NSScreen mainScreen] frame];
+ fullScreenWindow = [[NSWindow alloc] initWithContentRect:mainDisplayRect styleMask:NSBorderlessWindowMask
+ backing:NSBackingStoreBuffered defer:YES];
+
+ // Set the window level to be above the menu bar
+ [fullScreenWindow setLevel:NSMainMenuWindowLevel+1];
+
+ // Perform any other window configuration you desire
+ [fullScreenWindow setOpaque:YES];
+ [fullScreenWindow setHidesOnDeactivate:YES];
+
+ // Create a view with a double-buffered OpenGL context and attach it to the window
+ // By specifying the non-fullscreen context as the shareContext, we automatically inherit the OpenGL objects (textures, etc) it has defined
+ viewRect = NSMakeRect(0.0, 0.0, mainDisplayRect.size.width, mainDisplayRect.size.height);
+ fullScreenView = [[MyOpenGLView alloc] initWithFrame:viewRect shareContext:[openGLView openGLContext]];
+ [fullScreenWindow setContentView:fullScreenView];
+
+ // Show the window
+ [fullScreenWindow makeKeyAndOrderFront:self];
+
+ // Set the scene with the full-screen viewport and viewing transformation
+ [scene setViewportRect:viewRect];
+
+ // Assign the view's MainController to self
+ [fullScreenView setMainController:self];
+
+ if (!isAnimating) {
+ // Mark the view as needing drawing to initalize its contents
+ [fullScreenView setNeedsDisplay:YES];
+ }
+ else {
+ // Start playing the animation
+ [fullScreenView startAnimation];
+ }
+
+ }
+
+
+
+ */
+
+
+} // namespace webrtc
+
+#endif // COCOA_RENDERING
« 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