Uncommented beaudio code
[pwlib.git] / src / ptlib / unix / video4dc1394.cxx
blob60af1aef16f979b7a0dd2c661f2cd000a7e82291
1 /*
2 * README for IEEE 1394 digital camera support routine in PWLib
3 * ------------------------------------------------------------
4 *
5 * PWLib now contains preliminary support for the IEEE 1394 digital
6 * cameras under Linux.
7 *
8 *
9 * Supported cameras:
11 * There are two kind of the specifications of IEEE 1394 digital video
12 * cameras, one is called "digital camera" and another is "AV/C camera".
13 * A digital camera sends uncompressed video data while an AV/C camera
14 * sends compressed data. Currently PWLib only supports digital
15 * cameras. We can find a list of supported digital cameras by the Linux
16 * device driver at:
17 * http://www.tele.ucl.ac.be/PEOPLE/DOUXCHAMPS/ieee1394/cameras/
19 * AV/C cameras seem able to be used for video phone. You are welcome to
20 * write supporting codes for AV/C cameras!
23 * Installation and Use:
25 * To enable 1394 camera support, you have to define the "TRY_1394DC"
26 * shell environment variable at compilation time of PWLib, OpenH323, and
27 * ohphone. To select your 1394 camera for video input device instead of
28 * usual Video4Linux devices, specify "/dev/raw1394" or "/dev/video1394"
29 * as the filename of video input device. For example "ohphone
30 * --videoinput /dev/raw1394" should use your 1394 camera as video input.
32 * "/dev/video1394" uses faster DMA transfer for video input.
34 * If you use DEVFS, the filename for DMA transfer may be /dev/video1394/0.
36 * Requirements for Installation:
38 * You needs the following softwares to compile the 1394 camera support
39 * module in PWLib.
41 * - libdc1394 0.9.0 or later.
42 * - Linux 2.4.19 or later, which is required by the above version of
43 * libdc1394
44 * - libraw1394 0.9.0 or later
46 * You cannot compile it with older versions of libdc1394.
48 * Troubleshooting:
50 * If this module does not work for you, please verify the following
51 * items before sending email:
53 * 1) Can you view image of your camera by other programs? A sample
54 * program called "grab_gray_image" is included in the example
55 * directory of libdc1394. Please run grab_gray_image and see what
56 * happens. You can also use Coriander instead.
57 * (http://www.tele.ucl.ac.be/PEOPLE/DOUXCHAMPS/ieee1394/coriander/).
58 * 2) If you have make sure other programs can use the camera, but
59 * this module still does not work, please run the debbuging version
60 * of ohphone with option "-tttt -o log.txt". Examine the file "log.txt"
61 * and you may see what is wrong.
64 * Problem Reports:
65 * They should be send to Ryutaroh Matsumoto <ryutaroh@rmatsumoto.org>.
68 * Acknowledgment:
69 * R. Matsumoto thanks Dr. Derek Smithies for his kind support for making
70 * this module.
73 * Technical Notes for Programmers
74 * ------------------------------------------------------------
76 * Test Environment:
77 * This module was tested against:
79 * Pentium III
80 * Linux 2.4.19
81 * libraw1394 0.9.0
82 * libdc1394 0.9.0
84 * Irez StealthFire Camera (http://www.irez.com)
85 * OrangeMicro iBot Camera (http://www.orangemicro.com)
88 * Internal Structure:
89 * This module has been tested against the ohphone and GnomeMeeting
90 * video phone programs. They use 352x288 and 176x144 resolutions in
91 * YUV420P color format. So this module only supports these
92 * resolutions and YUV420P.
94 * 1394 Digital Cameras has many resolutions and color formats. Among
95 * them, this module uses:
96 * 160x120 YUV(4:4:4) for 176x144 PTlib resolution, and
97 * 320x240 YUV(4:2:2) for 352x288 PTlib resolution.
98 * The bus speed is always set to P_DC1394_DEFAULT_SPEED (400 Mbps).
99 * If transfer at P_DC1394_DEFAULT_SPEED is not supported by your
100 * camera, this module does not capture images from yours. In such
101 * a case please set P_DC1394_DEFAULT_SPEED to appropriate value.
103 * Conversion routines from above formats to YUV420P were added to
104 * src/ptlib/common/vconvert.cxx
106 * ToDo or Bugs:
107 * This module does not implement GetBrightness() etc. 1394 cameras
108 * can do both automatic control and manual control of brightness
109 * etc., and they are usually set to automatic
110 * control. Get/SetBrightness() etc. cannot access manual/automatic
111 * selection. So we cannot implement an interface that can fully
112 * control all of 1394 camera features. I decided not to implement
113 * controlling interface at all. Those features can be controlled by
114 * Coriander program even when ohphone or GnomeMeeting is being used.
115 * Please use Coriander.
117 * PVideoInput1394DcDevice does not allow creation of two or more instances.
119 * The bus speed is always set to P_DC1394_DEFAULT_SPEED (400 Mbps).
120 * If transfer at P_DC1394_DEFAULT_SPEED is not supported by your
121 * camera, this module does not capture images from yours. In such
122 * a case please set P_DC1394_DEFAULT_SPEED to appropriate value.
124 * Copyright:
125 * Copyright (c) 2002 Ryutaroh Matsumoto <ryutaroh@rmatsumoto.org>
127 * The contents of this file are subject to the Mozilla Public License
128 * Version 1.0 (the "License"); you may not use this file except in
129 * compliance with the License. You may obtain a copy of the License at
130 * http://www.mozilla.org/MPL/
132 * Software distributed under the License is distributed on an "AS IS"
133 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
134 * the License for the specific language governing rights and limitations
135 * under the License.
139 * $Log$
140 * Revision 1.9 2003/03/17 07:53:04 robertj
141 * Removed canCaptureVideo variable as this is really a virtual function to
142 * distinguish PVideoOutputDevice from PVideoInputDevice, it is not dynamic.
144 * Revision 1.8 2002/08/21 00:00:31 dereks
145 * Patches from Ryutaroh, to improve firewire (linux only) support. Many thanks.
147 * Revision 1.7 2002/05/30 22:49:35 dereks
148 * correct implementation of GetInputDeviceNames().
150 * Revision 1.6 2002/03/04 01:21:31 dereks
151 * Add frame rate support to Firewire camera. Thanks Ryutaroh Matsumoto.
153 * Revision 1.5 2002/02/28 19:44:03 dereks
154 * Add complete readme on Firewire usage. Thanks to Ryutaroh Matsumoto.
156 * Revision 1.4 2002/02/21 20:00:21 dereks
157 * Fix memory leak. Thanks Ryutaroh Matsumoto.
159 * Revision 1.3 2002/02/21 19:49:57 dereks
160 * Fix spelling mistake. Thanks Ryutaroh
162 * Revision 1.2 2002/02/20 20:27:28 dereks
163 * updates to previous checkin.
165 * Revision 1.1 2002/02/20 02:37:26 dereks
166 * Initial release of Firewire camera support for linux.
167 * Many thanks to Ryutaroh Matsumoto <ryutaroh@rmatsumoto.org>.
174 #pragma implementation "videoio1394dc.h"
176 #include <ptlib.h>
177 #include <ptlib/videoio.h>
178 #include <ptlib/videoio1394dc.h>
179 #include <ptlib/vconvert.h>
180 #include <ptlib/file.h>
181 #include <sys/utsname.h>
183 #ifndef P_DC1394_DEFAULT_SPEED
184 #define P_DC1394_DEFAULT_SPEED SPEED_400
185 #endif
187 //#define ESTIMATE_CAPTURE_PERFORMANCE
189 #ifdef ESTIMATE_CAPTURE_PERFORMANCE
190 // for debugging
191 static PInt64 start_time;
192 static int num_captured;
193 #endif
196 ///////////////////////////////////////////////////////////////////////////////
197 // PVideoInput1394DC
199 PVideoInput1394DcDevice::PVideoInput1394DcDevice()
201 handle = NULL;
202 is_capturing = FALSE;
203 capturing_duration = 10000; // arbitrary large value suffices
206 PVideoInput1394DcDevice::~PVideoInput1394DcDevice()
208 Close();
211 #define OK 1
212 #define NG 0
213 static int kernel_version_ok(void)
215 struct utsname utsbuf;
216 unsigned major_ver, minor_ver, minorminor_ver;
218 if (uname(&utsbuf) == -1)
219 return NG;
221 /* utsbuf.release looks like "2.4.19-pre8". */
222 if (sscanf(utsbuf.release, "%u.%u.%u", &major_ver, &minor_ver,
223 &minorminor_ver) < 3)
224 return NG; /* Should we return OK? */
226 if (major_ver >= 3)
227 return OK;
228 else if (major_ver <= 1)
229 return NG;
231 if (minor_ver >= 6)
232 return OK;
233 else if (minor_ver <= 3)
234 return NG;
235 else if (minor_ver == 4)
236 return minorminor_ver >= 19;
237 else /* if (minor_ver == 5) */
238 return minorminor_ver >= 9;
241 BOOL PVideoInput1394DcDevice::Open(const PString & devName, BOOL startImmediate)
243 if (!kernel_version_ok()) {
244 PTRACE(0, "The Linux kernel version is too old.");
245 return FALSE;
248 if (IsOpen()) {
249 PTRACE(0, "You cannot open PVideoInput1394DcDevice twice.");
250 return FALSE;
253 if (devName == "/dev/raw1394")
254 UseDMA = FALSE;
255 // Don't forget /dev/video1394/0
256 else if (strncmp(devName, "/dev/video1394", 14) == 0)
257 UseDMA = TRUE;
258 else {
259 PTRACE(0, "devName must be /dev/raw1394 or /dev/video1394");
260 return FALSE;
263 // See if devName is accessible.
264 if (!PFile::Exists(devName)) {
265 PTRACE(1, devName << " is not accessible.");
266 return FALSE;
269 /*-----------------------------------------------------------------------
270 * Open ohci and asign handle to it
271 *-----------------------------------------------------------------------*/
272 handle = dc1394_create_handle(0);
273 if (handle==NULL)
275 PTRACE(0, "Unable to aquire a raw1394 handle\n"
276 "did you insmod the drivers?\n");
277 return FALSE;
280 /*-----------------------------------------------------------------------
281 * get the camera nodes and describe them as we find them
282 *-----------------------------------------------------------------------*/
283 int numNodes = raw1394_get_nodecount(handle);
284 camera_nodes = dc1394_get_camera_nodes(handle,&numCameras,0);
285 if (numCameras<1)
287 PTRACE(0, "no cameras found :(\n");
288 dc1394_destroy_handle(handle);
289 handle = NULL;
290 return FALSE;
293 /*-----------------------------------------------------------------------
294 * to prevent the iso-transfer bug from raw1394 system, check if
295 * camera is highest node. For details see
296 * http://linux1394.sourceforge.net/faq.html#DCbusmgmt
297 * and
298 * http://sourceforge.net/tracker/index.php?func=detail&aid=435107&group_id=8157&atid=108157
299 *-----------------------------------------------------------------------*/
300 for (int i=0; i<numCameras; i++) {
301 if( camera_nodes[i] == numNodes-1) {
302 PTRACE(0,"Sorry, your camera is the highest numbered node\n"
303 "of the bus, and has therefore become the root node.\n"
304 "The root node is responsible for maintaining \n"
305 "the timing of isochronous transactions on the IEEE \n"
306 "1394 bus. However, if the root node is not cycle master \n"
307 "capable (it doesn't have to be), then isochronous \n"
308 "transactions will not work. The host controller card is \n"
309 "cycle master capable, however, most cameras are not.\n"
310 "\n"
311 "The quick solution is to add the parameter \n"
312 "attempt_root=1 when loading the OHCI driver as a \n"
313 "module. So please do (as root):\n"
314 "\n"
315 " rmmod ohci1394\n"
316 " insmod ohci1394 attempt_root=1\n"
317 "\n"
318 "for more information see the FAQ at \n"
319 "http://linux1394.sourceforge.net/faq.html#DCbusmgmt\n"
320 "\n");
321 dc1394_destroy_handle(handle);
322 handle = NULL;
323 return FALSE;
327 frameHeight = 240;
328 frameWidth = 320;
329 colourFormat = "UYVY422";
330 desiredFrameHeight = CIFHeight;
331 desiredFrameWidth = CIFWidth;
332 desiredColourFormat = "YUV420P";
333 capturing_duration = 10000; // arbitrary large value suffices
334 deviceName = devName;
336 // select the specified input and video format
337 if (!SetChannel(channelNumber) ||
338 !SetVideoFormat(videoFormat)) {
339 PTRACE(1, "SetChannel() or SetVideoFormat() failed");
340 Close();
341 return FALSE;
344 if (startImmediate && !Start()) {
345 Close();
346 return FALSE;
348 PTRACE(3, "Successfully opended\n");
349 return TRUE;
353 BOOL PVideoInput1394DcDevice::IsOpen()
355 return handle != NULL;
359 BOOL PVideoInput1394DcDevice::Close()
361 if (IsOpen()) {
362 if (IsCapturing())
363 Stop();
364 dc1394_destroy_handle(handle);
365 handle = NULL;
366 return TRUE;
367 } else
368 return FALSE;
371 BOOL PVideoInput1394DcDevice::Start()
373 int dc1394_mode;
374 if (!IsOpen()) return FALSE;
375 if (is_capturing) return TRUE;
376 if (frameWidth == 320 && frameHeight == 240)
377 dc1394_mode = MODE_320x240_YUV422;
378 else if (frameWidth == 160 && frameHeight == 120)
379 dc1394_mode = MODE_160x120_YUV444;
380 else {
381 PTRACE(1, "Frame size is neither 320x240 or 160x120" << frameWidth <<
382 "x" << frameHeight);
383 return FALSE;
385 PTRACE(1, deviceName << " " << channelNumber);
387 quadlet_t supported_framerates;
388 if (dc1394_query_supported_framerates(handle, camera_nodes[channelNumber],
389 FORMAT_VGA_NONCOMPRESSED, dc1394_mode,
390 &supported_framerates) != DC1394_SUCCESS) {
391 PTRACE(1, "dc1394_query_supported_framerates() failed.");
392 return FALSE;
395 int framerate;
397 // supported_framerates seems always in the network byte order.
398 if (supported_framerates & (1U << (31-5)))
399 framerate = FRAMERATE_60;
400 else if (supported_framerates & (1U << (31-4)))
401 framerate = FRAMERATE_30;
402 else if (supported_framerates & (1U << (31-3)))
403 framerate = FRAMERATE_15;
404 else if (supported_framerates & (1U << (31-2)))
405 framerate = FRAMERATE_7_5;
406 else if (supported_framerates & (1U << (31-1)))
407 framerate = FRAMERATE_3_75;
408 else if (supported_framerates & (1U << (31-0)))
409 framerate = FRAMERATE_1_875;
410 else {
411 PTRACE(1, "No supported frame rate??!!" << supported_framerates);
412 return FALSE;
415 // In order to compile the following line, you need libdc1394 0.9.0 or later.
416 if ((UseDMA &&dc1394_dma_setup_capture(handle,camera_nodes[channelNumber],
417 0, /* channel of IEEE 1394 */
418 FORMAT_VGA_NONCOMPRESSED,
419 dc1394_mode,
420 P_DC1394_DEFAULT_SPEED,
421 framerate, 4, 1, deviceName,
422 &camera)!=DC1394_SUCCESS) ||
423 (!UseDMA && dc1394_setup_capture(handle,camera_nodes[channelNumber],
424 0, /* channel of IEEE 1394 */
425 FORMAT_VGA_NONCOMPRESSED,
426 dc1394_mode,
427 P_DC1394_DEFAULT_SPEED,
428 framerate,
429 &camera)!=DC1394_SUCCESS))
431 PTRACE(0,"unable to setup camera-\n"
432 "check " __FILE__ " to make sure\n"
433 "that the video mode,framerate and format are\n"
434 "supported by your camera\n");
435 return FALSE;
438 /*-----------------------------------------------------------------------
439 * have the camera start sending us data
440 *-----------------------------------------------------------------------*/
441 if (dc1394_start_iso_transmission(handle,camera.node)
442 !=DC1394_SUCCESS)
444 PTRACE(0, "unable to start camera iso transmission\n");
445 if (UseDMA)
446 dc1394_dma_release_camera(handle,&camera);
447 else
448 dc1394_release_camera(handle,&camera);
449 return FALSE;
451 is_capturing = TRUE;
452 #ifdef ESTIMATE_CAPTURE_PERFORMANCE
453 PTime now;
454 start_time = now.GetTimestamp();
455 num_captured = 0;
456 #endif
457 return TRUE;
461 BOOL PVideoInput1394DcDevice::Stop()
463 if (IsCapturing()) {
464 dc1394_stop_iso_transmission(handle,camera.node);
465 if (UseDMA) {
466 dc1394_dma_unlisten(handle, &camera);
467 dc1394_dma_release_camera(handle,&camera);
468 } else
469 dc1394_release_camera(handle,&camera);
470 is_capturing = FALSE;
471 return TRUE;
472 } else
473 return FALSE;
477 BOOL PVideoInput1394DcDevice::IsCapturing()
479 return is_capturing;
482 PStringList PVideoInput1394DcDevice::GetInputDeviceNames()
484 PStringList list;
486 if (PFile::Exists("/dev/raw1394"))
487 list.AppendString("/dev/raw1394");
488 if (PFile::Exists("/dev/video1394/0"))
489 // DEVFS naming scheme
490 for (int i=0; ; i++) {
491 PString devname = PString("/dev/video1394/") + PString(i);
492 if (PFile::Exists(devname))
493 list.AppendString(devname);
494 else
495 break;
497 else if (PFile::Exists("/dev/video1394"))
498 /* traditional naming */
499 list.AppendString("/dev/video1394");
500 return list;
504 BOOL PVideoInput1394DcDevice::SetVideoFormat(VideoFormat newFormat)
506 if (!PVideoDevice::SetVideoFormat(newFormat)) {
507 PTRACE(3,"PVideoDevice::SetVideoFormat\t failed for format "<<newFormat);
508 return FALSE;
510 return TRUE;
513 int PVideoInput1394DcDevice::GetBrightness()
515 return -1;
519 BOOL PVideoInput1394DcDevice::SetBrightness(unsigned newBrightness)
521 return FALSE;
525 int PVideoInput1394DcDevice::GetHue()
527 return -1;
531 BOOL PVideoInput1394DcDevice::SetHue(unsigned newHue)
533 return FALSE;
537 int PVideoInput1394DcDevice::GetContrast()
539 return -1;
543 BOOL PVideoInput1394DcDevice::SetContrast(unsigned newContrast)
545 return FALSE;
548 BOOL PVideoInput1394DcDevice::SetColour(unsigned newColour)
550 return -1;
553 int PVideoInput1394DcDevice::GetColour()
555 return -1;
559 BOOL PVideoInput1394DcDevice::SetWhiteness(unsigned newWhiteness)
561 return FALSE;
564 int PVideoInput1394DcDevice::GetWhiteness()
566 return -1;
570 BOOL PVideoInput1394DcDevice::GetParameters (int *whiteness, int *brightness,
571 int *colour, int *contrast, int *hue)
573 *whiteness = -1;
574 *brightness = -1;
575 *colour = -1;
576 *hue = -1;
577 return FALSE;
581 int PVideoInput1394DcDevice::GetNumChannels()
583 return numCameras;
587 BOOL PVideoInput1394DcDevice::SetChannel(int newChannel)
589 if (PVideoDevice::SetChannel(newChannel) == FALSE)
590 return FALSE;
591 if(IsCapturing()) {
592 Stop();
593 Start();
595 return TRUE;
600 BOOL PVideoInput1394DcDevice::SetFrameRate(unsigned rate)
602 return PVideoDevice::SetFrameRate(rate);
606 BOOL PVideoInput1394DcDevice::GetFrameSizeLimits(unsigned & minWidth,
607 unsigned & minHeight,
608 unsigned & maxWidth,
609 unsigned & maxHeight)
611 minWidth = 160;
612 maxWidth = 320;
613 minHeight = 120;
614 maxHeight = 240;
615 return TRUE;
620 PINDEX PVideoInput1394DcDevice::GetMaxFrameBytes()
622 if (converter != NULL) {
623 PINDEX bytes = converter->GetMaxDstFrameBytes();
624 if (bytes > frameBytes)
625 return bytes;
628 return frameBytes;
631 BOOL PVideoInput1394DcDevice::GetFrameDataNoDelay(BYTE * buffer, PINDEX * bytesReturned)
633 if (!IsCapturing()) return FALSE;
635 PTRACE(3, "We are going to single capture.\n");
636 if ((UseDMA && dc1394_dma_single_capture(&camera)!=DC1394_SUCCESS) ||
637 (!UseDMA && dc1394_single_capture(handle,&camera)!=DC1394_SUCCESS)){
638 PTRACE(1, "dc1394_single_capture() failed.");
639 return FALSE;
642 PTRACE(3, "single captured, try to convert\n");
644 // If converting on the fly do it from frame store to output buffer, otherwise do
645 // straight copy.
646 if (converter != NULL)
647 converter->Convert((const BYTE *)camera.capture_buffer, buffer, bytesReturned);
648 else {
649 PTRACE(1, "Converter must exist. Something goes wrong.");
650 return FALSE;
653 #ifdef ESTIMATE_CAPTURE_PERFORMANCE
654 ++num_captured;
655 PTime now;
656 double capturing_time = (double)((now.GetTimestamp()-start_time))/1000000;
657 ::fprintf(stderr, "time %f, num_captured=%d, fps=%f\n",
658 capturing_time, num_captured, num_captured/capturing_time);
659 #endif
661 if (UseDMA)
662 dc1394_dma_done_with_buffer(&camera);
663 return TRUE;
666 BOOL PVideoInput1394DcDevice::GetFrameData(BYTE * buffer, PINDEX * bytesReturned)
668 if(frameRate>0) {
669 if (msBetweenFrames > capturing_duration)
670 PThread::Current()->Sleep(msBetweenFrames - capturing_duration);
671 PTime start;
672 if ( !GetFrameDataNoDelay(buffer, bytesReturned))
673 return FALSE;
674 PTime end;
675 capturing_duration = (int)((end-start).GetMilliSeconds());
676 return TRUE;
678 return GetFrameDataNoDelay(buffer,bytesReturned);
682 void PVideoInput1394DcDevice::ClearMapping()
687 BOOL PVideoInput1394DcDevice::TestAllFormats()
689 return TRUE;
692 BOOL PVideoInput1394DcDevice::SetColourFormat(const PString & newFormat)
694 if (newFormat != colourFormat) {
695 return FALSE;
697 return TRUE;
701 BOOL PVideoInput1394DcDevice::SetFrameSize(unsigned width, unsigned height)
703 if ((!(width == 320 && height == 240)) &&
704 (!(width == 160 && height == 120)))
705 return FALSE;
707 frameWidth = width;
708 frameHeight = height;
710 if (frameWidth == 320 && frameHeight == 240)
711 colourFormat = "UYVY422";
712 else if (frameWidth == 160 && frameHeight == 120)
713 colourFormat = "UYV444";
715 frameBytes = PVideoDevice::CalculateFrameBytes(frameWidth, frameHeight, colourFormat);
717 if (IsCapturing()) {
718 Stop(); Start();
721 return TRUE;
725 BOOL PVideoInput1394DcDevice::SetFrameSizeConverter(unsigned width, unsigned height,
726 BOOL bScaleNotCrop)
728 if (width == CIFWidth && height == CIFHeight)
729 SetFrameSize(320, 240);
730 else if (width == QCIFWidth && height == QCIFHeight)
731 SetFrameSize(160, 120);
732 else {
733 PTRACE(1, width << "x" << height << " is not supported.");
734 return FALSE;
737 if (converter != NULL)
738 delete converter;
740 desiredFrameWidth = width;
741 desiredFrameHeight = height;
743 converter = PColourConverter::Create(colourFormat, desiredColourFormat, width, height);
744 if (converter == NULL) {
745 PTRACE(1, "Failed to make a converter.");
746 return FALSE;
748 if (converter->SetSrcFrameSize(frameWidth, frameHeight) == FALSE) {
749 PTRACE(1, "Failed to set source frame size of a converter.");
750 return FALSE;
752 return TRUE;
755 BOOL PVideoInput1394DcDevice::SetColourFormatConverter(const PString & colourFmt)
757 if (colourFmt != "YUV420P") {
758 PTRACE(1, colourFmt << " is unsupported.");
759 return FALSE;
761 desiredColourFormat = colourFmt;
762 return SetFrameSizeConverter(desiredFrameWidth, desiredFrameHeight, FALSE);
767 // End Of File ///////////////////////////////////////////////////////////////