webrtc/modules/video_capture/main/test/testAPI/Renderer.cpp

407 lines
12 KiB
C++

/*
* Copyright (c) 2011 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 "Renderer.h"
#include <stdio.h>
#include "thread_wrapper.h"
#include "tick_util.h"
#if defined _WIN32
#include <tchar.h>
#endif
namespace webrtc
{
#if defined _WIN32
#define SLEEP_10_SEC ::Sleep(10000)
#define GET_TIME_IN_MS timeGetTime
LRESULT CALLBACK WinProc( HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
switch(uMsg)
{
case WM_DESTROY:
break;
case WM_COMMAND:
break;
}
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
int WebRtcCreateWindow(HWND &hwndMain,int winNum, int width, int height)
{
HINSTANCE hinst = GetModuleHandle(0);
WNDCLASSEX wcx;
wcx.hInstance = hinst;
wcx.lpszClassName = _T(" test camera delay");
wcx.lpfnWndProc = (WNDPROC)WinProc;
wcx.style = CS_DBLCLKS;
wcx.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wcx.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wcx.hCursor = LoadCursor (NULL, IDC_ARROW);
wcx.lpszMenuName = NULL;
wcx.cbSize = sizeof (WNDCLASSEX);
wcx.cbClsExtra = 0;
wcx.cbWndExtra = 0;
wcx.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
// Register our window class with the operating system.
// If there is an error, exit program.
if ( !RegisterClassEx (&wcx) )
{
//MessageBox( 0, TEXT("Failed to register window class!"),TEXT("Error!"), MB_OK|MB_ICONERROR ) ;
//return 0;
}
// Create the main window.
hwndMain = CreateWindowEx(
0, // no extended styles
wcx.lpszClassName, // class name
_T("Test Camera Delay"), // window name
WS_OVERLAPPED |WS_THICKFRAME, // overlapped window
0, // horizontal position
0, // vertical position
width, // width
height, // height
(HWND) NULL, // no parent or owner window
(HMENU) NULL, // class menu used
hinst, // instance handle
NULL); // no window creation data
if (!hwndMain)
{
int error = GetLastError();
return -1;
}
// Show the window using the flag specified by the program
// that started the application, and send the application
// a WM_PAINT message.
ShowWindow(hwndMain, SW_SHOWDEFAULT);
UpdateWindow(hwndMain);
return 0;
}
void SetWindowPos(HWND &hwndMain, int x, int y, int width, int height, bool onTop)
{
/* if(onTop)
{
SetWindowPos(hwndMain,HWND_TOPMOST,x,y,width,height,0);
}
else*/
{
SetWindowPos(hwndMain,HWND_TOP,x,y,width,height,0);
}
}
#elif defined(WEBRTC_MAC_INTEL)
static int _screen = 0;
int WebRtcCreateWindow(CocoaRenderer*& cocoaRenderer,int winNum, int width, int height)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc]init];
_screen = winNum = 0;
// In Cocoa, rendering is not done directly to a window like in Windows and Linux.
// It is rendererd to a Subclass of NSOpenGLView
// create cocoa container window
NSRect outWindowFrame = NSMakeRect(200, 800, width + 20, height + 20);
NSArray* screens = [NSScreen screens];
if(_screen >= [screens count])
{
// requesting screen
return -1;
}
NSScreen* screen = (NSScreen*)[screens objectAtIndex:_screen];
NSWindow* outWindow = [[NSWindow alloc] initWithContentRect:outWindowFrame styleMask:NSTitledWindowMask backing:NSBackingStoreBuffered defer:NO screen:screen];
[outWindow orderOut:nil];
[outWindow setTitle:@"Cocoa Renderer"];
[outWindow setBackgroundColor:[NSColor blueColor]];
[[outWindow contentView] setAutoresizesSubviews:YES];
// // ***** TODO: test screen positioning *****
// // set to the appropriate screen
// NSArray* screens = [NSScreen screens];
// printf("TODO: test positioning to correct screen\n");
// switch(winNum){
// case 0:
// if([screens count] >= 1){
// [outWindow constrainFrameRect:outWindowFrame toScreen:(NSScreen*)[screens objectAtIndex:0]];
// }
// break;
// case 1:
// if([screens count] >= 2){
// [outWindow constrainFrameRect:outWindowFrame toScreen:(NSScreen*)[screens objectAtIndex:1]];
// }
// break;
// case 2:
// if([screens count] >= 3){
// [outWindow constrainFrameRect:outWindowFrame toScreen:(NSScreen*)[screens objectAtIndex:2]];
// }
// break;
// case 3:
// if([screens count] >= 4){
// [outWindow constrainFrameRect:outWindowFrame toScreen:(NSScreen*)[screens objectAtIndex:3]];
// }
// break;
// default:
// break;
//
// }//
// create renderer and attach to window
NSRect cocoaRendererFrame = NSMakeRect(10, 10, width, height);
cocoaRenderer = [[CocoaRenderer alloc] initWithFrame:cocoaRendererFrame];
[[outWindow contentView] addSubview:cocoaRenderer];
// must tell Cocoa to draw the window, but any GUI work must be done on the main thread.
[outWindow performSelector:@selector(display) onThread:[NSThread mainThread] withObject:nil waitUntilDone:YES];
[outWindow makeKeyAndOrderFront:NSApp];
[pool release];
return 0;
}
void SetWindowPos(CocoaRenderer*& cocoaRenderer, int x, int y, int width, int height, bool onTop)
{
NSWindow* ownerWindow = [cocoaRenderer window];
NSRect ownerNewRect = NSMakeRect(x, y, width, height);
[ownerWindow setFrame:ownerNewRect display:YES];
//NSRect cocoaRendererNewRect = {0, 0, 500, 500};
//NSArray* screens = [NSScreen screens];
//NSScreen* screen = (NSScreen*)[screens objectAtIndex:_screen];
//cocoaRendererNewRect = [cocoaRenderer constrainFrameRect:cocoaRendererNewRect toScreen:screen];
//[cocoaRenderer setFrame:cocoaRendererNewRect];
//[cocoaRenderer performSelector:@selector(display) onThread:[NSThread mainThread] withObject:nil waitUntilDone:YES];
//[cocoaRenderer performSelector:@selector(drawRect) onThread:[NSThread mainThread] withObject:cocoaRendererNewRect waitUntilDone:YES];
// *** Setting onTop is toooo on top. Can't get to anything underneath.
// [ownerWindow setLevel:NSNormalWindowLevel];
// if(YES == onTop){
// [ownerWindow setLevel:NSScreenSaverWindowLevel];
// }
// else{
// [ownerWindow setLevel:NSNormalWindowLevel];
// }
}
#elif defined(ANDROID)
#define nil NULL
#define NO false
jobject Renderer::g_renderWindow=NULL;
int WebRtcCreateWindow(jobject &renderWin,int /*winNum*/, int /*width*/, int /*height*/)
{
renderWin=Renderer::g_renderWindow;
return 0;
}
void SetWindowPos(void *& /*hwndMain*/, int /*x*/, int /*y*/, int /*width*/, int /*height*/, bool /*onTop*/)
{
}
void Renderer::SetRenderWindow(jobject renderWindow)
{
__android_log_print(ANDROID_LOG_DEBUG, "VideoCaptureModule -testAPI", "Renderer::SetRenderWindow");
g_renderWindow=renderWindow;
}
#elif defined(WEBRTC_LINUX)
int WebRtcCreateWindow(HWND &hwndMain,int winNum, int width, int height)
{
}
void SetWindowPos(HWND &hwndMain, int x, int y, int width, int height, bool onTop)
{
}
#endif
Renderer::Renderer(bool preview) :
_renderModule(NULL), _quiting(false), _renderWindow(NULL)
{
#ifndef _WIN32
if (-1 == WebRtcCreateWindow(_renderWindow, 0, 352, 288))
{
printf("ERROR** INVALID SCREEN\n");
}
#endif // In Windows the thread running the message loop needs to create the window.
_messageThread = ThreadWrapper::CreateThread(RenderThread, this,
kLowPriority, "RenderThread");
unsigned int threadId;
_messageThread->Start(threadId);
while (!_renderWindow)
{
SLEEP(10);
}// Wait until messageThread has created the window
_renderModule = VideoRender::CreateVideoRender(0, (void*) _renderWindow,
false);
#if defined(WEBRTC_MAC_INTEL)
_pool = [[NSAutoreleasePool alloc] init];
#endif
_renderProvider = _renderModule->AddIncomingRenderStream(0, 0, 0.0f, 0.0f,
1.0f, 1.0f);
WebRtc_UWord32 width;
WebRtc_UWord32 height;
_renderModule->GetScreenResolution(width, height);
#ifdef _WIN32
// GetScreenResolution is currently not implemented
RECT screenRect;
GetWindowRect(GetDesktopWindow(), &screenRect);
width=screenRect.right;
height=screenRect.bottom;
#endif
if (!preview)
{
#if defined(_WIN32)
SetWindowPos(_renderWindow,0,height/2,width,height/2,true);
#elif defined(WEBRTC_MAC_INTEL)
SetWindowPos(_renderWindow, 0, height, width, height, true);
#elif defined(WEBRTC_LINUX)
#endif
_videoFrame.VerifyAndAllocate(_frameWidth * _frameHeight * 3 / 2);
_videoFrame.SetHeight(_frameHeight);
_videoFrame.SetWidth(_frameWidth);
_videoFrame.SetLength(_videoFrame.Size());
memset(_videoFrame.Buffer(), 0, _videoFrame.Size());
}
else // Preview window
{
#if defined(_WIN32)
SetWindowPos(_renderWindow,width/2,0,width/2,height/2,false);
#elif defined(WEBRTC_MAC_INTEL)
SetWindowPos(_renderWindow, 0, height, width, height, false);
#elif defined(WEBRTC_LINUX)
#endif
}
_renderModule->StartRender(0);
}
Renderer::~Renderer(void)
{
VideoRender::DestroyVideoRender(_renderModule);
_quiting = true;
while (_renderWindow)
{
SLEEP(20);
}
_messageThread->Stop();
#if defined(WEBRTC_MAC_INTEL)
[_pool release];
#endif
delete _messageThread;
}
bool Renderer::RenderThread(ThreadObj obj)
{
return static_cast<Renderer*> (obj)->RenderThreadProcess();
}
bool Renderer::RenderThreadProcess()
{
if (_quiting == false && _renderWindow == NULL) // Create the render window
{
WebRtcCreateWindow(_renderWindow, 0, 352, 288);
}
#ifdef _WIN32
MSG msg;
if(PeekMessage(&msg, NULL, 0, 0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
#endif
if (_quiting == true)
{
#if defined _WIN32
::DestroyWindow(_renderWindow);
#endif
_renderWindow = NULL;
}
SLEEP(50);
return true;
}
void Renderer::PaintGreen()
{
_videoFrame.VerifyAndAllocate(_frameWidth * _frameHeight * 3 / 2);
_videoFrame.SetHeight(_frameHeight);
_videoFrame.SetWidth(_frameWidth);
_videoFrame.SetLength(_videoFrame.Size());
memset(_videoFrame.Buffer(), 127, _videoFrame.Size());
memset(_videoFrame.Buffer() + _videoFrame.Width() * _videoFrame.Height(),
0, _videoFrame.Width() * _videoFrame.Height() / 2);
_videoFrame.SetRenderTime(TickTime::MillisecondTimestamp());
_renderProvider->RenderFrame(0,_videoFrame);
}
void Renderer::RenderFrame(VideoFrame& videoFrame)
{
_renderProvider->RenderFrame(0, videoFrame);
}
void Renderer::PaintBlue()
{
_videoFrame.VerifyAndAllocate(_frameWidth * _frameHeight * 3 / 2);
_videoFrame.SetHeight(_frameHeight);
_videoFrame.SetWidth(_frameWidth);
_videoFrame.SetLength(_videoFrame.Size());
memset(_videoFrame.Buffer(), 127, _videoFrame.Size());
memset(_videoFrame.Buffer() + _videoFrame.Width() * _videoFrame.Height(),
255, _videoFrame.Width() * _videoFrame.Height() / 2);
_videoFrame.SetRenderTime(TickTime::MillisecondTimestamp());
_renderProvider->RenderFrame(0, _videoFrame);
}
void* Renderer::GetWindow()
{
return (void*) _renderWindow;
}
} // namespace webrtc