Contents
Introduction
Webcam is a Simple Object Access Protocol (SOAP) project that will permit
client's software to get, from a Web Service, JPEG pictures captured by a
Webcam. It is my first step experiment in the world of SOAP after several
projects using COM/DCOM and ATL.
The project is split in three parts:
-
Server: Active Template Library Server capturing a picture from the Webcam.
- Web
Service: Generated with WSDL Generator from Microsoft�.
- Client: ActiveX client
connecting to Webcam SOAP Server getting pictures and displaying them.
Server
We use Visual C++ and the Active Template Library (ATL) object Wizard to create a
Simple COM object, called Camera
. It handles the grabbing of the picture and
the JPEG compression.
The jpeg compression is achieved with Intel� JPEG Library v1.5. Get it
here. You may use other libraries, like IJG JPEG LIBRARY, by using the abstract base
class CPicturePacker
.
Camera handling is done using Microsoft� Video for Windows� (VFW).
Get more information on MSDN / Platform SDK Documentation / Graphics and
Multimedia Services / Windows Multimedia / Video Capture.
Trick: VFW needs a handler on a window to attach the camera driver to. As we
chose to create a Simple COM object we do not have access to any window
handler. Calling GetDesktopWindow()
got us one.
HWND hWnd = ::GetDesktopWindow();
if ( hWnd )
{ ...
All functionalities needed to grab a picture on a Webcam are done in the class
CWebCam
. For example the method
GrabFrame
:
bool CWebCam::GrabFrame( CPicturePacker * pPacker,
unsigned char ** ppPackedPicture,
unsigned long * pnPackedPictureBytes )
Use a reference to a
CPicturePacker
base class to pack the original picture's
bits, permitting to extend the packing to whatever format you want, as
mentioned before. In this sample I have written the class
CIntelJpegPacker
inheriting
from
CPicturePacker
and using the Intel� JPEG Library v1.5 to pack the picture
grabbed. You may consider using GDI+ for example to do the same.
The rest of the source is dealing with COM and is nothing special.
Server Interface
Our server needs to achieve two simple operations: grabbing a picture from a
Webcam and compressing it as a JPEG picture according to a compression ratio
defined by the caller. This is achieved in the GrabFrame
method.
HRESULT GrabFrame( [in] short nQuality,
[out, retval] SAFEARRAY(unsigned char) * ppGrabbedPicture );
The input parameter '
nQuality
' represents the jpeg compression ratio, from 1 to 99.
A value of one meaning lowest quality (highest compression) and a value of
ninety-nine meaning highest quality (lowest compression).
As an output return value the client get the jpeg picture in a
SAFEARRAY
of
unsigned
char
. We use this data type because it is fully supported by SOAP
(See faced problem 1 and 2).
Our COM object supports the interface
IErrorInfo
as indicated by
the
ISupportErrorInfo
interface. It permits sending back to the
client information about possible issues encountered by the server. The good
point is that it is fully automatic for us. Read more about that point in
Microsoft SOAP User Guide: "Understanding the SOAP Fault <detail>
Contents".
Before writing your interfaces check out the different types supported by SOAP
in "Data Type Mappings" and there equivalence in programming languages. You
find them in the Microsoft SOAP User Guide.
Web Service
We simply use Microsoft WSDL Generator to wrap our COM object, Camera, into a
SOAP Web Service.
On the welcome page click Next.
|
On the dialog "Select the COM .dll to analyze":
Enter the name of your Web Service, i.e. webcam.
Browse to select your dll.
Click Next.
|
|
On the dialog "Select the services you would like to expose":
Expand the list and check the GrabFrame method.
Click Next.
|
|
On the dialog "SOAP listener information":
In the URI text box, type the url of your webservice, i.e.
http://localhost/webservices/webcam.
Choose ISAPI Listener type.
Then select 2001 as XSD Schema Namespace.
Click Next.
|
|
On the dialog "Specify the location for the new WSDL and WSML files":
Select UTF-8 as character set.
Then select the place you want to store the new files, i.e.
c:\inetpub\WebServices\webcam.
Click Next.
Click Finish.
|
Now we have our Web Service! You must also define a Virtual Directory called
WebServices in IIS.
In the case you want to change the location of the Web Service you need to
change the WSDL file generated by Microsoft WSDL Generator.
Client
We use Visual C++ and Active Template Library (ATL) object Wizard to create an
ActiveX, called Webcam. This ActiveX is the client part of the Web Service
Webcam. It is connecting to the Webcam Web Service, receiving back a jpeg
picture and displaying it.
To be able to compile the project you must have installed SOAP Toolkit on your
computer. Find it
here. For the client you must also have WTL installed. If It is not the
case donwload it
here.
Client Interface
To be able to grab a picture on the Webcam Web Service, we need to specify the
location of the Web Service and a compression ratio. We define this interface:
HRESULT GrabFrame([in] BSTR strWeb ServiceURL, [in] short nQuality);
-
Input parameter 'strWeb ServiceURL' represents Web Service's URL.
-
Input parameter 'nQuality' represents the jpeg compression ratio, from 1 to 99.
A value of one meaning lowest quality (highest compression) and a value of
ninety-nine meaning highest quality (lowest compression).
If we get an error, we display it in a tooltip. To create and display the
tooltip we use Windows Template Library (WTL).
Test
You may test this Web Service after installing client ActiveX on this
page.
Problems Faced
-
When adding the "
GrabFrame
" method to Webcam Server using the ATL "Add Method
to Interface", the method was created correctly in .idl and .h files but the
not in the .cpp. We can find a kind of explanation on MSDN: Q198017.
-
Before SOAP SDK SP2,
SAFEARRAY(unsigned char)
was not correctly handled. You
need the SP2 to get a correct wrapping from SAFEARRAY(unisgned char)
to
base64Binary.
History
Version 1.00
|
December 4, 2001
First release.
|