Uncommented beaudio code
[pwlib.git] / src / ptlib / unix / video4bsd.cxx
blob10ff4a2531016e03feaee2a1a3aa0cfbab7b9927
1 /*
2 * video4bsd.cxx
4 * Classes to support streaming video input (grabbing) and output.
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): Roger Hardiman <roger@freebsd.org>
26 * $Log$
27 * Revision 1.21 2004/01/02 23:30:18 rjongbloed
28 * Removed extraneous static function for getting input device names that has been deprecated during the plug ins addition.
30 * Revision 1.20 2002/10/28 19:12:45 rogerh
31 * Add svideo input support for Lars Eggert <larse@isi.edu>
33 * Revision 1.19 2002/04/10 08:40:36 rogerh
34 * Simplify the SetVideoChannelFormat() code. Use the implementation in the
35 * ancestor class.
37 * Revision 1.18 2002/04/05 06:41:54 rogerh
38 * Apply video changes from Damien Sandras <dsandras@seconix.com>.
39 * The Video Channel and Format are no longer set in Open(). Instead
40 * call the new SetVideoChannelFormat() method. This makes video capture
41 * and GnomeMeeting more stable with certain Linux video capture devices.
43 * Revision 1.17 2002/01/08 17:16:13 rogerh
44 * Add code to grab Even fields (instead of interlaced frames) whenever
45 * possible. This improves the image quality.
46 * Add TestAllFormats
48 * Revision 1.16 2001/12/05 14:45:20 rogerh
49 * Implement GetFrameData and GetFrameDataNoDelay
51 * Revision 1.15 2001/12/05 14:32:48 rogerh
52 * Add GetParemters function
54 * Revision 1.14 2001/08/06 06:56:16 rogerh
55 * Add scaling for new methods to match BSD's Meteor API
57 * Revision 1.13 2001/08/06 06:19:33 rogerh
58 * Implement Brightness, Contract and Hue methods.
60 * Revision 1.12 2001/03/26 16:02:01 rogerh
61 * Add dummy function for VerifyHardwareFrameSize
63 * Revision 1.11 2001/03/08 03:59:13 robertj
64 * Fixed previous change, needed to allow for -1 as chammelNumber in Open().
66 * Revision 1.10 2001/03/08 02:23:17 robertj
67 * Added improved defaulting of video formats so Open() does not fail.
69 * Revision 1.9 2001/03/07 00:10:05 robertj
70 * Improved the device list, uses /proc, thanks Thorsten Westheider.
72 * Revision 1.8 2001/03/03 23:29:00 robertj
73 * Oops, fixed BSD version of video.
75 * Revision 1.7 2001/03/03 23:25:07 robertj
76 * Fixed use of video conversion function, returning bytes in destination frame.
78 * Revision 1.6 2001/03/03 06:13:01 robertj
79 * Major upgrade of video conversion and grabbing classes.
81 * Revision 1.5 2001/01/11 13:26:39 rogerh
82 * Add me in the Contributors section
84 * Revision 1.4 2001/01/05 18:12:30 rogerh
85 * First fully working version of video4bsd.
86 * Note that Start() and Stop() are not called, hence the first time hacks
87 * in GetFrameData(). Also video is always grabbed in interlaced mode
88 * so it does not look as good as it could.
90 * Revision 1.3 2001/01/05 14:52:36 rogerh
91 * More work on the FreeBSD video capture code
93 * Revision 1.2 2001/01/04 18:02:16 rogerh
94 * remove some old parts refering to linux
96 * Revision 1.1 2001/01/04 18:00:43 rogerh
97 * Start to add support for video capture using on FreeBSD/NetBSD and OpenBSD
98 * using the Meteor API (used by the Matrox Meteor and the bktr driver for
99 * Bt848/Bt878 TV Tuner Cards). This is incomplete but it does compile.
102 #pragma implementation "videoio.h"
104 #include <ptlib.h>
105 #include <ptlib/videoio.h>
106 #include <ptlib/vfakeio.h>
107 #include <ptlib/vconvert.h>
109 #include <sys/mman.h>
112 ///////////////////////////////////////////////////////////////////////////////
113 // PVideoInputDevice
115 PVideoInputDevice::PVideoInputDevice()
117 videoFd = -1;
118 canMap = -1;
122 BOOL PVideoInputDevice::Open(const PString & devName, BOOL startImmediate)
124 Close();
126 deviceName = devName;
127 videoFd = ::open((const char *)devName, O_RDONLY);
128 if (videoFd < 0) {
129 videoFd = -1;
130 return FALSE;
133 // fill in a device capabilities structure
134 videoCapability.minheight = 32;
135 videoCapability.minwidth = 32;
136 videoCapability.maxheight = 768;
137 videoCapability.maxwidth = 576;
138 videoCapability.channels = 5;
140 // set height and width
141 frameHeight = videoCapability.maxheight;
142 frameWidth = videoCapability.maxwidth;
144 // select the specified input
145 if (!SetChannel(channelNumber)) {
146 ::close (videoFd);
147 videoFd = -1;
148 return FALSE;
151 // select the video format (eg PAL, NTSC)
152 if (!SetVideoFormat(videoFormat)) {
153 ::close (videoFd);
154 videoFd = -1;
155 return FALSE;
158 // select the colpur format (eg YUV420, or RGB)
159 if (!SetColourFormat(colourFormat)) {
160 ::close (videoFd);
161 videoFd = -1;
162 return FALSE;
165 // select the image size
166 if (!SetFrameSize(frameWidth, frameHeight)) {
167 ::close (videoFd);
168 videoFd = -1;
169 return FALSE;
172 return TRUE;
176 BOOL PVideoInputDevice::IsOpen()
178 return videoFd >= 0;
182 BOOL PVideoInputDevice::Close()
184 if (!IsOpen())
185 return FALSE;
187 ClearMapping();
188 ::close(videoFd);
189 videoFd = -1;
190 canMap = -1;
192 return TRUE;
195 BOOL PVideoInputDevice::Start()
197 return TRUE;
201 BOOL PVideoInputDevice::Stop()
203 return TRUE;
207 BOOL PVideoInputDevice::IsCapturing()
209 return IsOpen();
213 BOOL PVideoInputDevice::SetVideoFormat(VideoFormat newFormat)
215 if (!PVideoDevice::SetVideoFormat(newFormat))
216 return FALSE;
218 // set channel information
219 static int fmt[4] = { METEOR_FMT_PAL, METEOR_FMT_NTSC,
220 METEOR_FMT_SECAM, METEOR_FMT_AUTOMODE };
221 int format = fmt[newFormat];
223 // set the information
224 if (::ioctl(videoFd, METEORSFMT, &format) >= 0)
225 return TRUE;
227 // setting the format failed. Fall back trying other standard formats
229 if (newFormat != Auto)
230 return FALSE;
232 if (SetVideoFormat(PAL))
233 return TRUE;
234 if (SetVideoFormat(NTSC))
235 return TRUE;
236 if (SetVideoFormat(SECAM))
237 return TRUE;
239 return FALSE;
243 int PVideoInputDevice::GetNumChannels()
245 return videoCapability.channels;
249 BOOL PVideoInputDevice::SetChannel(int newChannel)
251 if (!PVideoDevice::SetChannel(newChannel))
252 return FALSE;
254 // set channel information
255 static int chnl[5] = { METEOR_INPUT_DEV0, METEOR_INPUT_DEV1,
256 METEOR_INPUT_DEV2, METEOR_INPUT_DEV3,
257 METEOR_INPUT_DEV_SVIDEO };
258 int channel = chnl[newChannel];
260 // set the information
261 if (::ioctl(videoFd, METEORSINPUT, &channel) < 0)
262 return FALSE;
264 return TRUE;
268 BOOL PVideoInputDevice::SetColourFormat(const PString & newFormat)
270 if (!PVideoDevice::SetColourFormat(newFormat))
271 return FALSE;
273 ClearMapping();
275 frameBytes = CalculateFrameBytes(frameWidth, frameHeight, colourFormat);
277 return TRUE;
282 BOOL PVideoInputDevice::SetFrameRate(unsigned rate)
284 if (!PVideoDevice::SetFrameRate(rate))
285 return FALSE;
287 return TRUE;
291 BOOL PVideoInputDevice::GetFrameSizeLimits(unsigned & minWidth,
292 unsigned & minHeight,
293 unsigned & maxWidth,
294 unsigned & maxHeight)
296 if (!IsOpen())
297 return FALSE;
299 minWidth = videoCapability.minwidth;
300 minHeight = videoCapability.minheight;
301 maxWidth = videoCapability.maxwidth;
302 maxHeight = videoCapability.maxheight;
303 return TRUE;
308 BOOL PVideoInputDevice::SetFrameSize(unsigned width, unsigned height)
310 if (!PVideoDevice::SetFrameSize(width, height))
311 return FALSE;
313 ClearMapping();
315 frameBytes = CalculateFrameBytes(frameWidth, frameHeight, colourFormat);
317 return TRUE;
321 PINDEX PVideoInputDevice::GetMaxFrameBytes()
323 return frameBytes;
327 BOOL PVideoInputDevice::GetFrameData(BYTE * buffer, PINDEX * bytesReturned)
329 if(frameRate>0) {
330 frameTimeError += msBetweenFrames;
332 do {
333 if ( !GetFrameDataNoDelay(buffer, bytesReturned))
334 return FALSE;
335 PTime now;
336 PTimeInterval delay = now - previousFrameTime;
337 frameTimeError -= (int)delay.GetMilliSeconds();
338 previousFrameTime = now;
339 } while(frameTimeError > 0) ;
341 return TRUE;
343 return GetFrameDataNoDelay(buffer,bytesReturned);
347 BOOL PVideoInputDevice::GetFrameDataNoDelay(BYTE * buffer, PINDEX * bytesReturned)
350 // Hack time. It seems that the Start() and Stop() functions are not
351 // actually called, so we will have to initialise the frame grabber
352 // here on the first pass through this GetFrameData() function
354 if (canMap < 0) {
356 struct meteor_geomet geo;
357 geo.rows = frameHeight;
358 geo.columns = frameWidth;
359 geo.frames = 1;
360 geo.oformat = METEOR_GEO_YUV_422 | METEOR_GEO_YUV_12;
362 // Grab even field (instead of interlaced frames) where possible to stop
363 // jagged interlacing artifacts. NTSC is 640x480, PAL/SECAM is 768x576.
364 if ( ((PVideoDevice::GetVideoFormat() == PAL) && (frameHeight <= 288))
365 || ((PVideoDevice::GetVideoFormat() == SECAM) && (frameHeight <= 288))
366 || ((PVideoDevice::GetVideoFormat() == NTSC) && (frameHeight <= 240)) ){
367 geo.oformat |= METEOR_GEO_EVEN_ONLY;
370 // set the new geometry
371 if (ioctl(videoFd, METEORSETGEO, &geo) < 0) {
372 return FALSE;
375 mmap_size = frameBytes;
376 videoBuffer = (BYTE *)::mmap(0, mmap_size, PROT_READ, 0, videoFd, 0);
377 if (videoBuffer < 0) {
378 return FALSE;
379 } else {
380 canMap = 1;
383 // put the grabber into continuous capture mode
384 int mode = METEOR_CAP_CONTINOUS;
385 if (ioctl(videoFd, METEORCAPTUR, &mode) < 0 ) {
386 return FALSE;
391 // Copy a snapshot of the image from the mmap buffer
392 // Really there should be some synchronisation here to avoid tearing
393 // in the image, but we will worry about that later
395 if (converter != NULL)
396 return converter->Convert(videoBuffer, buffer, bytesReturned);
398 memcpy(buffer, videoBuffer, frameBytes);
400 if (bytesReturned != NULL)
401 *bytesReturned = frameBytes;
404 return TRUE;
408 void PVideoInputDevice::ClearMapping()
410 if (canMap == 1) {
412 // better stop grabbing first
413 // Really this should be in the Stop() function, but that is
414 // not actually called anywhere.
416 int mode = METEOR_CAP_STOP_CONT;
417 ioctl(videoFd, METEORCAPTUR, &mode);
419 if (videoBuffer != NULL)
420 ::munmap(videoBuffer, mmap_size);
422 canMap = -1;
423 videoBuffer = NULL;
427 BOOL PVideoInputDevice::VerifyHardwareFrameSize(unsigned width,
428 unsigned height)
430 // Assume the size is valid
431 return TRUE;
435 int PVideoInputDevice::GetBrightness()
437 if (!IsOpen())
438 return -1;
440 unsigned char data;
441 if (::ioctl(videoFd, METEORGBRIG, &data) < 0)
442 return -1;
443 frameBrightness = (data << 8);
445 return frameBrightness;
448 int PVideoInputDevice::GetContrast()
450 if (!IsOpen())
451 return -1;
453 unsigned char data;
454 if (::ioctl(videoFd, METEORGCONT, &data) < 0)
455 return -1;
456 frameContrast = (data << 8);
458 return frameContrast;
461 int PVideoInputDevice::GetHue()
463 if (!IsOpen())
464 return -1;
466 char data;
467 if (::ioctl(videoFd, METEORGHUE, &data) < 0)
468 return -1;
469 frameHue = ((data + 128) << 8);
471 return frameHue;
474 BOOL PVideoInputDevice::SetBrightness(unsigned newBrightness)
476 if (!IsOpen())
477 return FALSE;
479 unsigned char data = (newBrightness >> 8); // rescale for the ioctl
480 if (::ioctl(videoFd, METEORSBRIG, &data) < 0)
481 return FALSE;
483 frameBrightness=newBrightness;
484 return TRUE;
487 BOOL PVideoInputDevice::SetContrast(unsigned newContrast)
489 if (!IsOpen())
490 return FALSE;
492 unsigned char data = (newContrast >> 8); // rescale for the ioctl
493 if (::ioctl(videoFd, METEORSCONT, &data) < 0)
494 return FALSE;
496 frameContrast = newContrast;
497 return TRUE;
500 BOOL PVideoInputDevice::SetHue(unsigned newHue)
502 if (!IsOpen())
503 return FALSE;
505 char data = (newHue >> 8) - 128; // ioctl takes a signed char
506 if (::ioctl(videoFd, METEORSHUE, &data) < 0)
507 return FALSE;
509 frameHue=newHue;
510 return TRUE;
513 BOOL PVideoInputDevice::GetParameters (int *whiteness, int *brightness,
514 int *colour, int *contrast, int *hue)
516 if (!IsOpen())
517 return FALSE;
519 unsigned char data;
520 char signed_data;
522 if (::ioctl(videoFd, METEORGBRIG, &data) < 0)
523 return -1;
524 *brightness = (data << 8);
526 if (::ioctl(videoFd, METEORGCONT, &data) < 0)
527 return -1;
528 *contrast = (data << 8);
530 if (::ioctl(videoFd, METEORGHUE, &signed_data) < 0)
531 return -1;
532 *hue = ((data + 128) << 8);
534 // The bktr driver does not have colour or whiteness ioctls
535 // so set them to the current global values
536 *colour = frameColour;
537 *whiteness = frameWhiteness;
539 // update the global settings
540 frameBrightness = *brightness;
541 frameContrast = *contrast;
542 frameHue = *hue;
544 return TRUE;
547 BOOL PVideoInputDevice::TestAllFormats()
549 return TRUE;
551 // End Of File ///////////////////////////////////////////////////////////////