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
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Contributor(s): ______________________________________.
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
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
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
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
104 #pragma implementation "vsdl.h"
107 #define P_FORCE_STATIC_PLUGIN
110 #include <ptlib/vconvert.h>
111 #include <ptlib/pluginmgr.h>
112 #include <ptclib/vsdl.h>
120 #if defined(P_FREEBSD)
121 #include <SDL11/SDL.h>
129 #pragma comment(lib, P_SDL_LIBRARY)
133 class PVideoOutputDevice_SDL_PluginServiceDescriptor
: public PDevicePluginServiceDescriptor
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";
151 updateOverlay
= false;
157 PVideoOutputDevice_SDL::~PVideoOutputDevice_SDL()
163 PStringList
PVideoOutputDevice_SDL::GetDeviceNames() const
165 return PStringList("SDL");
169 BOOL
PVideoOutputDevice_SDL::Open(const PString
& name
, BOOL
/*startImmediate*/)
175 sdlThread
= PThread::Create(PCREATE_NOTIFIER(SDLThreadMain
), 0,
176 PThread::NoAutoDeleteThread
,
177 PThread::LowPriority
,
182 return screen
!= NULL
;
186 BOOL
PVideoOutputDevice_SDL::IsOpen()
188 return screen
!= NULL
&& overlay
!= NULL
;
192 BOOL
PVideoOutputDevice_SDL::Close()
196 sdlThread
->WaitForTermination(1000);
204 BOOL
PVideoOutputDevice_SDL::SetColourFormat(const PString
& colourFormat
)
206 if (colourFormat
*= "YUV420P")
207 return PVideoOutputDevice::SetColourFormat(colourFormat
);
213 BOOL
PVideoOutputDevice_SDL::SetFrameSize(unsigned width
, unsigned height
)
216 PWaitAndSignal
m(mutex
);
218 if (width
== frameWidth
&& height
== frameHeight
)
221 if (!PVideoOutputDevice::SetFrameSize(width
, height
))
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
,
242 PWaitAndSignal
m(mutex
);
247 if (x
!= 0 || y
!= 0 || width
!= frameWidth
|| height
!= frameHeight
|| !endFrame
)
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
));
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;
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());
285 SDL_SetModuleHandle(GetModuleHandle(NULL
));
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());
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());
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");
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");
318 case SDL_VIDEORESIZE
:
319 PTRACE(4, "VSDL\t Resize window to " << event
.resize
.w
<< " x " << event
.resize
.h
);
322 // Sleep for 25 milliseconds
329 void PVideoOutputDevice_SDL::SDLThreadMain(PThread
&, INT
)
335 PTRACE(4, "VSDL\tMain loop is underway, with SDL screen initialised");
337 while (ProcessSDLEvents()) {
341 PWaitAndSignal
m(mutex
);
343 if (adjustSize
.Wait(0)) {
344 ::SDL_FreeYUVOverlay(overlay
);
347 screen
= ::SDL_SetVideoMode(frameWidth
, frameHeight
, 0, SDL_SWSURFACE
/* | SDL_RESIZABLE */);
349 overlay
= ::SDL_CreateYUVOverlay(frameWidth
, frameHeight
, SDL_IYUV_OVERLAY
, screen
);
351 adjustSize
.Acknowledge();
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
);
370 if (screen
!= NULL
) {
371 ::SDL_FreeSurface(screen
);
377 sdlStop
.Acknowledge();
379 PTRACE(4, "VSDL\tEnd of sdl display loop");
386 // End of file ////////////////////////////////////////////////////////////////