Fixed DevStudio 2003 build with memory check code.
[pwlib.git] / src / ptclib / vsdl.cxx
blobe275a12727bf0c41060693f27660c121304b5450
1 /*
2 * vsdl.cxx
4 * Classes to support video output via SDL
6 * Portable Windows Library
8 * Copyright (c) 1993-2000 Equivalence Pty. Ltd.
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
18 * under the License.
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Contributor(s): ______________________________________.
26 * $Log$
27 * Revision 1.18 2007/04/04 01:51:38 rjongbloed
28 * Reviewed and adjusted PTRACE log levels
29 * Now follows 1=error,2=warn,3=info,4+=debug
31 * Revision 1.17 2007/04/02 05:29:54 rjongbloed
32 * Tidied some trace logs to assure all have a category (bit before a tab character) set.
34 * Revision 1.16 2006/06/21 04:20:07 csoutheren
35 * Fixes for VS.net
37 * Revision 1.15 2006/06/09 04:43:04 dereksmithies
38 * Add patch from Ben Lear to reduce the cpu consumption. Previously, the SDL
39 * display thread was using 100% of the CPU time. Many thanks.
41 * Revision 1.14 2005/08/09 09:08:11 rjongbloed
42 * Merged new video code from branch back to the trunk.
44 * Revision 1.13.12.4 2005/08/04 08:21:58 dsandras
45 * Added static plugin flag.
47 * Revision 1.13.12.3 2005/07/26 17:07:03 dsandras
48 * Fix to make gcc happy.
50 * Revision 1.13.12.2 2005/07/17 12:58:15 rjongbloed
51 * Sorted out the ordering or Red. Blue, Cr and Cb in RGB/BGR/YUV420 formats
53 * Revision 1.13.12.1 2005/07/17 09:27:07 rjongbloed
54 * Major revisions of the PWLib video subsystem including:
55 * removal of F suffix on colour formats for vertical flipping, all done with existing bool
56 * working through use of RGB and BGR formats so now consistent
57 * cleaning up the plug in system to use virtuals instead of pointers to functions.
58 * rewrite of SDL to be a plug in compatible video output device.
59 * extensive enhancement of video test program
61 * Revision 1.13 2004/04/09 06:52:17 rjongbloed
62 * Removed #pargma linker command for /delayload of DLL as documentations sais that
63 * you cannot do this.
65 * Revision 1.12 2004/02/23 23:52:20 csoutheren
66 * Added pragmas to avoid every Windows application needing to include libs explicitly
68 * Revision 1.11 2003/12/12 05:11:56 rogerhardiman
69 * Add SDL support on FreeBSD. Header files live in SDL11 directory
71 * Revision 1.10 2003/11/06 09:13:20 rjongbloed
72 * Improved the Windows configure system to allow multiple defines based on file existence. Needed for SDL support of two different distros.
74 * Revision 1.9 2003/07/22 22:55:20 dereksmithies
75 * Add memory allocation feature.
77 * Revision 1.8 2003/05/21 03:59:10 dereksmithies
78 * Fix close down bug.
80 * Revision 1.7 2003/05/17 03:21:26 rjongbloed
81 * Removed need to do strange things with main() function.
83 * Revision 1.6 2003/05/14 02:34:53 dereksmithies
84 * Make SDL display work if only one of two display areas in use.
86 * Revision 1.5 2003/05/07 02:40:58 dereks
87 * Fix to allow it to exit when the ::Terminate method called.
89 * Revision 1.4 2003/04/28 14:30:02 craigs
90 * Started rearranging code
92 * Revision 1.3 2003/04/28 08:33:00 craigs
93 * Linux SDL includes are in a SDL directory, but Windows is not
95 * Revision 1.2 2003/04/28 07:27:15 craigs
96 * Added missed functions
98 * Revision 1.1 2003/04/28 07:03:55 craigs
99 * Initial version from ohphone
103 #ifdef __GNUC__
104 #pragma implementation "vsdl.h"
105 #endif
107 #define P_FORCE_STATIC_PLUGIN
109 #include <ptlib.h>
110 #include <ptlib/vconvert.h>
111 #include <ptlib/pluginmgr.h>
112 #include <ptclib/vsdl.h>
114 #define new PNEW
116 #if P_SDL
118 extern "C" {
120 #if defined(P_FREEBSD)
121 #include <SDL11/SDL.h>
122 #else
123 #include <SDL/SDL.h>
124 #endif
128 #ifdef _MSC_VER
129 #pragma comment(lib, P_SDL_LIBRARY)
130 #endif
133 class PVideoOutputDevice_SDL_PluginServiceDescriptor : public PDevicePluginServiceDescriptor
135 public:
136 virtual PObject * CreateInstance(int /*userData*/) const { return new PVideoOutputDevice_SDL; }
137 virtual PStringList GetDeviceNames(int /*userData*/) const { return PStringList("SDL"); }
138 virtual bool ValidateDeviceName(const PString & deviceName, int /*userData*/) const { return deviceName.Find("SDL") == 0; }
139 } PVideoOutputDevice_SDL_descriptor;
141 PCREATE_PLUGIN(SDL, PVideoOutputDevice, &PVideoOutputDevice_SDL_descriptor);
144 ///////////////////////////////////////////////////////////////////////
146 PVideoOutputDevice_SDL::PVideoOutputDevice_SDL()
148 colourFormat = "YUV420P";
150 sdlThread = NULL;
151 updateOverlay = false;
152 screen = NULL;
153 overlay = NULL;
157 PVideoOutputDevice_SDL::~PVideoOutputDevice_SDL()
159 Close();
163 PStringList PVideoOutputDevice_SDL::GetDeviceNames() const
165 return PStringList("SDL");
169 BOOL PVideoOutputDevice_SDL::Open(const PString & name, BOOL /*startImmediate*/)
171 Close();
173 deviceName = name;
175 sdlThread = PThread::Create(PCREATE_NOTIFIER(SDLThreadMain), 0,
176 PThread::NoAutoDeleteThread,
177 PThread::LowPriority,
178 "SDL:%x");
180 sdlStarted.Wait();
182 return screen != NULL;
186 BOOL PVideoOutputDevice_SDL::IsOpen()
188 return screen != NULL && overlay != NULL;
192 BOOL PVideoOutputDevice_SDL::Close()
194 if (IsOpen()) {
195 sdlStop.Signal();
196 sdlThread->WaitForTermination(1000);
197 delete sdlThread;
200 return TRUE;
204 BOOL PVideoOutputDevice_SDL::SetColourFormat(const PString & colourFormat)
206 if (colourFormat *= "YUV420P")
207 return PVideoOutputDevice::SetColourFormat(colourFormat);
209 return FALSE;
213 BOOL PVideoOutputDevice_SDL::SetFrameSize(unsigned width, unsigned height)
216 PWaitAndSignal m(mutex);
218 if (width == frameWidth && height == frameHeight)
219 return TRUE;
221 if (!PVideoOutputDevice::SetFrameSize(width, height))
222 return FALSE;
225 adjustSize.Signal();
226 return IsOpen();
230 PINDEX PVideoOutputDevice_SDL::GetMaxFrameBytes()
232 PWaitAndSignal m(mutex);
233 return GetMaxFrameBytesConverted(CalculateFrameBytes(frameWidth, frameHeight, colourFormat));
237 BOOL PVideoOutputDevice_SDL::SetFrameData(unsigned x, unsigned y,
238 unsigned width, unsigned height,
239 const BYTE * data,
240 BOOL endFrame)
242 PWaitAndSignal m(mutex);
244 if (!IsOpen())
245 return FALSE;
247 if (x != 0 || y != 0 || width != frameWidth || height != frameHeight || !endFrame)
248 return FALSE;
250 ::SDL_LockYUVOverlay(overlay);
252 PAssert(frameWidth == (unsigned)overlay->w && frameHeight == (unsigned)overlay->h, PLogicError);
253 PINDEX pixelsFrame = frameWidth * frameHeight;
254 PINDEX pixelsQuartFrame = pixelsFrame >> 2;
256 const BYTE * dataPtr = data;
258 PBYTEArray tempStore;
259 if (converter != NULL) {
260 converter->Convert(data, tempStore.GetPointer(pixelsFrame+2*pixelsQuartFrame));
261 dataPtr = tempStore;
264 memcpy(overlay->pixels[0], dataPtr, pixelsFrame);
265 memcpy(overlay->pixels[1], dataPtr + pixelsFrame, pixelsQuartFrame);
266 memcpy(overlay->pixels[2], dataPtr + pixelsFrame + pixelsQuartFrame, pixelsQuartFrame);
268 ::SDL_UnlockYUVOverlay(overlay);
270 updateOverlay = true;
272 return TRUE;
276 bool PVideoOutputDevice_SDL::InitialiseSDL()
278 // initialise the SDL library
279 if (::SDL_Init(SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE) < 0 ) {
280 PTRACE(1, "VSDL\tCouldn't initialize SDL: " << ::SDL_GetError());
281 return false;
284 #ifdef _WIN32
285 SDL_SetModuleHandle(GetModuleHandle(NULL));
286 #endif
288 screen = ::SDL_SetVideoMode(frameWidth, frameHeight, 0, SDL_SWSURFACE /* | SDL_RESIZABLE */);
289 if (screen == NULL) {
290 PTRACE(1, "VSDL\tCouldn't create SDL screen: " << ::SDL_GetError());
291 return false;
294 overlay = ::SDL_CreateYUVOverlay(frameWidth, frameHeight, SDL_IYUV_OVERLAY, screen);
295 if (overlay == NULL) {
296 PTRACE(1, "VSDL\tCouldn't create SDL overlay: " << ::SDL_GetError());
297 return false;
300 return true;
304 bool PVideoOutputDevice_SDL::ProcessSDLEvents()
306 if (screen == NULL || overlay == NULL) {
307 PTRACE(6, "VSDL\t Screen and/or overlay not open, so dont process events");
308 return false;
311 SDL_Event event;
312 while (::SDL_PollEvent(&event)) {
313 switch (event.type) {
314 case SDL_QUIT : //User selected cross
315 PTRACE(3, "VSDL\t user selected cross on window, close window");
316 return false;
318 case SDL_VIDEORESIZE :
319 PTRACE(4, "VSDL\t Resize window to " << event.resize.w << " x " << event.resize.h);
322 // Sleep for 25 milliseconds
323 SDL_Delay(25);
325 return true;
329 void PVideoOutputDevice_SDL::SDLThreadMain(PThread &, INT)
331 InitialiseSDL();
333 sdlStarted.Signal();
335 PTRACE(4, "VSDL\tMain loop is underway, with SDL screen initialised");
337 while (ProcessSDLEvents()) {
338 if (sdlStop.Wait(0))
339 break;
341 PWaitAndSignal m(mutex);
343 if (adjustSize.Wait(0)) {
344 ::SDL_FreeYUVOverlay(overlay);
345 overlay = NULL;
347 screen = ::SDL_SetVideoMode(frameWidth, frameHeight, 0, SDL_SWSURFACE /* | SDL_RESIZABLE */);
348 if (screen != NULL)
349 overlay = ::SDL_CreateYUVOverlay(frameWidth, frameHeight, SDL_IYUV_OVERLAY, screen);
351 adjustSize.Acknowledge();
354 if (updateOverlay) {
355 SDL_Rect rect;
356 rect.x = 0;
357 rect.y = 0;
358 rect.w = (Uint16)frameWidth;
359 rect.h = (Uint16)frameHeight;
360 ::SDL_DisplayYUVOverlay(overlay, &rect);
361 updateOverlay = true;
365 if (overlay != NULL) {
366 ::SDL_FreeYUVOverlay(overlay);
367 overlay = NULL;
370 if (screen != NULL) {
371 ::SDL_FreeSurface(screen);
372 screen = NULL;
375 ::SDL_Quit();
377 sdlStop.Acknowledge();
379 PTRACE(4, "VSDL\tEnd of sdl display loop");
383 #endif // P_SDL
386 // End of file ////////////////////////////////////////////////////////////////