2 * README for IEEE 1394 digital camera support routine in PWLib
3 * ------------------------------------------------------------
5 * PWLib now contains preliminary support for the IEEE 1394 digital
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
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
41 * - libdc1394 0.9.0 or later.
42 * - Linux 2.4.19 or later, which is required by the above version of
44 * - libraw1394 0.9.0 or later
46 * You cannot compile it with older versions of libdc1394.
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.
65 * They should be send to Ryutaroh Matsumoto <ryutaroh@rmatsumoto.org>.
69 * R. Matsumoto thanks Dr. Derek Smithies for his kind support for making
73 * Technical Notes for Programmers
74 * ------------------------------------------------------------
77 * This module was tested against:
84 * Irez StealthFire Camera (http://www.irez.com)
85 * OrangeMicro iBot Camera (http://www.orangemicro.com)
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
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.
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
140 * Revision 1.2 2004/05/10 10:09:19 csoutheren
141 * Removed printf that was interpreted as a trigraph
143 * Revision 1.1 2003/12/17 15:40:56 dominance
144 * Added DC Plugin as provided by Julien Puydt <julien.puydt@laposte.net>. Needs manual patching of plugins/configure for now though. (i.e. disabled by default, run autoconf in plugins/)
146 * Revision 1.9 2003/03/17 07:53:04 robertj
147 * Removed canCaptureVideo variable as this is really a virtual function to
148 * distinguish PVideoOutputDevice from PVideoInputDevice, it is not dynamic.
150 * Revision 1.8 2002/08/21 00:00:31 dereks
151 * Patches from Ryutaroh, to improve firewire (linux only) support. Many thanks.
153 * Revision 1.7 2002/05/30 22:49:35 dereks
154 * correct implementation of GetInputDeviceNames().
156 * Revision 1.6 2002/03/04 01:21:31 dereks
157 * Add frame rate support to Firewire camera. Thanks Ryutaroh Matsumoto.
159 * Revision 1.5 2002/02/28 19:44:03 dereks
160 * Add complete readme on Firewire usage. Thanks to Ryutaroh Matsumoto.
162 * Revision 1.4 2002/02/21 20:00:21 dereks
163 * Fix memory leak. Thanks Ryutaroh Matsumoto.
165 * Revision 1.3 2002/02/21 19:49:57 dereks
166 * Fix spelling mistake. Thanks Ryutaroh
168 * Revision 1.2 2002/02/20 20:27:28 dereks
169 * updates to previous checkin.
171 * Revision 1.1 2002/02/20 02:37:26 dereks
172 * Initial release of Firewire camera support for linux.
173 * Many thanks to Ryutaroh Matsumoto <ryutaroh@rmatsumoto.org>.
180 #pragma implementation "videoio1394dc.h"
183 #include <ptlib/videoio.h>
184 #include <ptlib/vconvert.h>
185 #include <ptlib/file.h>
186 #include "videoio1394dc.h"
187 #include <sys/utsname.h>
189 PCREATE_VIDINPUT_PLUGIN(DC
, PVideoInput1394DcDevice
);
191 #ifndef P_DC1394_DEFAULT_SPEED
192 #define P_DC1394_DEFAULT_SPEED SPEED_400
195 //#define ESTIMATE_CAPTURE_PERFORMANCE
197 #ifdef ESTIMATE_CAPTURE_PERFORMANCE
199 static PInt64 start_time
;
200 static int num_captured
;
204 ///////////////////////////////////////////////////////////////////////////////
207 PVideoInput1394DcDevice::PVideoInput1394DcDevice()
210 is_capturing
= FALSE
;
211 capturing_duration
= 10000; // arbitrary large value suffices
214 PVideoInput1394DcDevice::~PVideoInput1394DcDevice()
221 static int kernel_version_ok(void)
223 struct utsname utsbuf
;
224 unsigned major_ver
, minor_ver
, minorminor_ver
;
226 if (uname(&utsbuf
) == -1)
229 /* utsbuf.release looks like "2.4.19-pre8". */
230 if (sscanf(utsbuf
.release
, "%u.%u.%u", &major_ver
, &minor_ver
,
231 &minorminor_ver
) < 3)
232 return NG
; /* Should we return OK? */
236 else if (major_ver
<= 1)
241 else if (minor_ver
<= 3)
243 else if (minor_ver
== 4)
244 return minorminor_ver
>= 19;
245 else /* if (minor_ver == 5) */
246 return minorminor_ver
>= 9;
249 BOOL
PVideoInput1394DcDevice::Open(const PString
& devName
, BOOL startImmediate
)
251 if (!kernel_version_ok()) {
252 PTRACE(0, "The Linux kernel version is too old.");
257 PTRACE(0, "You cannot open PVideoInput1394DcDevice twice.");
261 if (devName
== "/dev/raw1394")
263 // Don't forget /dev/video1394/0
264 else if (strncmp(devName
, "/dev/video1394", 14) == 0)
267 PTRACE(0, "devName must be /dev/raw1394 or /dev/video1394");
271 // See if devName is accessible.
272 if (!PFile::Exists(devName
)) {
273 PTRACE(1, devName
<< " is not accessible.");
277 /*-----------------------------------------------------------------------
278 * Open ohci and asign handle to it
279 *-----------------------------------------------------------------------*/
280 handle
= dc1394_create_handle(0);
283 PTRACE(0, "Unable to aquire a raw1394 handle\n"
284 "did you insmod the drivers?\n");
288 /*-----------------------------------------------------------------------
289 * get the camera nodes and describe them as we find them
290 *-----------------------------------------------------------------------*/
291 int numNodes
= raw1394_get_nodecount(handle
);
292 camera_nodes
= dc1394_get_camera_nodes(handle
,&numCameras
,0);
295 PTRACE(0, "no cameras found :(\n");
296 dc1394_destroy_handle(handle
);
301 /*-----------------------------------------------------------------------
302 * to prevent the iso-transfer bug from raw1394 system, check if
303 * camera is highest node. For details see
304 * http://linux1394.sourceforge.net/faq.html#DCbusmgmt
306 * http://sourceforge.net/tracker/index.php?func=detail&aid=435107&group_id=8157&atid=108157
307 *-----------------------------------------------------------------------*/
308 for (int i
=0; i
<numCameras
; i
++) {
309 if( camera_nodes
[i
] == numNodes
-1) {
310 PTRACE(0,"Sorry, your camera is the highest numbered node\n"
311 "of the bus, and has therefore become the root node.\n"
312 "The root node is responsible for maintaining \n"
313 "the timing of isochronous transactions on the IEEE \n"
314 "1394 bus. However, if the root node is not cycle master \n"
315 "capable (it doesn't have to be), then isochronous \n"
316 "transactions will not work. The host controller card is \n"
317 "cycle master capable, however, most cameras are not.\n"
319 "The quick solution is to add the parameter \n"
320 "attempt_root=1 when loading the OHCI driver as a \n"
321 "module. So please do (as root):\n"
324 " insmod ohci1394 attempt_root=1\n"
326 "for more information see the FAQ at \n"
327 "http://linux1394.sourceforge.net/faq.html#DCbusmgmt\n"
329 dc1394_destroy_handle(handle
);
337 colourFormat
= "UYVY422";
338 desiredFrameHeight
= CIFHeight
;
339 desiredFrameWidth
= CIFWidth
;
340 desiredColourFormat
= "YUV420P";
341 capturing_duration
= 10000; // arbitrary large value suffices
342 deviceName
= devName
;
344 // select the specified input and video format
345 if (!SetChannel(channelNumber
) ||
346 !SetVideoFormat(videoFormat
)) {
347 PTRACE(1, "SetChannel() or SetVideoFormat() failed");
352 if (startImmediate
&& !Start()) {
356 PTRACE(3, "Successfully opended\n");
361 BOOL
PVideoInput1394DcDevice::IsOpen()
363 return handle
!= NULL
;
367 BOOL
PVideoInput1394DcDevice::Close()
372 dc1394_destroy_handle(handle
);
379 BOOL
PVideoInput1394DcDevice::Start()
382 if (!IsOpen()) return FALSE
;
383 if (is_capturing
) return TRUE
;
384 if (frameWidth
== 320 && frameHeight
== 240)
385 dc1394_mode
= MODE_320x240_YUV422
;
386 else if (frameWidth
== 160 && frameHeight
== 120)
387 dc1394_mode
= MODE_160x120_YUV444
;
389 PTRACE(1, "Frame size is neither 320x240 or 160x120" << frameWidth
<<
393 PTRACE(1, deviceName
<< " " << channelNumber
);
395 quadlet_t supported_framerates
;
396 if (dc1394_query_supported_framerates(handle
, camera_nodes
[channelNumber
],
397 FORMAT_VGA_NONCOMPRESSED
, dc1394_mode
,
398 &supported_framerates
) != DC1394_SUCCESS
) {
399 PTRACE(1, "dc1394_query_supported_framerates() failed.");
405 // supported_framerates seems always in the network byte order.
406 if (supported_framerates
& (1U << (31-5)))
407 framerate
= FRAMERATE_60
;
408 else if (supported_framerates
& (1U << (31-4)))
409 framerate
= FRAMERATE_30
;
410 else if (supported_framerates
& (1U << (31-3)))
411 framerate
= FRAMERATE_15
;
412 else if (supported_framerates
& (1U << (31-2)))
413 framerate
= FRAMERATE_7_5
;
414 else if (supported_framerates
& (1U << (31-1)))
415 framerate
= FRAMERATE_3_75
;
416 else if (supported_framerates
& (1U << (31-0)))
417 framerate
= FRAMERATE_1_875
;
419 PTRACE(1, "Frame rate " << supported_framerates
<< " is not supported");
423 // In order to compile the following line, you need libdc1394 0.9.0 or later.
424 if ((UseDMA
&&dc1394_dma_setup_capture(handle
,camera_nodes
[channelNumber
],
425 0, /* channel of IEEE 1394 */
426 FORMAT_VGA_NONCOMPRESSED
,
428 P_DC1394_DEFAULT_SPEED
,
429 framerate
, 4, 1, deviceName
,
430 &camera
)!=DC1394_SUCCESS
) ||
431 (!UseDMA
&& dc1394_setup_capture(handle
,camera_nodes
[channelNumber
],
432 0, /* channel of IEEE 1394 */
433 FORMAT_VGA_NONCOMPRESSED
,
435 P_DC1394_DEFAULT_SPEED
,
437 &camera
)!=DC1394_SUCCESS
))
439 PTRACE(0,"unable to setup camera-\n"
440 "check " __FILE__
" to make sure\n"
441 "that the video mode,framerate and format are\n"
442 "supported by your camera\n");
446 /*-----------------------------------------------------------------------
447 * have the camera start sending us data
448 *-----------------------------------------------------------------------*/
449 if (dc1394_start_iso_transmission(handle
,camera
.node
)
452 PTRACE(0, "unable to start camera iso transmission\n");
454 dc1394_dma_release_camera(handle
,&camera
);
456 dc1394_release_camera(handle
,&camera
);
460 #ifdef ESTIMATE_CAPTURE_PERFORMANCE
462 start_time
= now
.GetTimestamp();
469 BOOL
PVideoInput1394DcDevice::Stop()
472 dc1394_stop_iso_transmission(handle
,camera
.node
);
474 dc1394_dma_unlisten(handle
, &camera
);
475 dc1394_dma_release_camera(handle
,&camera
);
477 dc1394_release_camera(handle
,&camera
);
478 is_capturing
= FALSE
;
485 BOOL
PVideoInput1394DcDevice::IsCapturing()
490 PStringList
PVideoInput1394DcDevice::GetInputDeviceNames()
494 if (PFile::Exists("/dev/raw1394"))
495 list
.AppendString("/dev/raw1394");
496 if (PFile::Exists("/dev/video1394/0"))
497 // DEVFS naming scheme
498 for (int i
=0; ; i
++) {
499 PString devname
= PString("/dev/video1394/") + PString(i
);
500 if (PFile::Exists(devname
))
501 list
.AppendString(devname
);
505 else if (PFile::Exists("/dev/video1394"))
506 /* traditional naming */
507 list
.AppendString("/dev/video1394");
512 BOOL
PVideoInput1394DcDevice::SetVideoFormat(VideoFormat newFormat
)
514 if (!PVideoDevice::SetVideoFormat(newFormat
)) {
515 PTRACE(3,"PVideoDevice::SetVideoFormat\t failed for format "<<newFormat
);
521 int PVideoInput1394DcDevice::GetBrightness()
527 BOOL
PVideoInput1394DcDevice::SetBrightness(unsigned newBrightness
)
533 int PVideoInput1394DcDevice::GetHue()
539 BOOL
PVideoInput1394DcDevice::SetHue(unsigned newHue
)
545 int PVideoInput1394DcDevice::GetContrast()
551 BOOL
PVideoInput1394DcDevice::SetContrast(unsigned newContrast
)
556 BOOL
PVideoInput1394DcDevice::SetColour(unsigned newColour
)
561 int PVideoInput1394DcDevice::GetColour()
567 BOOL
PVideoInput1394DcDevice::SetWhiteness(unsigned newWhiteness
)
572 int PVideoInput1394DcDevice::GetWhiteness()
578 BOOL
PVideoInput1394DcDevice::GetParameters (int *whiteness
, int *brightness
,
579 int *colour
, int *contrast
, int *hue
)
589 int PVideoInput1394DcDevice::GetNumChannels()
595 BOOL
PVideoInput1394DcDevice::SetChannel(int newChannel
)
597 if (PVideoDevice::SetChannel(newChannel
) == FALSE
)
608 BOOL
PVideoInput1394DcDevice::SetFrameRate(unsigned rate
)
610 return PVideoDevice::SetFrameRate(rate
);
614 BOOL
PVideoInput1394DcDevice::GetFrameSizeLimits(unsigned & minWidth
,
615 unsigned & minHeight
,
617 unsigned & maxHeight
)
628 PINDEX
PVideoInput1394DcDevice::GetMaxFrameBytes()
630 if (converter
!= NULL
) {
631 PINDEX bytes
= converter
->GetMaxDstFrameBytes();
632 if (bytes
> frameBytes
)
639 BOOL
PVideoInput1394DcDevice::GetFrame(PBYTEArray
& frame
)
642 if (!GetFrameData(frame
.GetPointer(GetMaxFrameBytes()), &returned
))
645 frame
.SetSize(returned
);
650 BOOL
PVideoInput1394DcDevice::GetFrameDataNoDelay(BYTE
* buffer
, PINDEX
* bytesReturned
)
652 if (!IsCapturing()) return FALSE
;
654 PTRACE(3, "We are going to single capture.\n");
655 if ((UseDMA
&& dc1394_dma_single_capture(&camera
)!=DC1394_SUCCESS
) ||
656 (!UseDMA
&& dc1394_single_capture(handle
,&camera
)!=DC1394_SUCCESS
)){
657 PTRACE(1, "dc1394_single_capture() failed.");
661 PTRACE(3, "single captured, try to convert\n");
663 // If converting on the fly do it from frame store to output buffer, otherwise do
665 if (converter
!= NULL
)
666 converter
->Convert((const BYTE
*)camera
.capture_buffer
, buffer
, bytesReturned
);
668 PTRACE(1, "Converter must exist. Something goes wrong.");
672 #ifdef ESTIMATE_CAPTURE_PERFORMANCE
675 double capturing_time
= (double)((now
.GetTimestamp()-start_time
))/1000000;
676 ::fprintf(stderr
, "time %f, num_captured=%d, fps=%f\n",
677 capturing_time
, num_captured
, num_captured
/capturing_time
);
681 dc1394_dma_done_with_buffer(&camera
);
685 BOOL
PVideoInput1394DcDevice::GetFrameData(BYTE
* buffer
, PINDEX
* bytesReturned
)
688 if (msBetweenFrames
> capturing_duration
)
689 PThread::Current()->Sleep(msBetweenFrames
- capturing_duration
);
691 if ( !GetFrameDataNoDelay(buffer
, bytesReturned
))
694 capturing_duration
= (int)((end
-start
).GetMilliSeconds());
697 return GetFrameDataNoDelay(buffer
,bytesReturned
);
701 void PVideoInput1394DcDevice::ClearMapping()
706 BOOL
PVideoInput1394DcDevice::TestAllFormats()
711 BOOL
PVideoInput1394DcDevice::SetColourFormat(const PString
& newFormat
)
713 if (newFormat
!= colourFormat
) {
720 BOOL
PVideoInput1394DcDevice::SetFrameSize(unsigned width
, unsigned height
)
722 if ((!(width
== 320 && height
== 240)) &&
723 (!(width
== 160 && height
== 120)))
727 frameHeight
= height
;
729 if (frameWidth
== 320 && frameHeight
== 240)
730 colourFormat
= "UYVY422";
731 else if (frameWidth
== 160 && frameHeight
== 120)
732 colourFormat
= "UYV444";
734 frameBytes
= PVideoDevice::CalculateFrameBytes(frameWidth
, frameHeight
, colourFormat
);
744 BOOL
PVideoInput1394DcDevice::SetFrameSizeConverter(unsigned width
, unsigned height
,
747 if (width
== CIFWidth
&& height
== CIFHeight
)
748 SetFrameSize(320, 240);
749 else if (width
== QCIFWidth
&& height
== QCIFHeight
)
750 SetFrameSize(160, 120);
752 PTRACE(1, width
<< "x" << height
<< " is not supported.");
756 if (converter
!= NULL
)
759 desiredFrameWidth
= width
;
760 desiredFrameHeight
= height
;
762 converter
= PColourConverter::Create(colourFormat
, desiredColourFormat
, width
, height
);
763 if (converter
== NULL
) {
764 PTRACE(1, "Failed to make a converter.");
767 if (converter
->SetSrcFrameSize(frameWidth
, frameHeight
) == FALSE
) {
768 PTRACE(1, "Failed to set source frame size of a converter.");
774 BOOL
PVideoInput1394DcDevice::SetColourFormatConverter(const PString
& colourFmt
)
776 if (colourFmt
!= "YUV420P") {
777 PTRACE(1, colourFmt
<< " is unsupported.");
780 desiredColourFormat
= colourFmt
;
781 return SetFrameSizeConverter(desiredFrameWidth
, desiredFrameHeight
, FALSE
);
786 // End Of File ///////////////////////////////////////////////////////////////