Browse Source

In process of adding webcam support. Not finished yet.

Josh Yelon 18 years ago
parent
commit
4f5a95ed47

+ 6 - 4
doc/makepanda/makepanda.py

@@ -730,6 +730,7 @@ def ChooseCompiler():
         AddToPathEnv("INCLUDE", vcdir + "VC\\include")
         AddToPathEnv("LIB",     vcdir + "VC\\lib")
         AddToPathEnv("INCLUDE", platsdk + "include")
+        AddToPathEnv("INCLUDE", platsdk + "include\\atl")
         AddToPathEnv("LIB",     platsdk + "lib")
 	COMPILER="MSVC"
 	THIRDPARTYLIBS="thirdparty/win-libs-vc8/"
@@ -1375,6 +1376,7 @@ def CompileLink(dll, obj, opts, ldef):
         if (opts.count("WINGDI")):      cmd = cmd + " gdi32.lib"
         if (opts.count("ADVAPI")):      cmd = cmd + " advapi32.lib"
         if (opts.count("GLUT")):        cmd = cmd + " opengl32.lib glu32.lib"
+        if (opts.count("DIRECTSHOW")):  cmd = cmd + " strmiids.lib quartz.lib odbc32.lib odbccp32.lib"
         if (PkgSelected(opts,"PNG")):      cmd = cmd + ' ' + THIRDPARTYLIBS + 'png/lib/libpandapng.lib'
         if (PkgSelected(opts,"JPEG")):     cmd = cmd + ' ' + THIRDPARTYLIBS + 'jpeg/lib/libpandajpeg.lib'
         if (PkgSelected(opts,"TIFF")):     cmd = cmd + ' ' + THIRDPARTYLIBS + 'tiff/lib/libpandatiff.lib'
@@ -2587,7 +2589,7 @@ EnqueueIgate(ipath=IPATH, opts=OPTS, outd='libtext.in', obj='libtext_igate.obj',
 #
 
 IPATH=['panda/src/movies']
-OPTS=['BUILDING_PANDA', 'FFMPEG']
+OPTS=['BUILDING_PANDA', 'FFMPEG', 'DX9', 'DIRECTSHOW']
 EnqueueCxx(ipath=IPATH, opts=OPTS, src='movies_composite1.cxx', obj='movies_composite1.obj')
 EnqueueIgate(ipath=IPATH, opts=OPTS, outd='libmovies.in', obj='libmovies_igate.obj',
             src='panda/src/movies',  module='panda', library='libmovies',
@@ -2687,7 +2689,7 @@ if (OMIT.count("VRPN")==0):
 #
 
 IPATH=['panda/metalibs/panda']
-OPTS=['BUILDING_PANDA', 'ZLIB', 'VRPN', 'JPEG', 'PNG', 'TIFF', 'ZLIB',  'NVIDIACG', 'OPENSSL', 'FREETYPE', 'FFTW', 'ADVAPI', 'WINSOCK2', 'WINUSER', 'WINMM', 'FFMPEG', 'ARTOOLKIT']
+OPTS=['BUILDING_PANDA', 'ZLIB', 'VRPN', 'JPEG', 'PNG', 'TIFF', 'ZLIB',  'NVIDIACG', 'OPENSSL', 'FREETYPE', 'FFTW', 'ADVAPI', 'WINSOCK2', 'WINUSER', 'WINMM', 'FFMPEG', 'DIRECTSHOW', 'ARTOOLKIT']
 INFILES=['librecorder.in', 'libpgraph.in', 'libcull.in', 'libgrutil.in', 'libchan.in', 'libpstatclient.in',
          'libchar.in', 'libcollide.in', 'libdevice.in', 'libdgraph.in', 'libdisplay.in', 'libpipeline.in', 'libevent.in',
          'libgobj.in', 'libgsgbase.in', 'liblinmath.in', 'libmathutil.in', 'libparametrics.in',
@@ -2746,7 +2748,7 @@ EnqueueLink(opts=OPTS, dll='libpanda.dll', obj=OBJFILES, xdep=[
 #
 
 IPATH=['panda/src/skel']
-OPTS=['BUILDING_PANDASKEL', 'ARTOOLKIT']
+OPTS=['BUILDING_PANDASKEL', 'ADVAPI']
 EnqueueCxx(ipath=IPATH, opts=OPTS, src='skel_composite.cxx', obj='skel_composite.obj')
 EnqueueIgate(ipath=IPATH, opts=OPTS, outd='libskel.in', obj='libskel_igate.obj',
              src='panda/src/skel',  module='pandaskel', library='libskel',
@@ -2756,7 +2758,7 @@ EnqueueIgate(ipath=IPATH, opts=OPTS, outd='libskel.in', obj='libskel_igate.obj',
 # DIRECTORY: panda/metalibs/panda
 #
 
-OPTS=['BUILDING_PANDASKEL', 'ARTOOLKIT', 'ADVAPI']
+OPTS=['BUILDING_PANDASKEL', 'ADVAPI']
 EnqueueImod(ipath=IPATH, opts=OPTS, obj='libpandaskel_module.obj',
             module='pandaskel', library='libpandaskel', files=["libskel.in","libmovies.in"])
 EnqueueLink(dll='libpandaskel.dll', opts=OPTS, obj=[

+ 3 - 0
panda/src/movies/config_movies.cxx

@@ -18,6 +18,7 @@
 
 #include "config_movies.h"
 #include "dconfig.h"
+#include "webcamVideo.h"
 
 #ifdef HAVE_FFMPEG
 #include "avcodec.h"
@@ -52,6 +53,8 @@ init_libmovies() {
   MovieAudioCursor::init_type();
   InkblotVideo::init_type();
   InkblotVideoCursor::init_type();
+  WebcamVideo::init_type();
+  WebcamVideo::init_cursor_type();
 #ifdef HAVE_FFMPEG
   FfmpegVideo::init_type();
   FfmpegVideoCursor::init_type();

+ 2 - 0
panda/src/movies/movies_composite1.cxx

@@ -15,4 +15,6 @@
 
 #include "ffmpegVirtualFile.cxx"
 
+#include "webcamVideo.cxx"
+
 #include "config_movies.cxx"

+ 18 - 0
panda/src/movies/webcamVideo.I

@@ -0,0 +1,18 @@
+// Filename: webcamVideo.I
+// Created by: jyelon (01Nov2007)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+

+ 70 - 0
panda/src/movies/webcamVideo.cxx

@@ -0,0 +1,70 @@
+// Filename: webcamVideo.cxx
+// Created by: jyelon (01Nov2007)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2007, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "webcamVideo.h"
+#include "pandabase.h"
+#include "movieVideoCursor.h"
+
+TypeHandle WebcamVideo::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: WebcamVideo::Constructor
+//       Access: Public
+//  Description: The parameters x,y, and fps are suggestions.  The
+//               webcam will match these as closely as it can, but
+//               of course, there are no guarantees.
+////////////////////////////////////////////////////////////////////
+WebcamVideo::
+WebcamVideo(const string &dev, int x, int y, int fps) :
+  MovieVideo("webcam"),
+  _specified_device(dev),
+  _specified_x(x),
+  _specified_y(y),
+  _specified_fps(y)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WebcamVideo::Destructor
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+WebcamVideo::
+~WebcamVideo() {
+}
+
+////////////////////////////////////////////////////////////////////
+// The rest of this file is OS-dependent.
+// We include the appropriate version depending 
+// the user's compile-configuration.
+////////////////////////////////////////////////////////////////////
+
+#if defined(HAVE_DX9)
+
+#include "webcamVideoDX.cxx"
+
+#elif defined(HAVE_VIDEO4LINUX)
+
+#include "webcamVideoV4L.cxx"
+
+#else
+
+#include "webcamVideoNull.cxx"
+
+#endif
+

+ 70 - 0
panda/src/movies/webcamVideo.h

@@ -0,0 +1,70 @@
+// Filename: webcamVideo.h
+// Created by: jyelon (01Nov2007)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef WEBCAMVIDEO_H
+#define WEBCAMVIDEO_H
+
+#include "movieVideo.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : WebcamVideo
+// Description : Allows you to open a webcam or other video capture
+//               device as a video stream.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA_MOVIES WebcamVideo : public MovieVideo {
+
+ PUBLISHED:
+  WebcamVideo(const string &dev, int x=640, int y=480, int fps=24);
+  virtual ~WebcamVideo();
+
+  static int    get_num_devices();
+  static string get_device_name(int n);
+  
+  virtual PT(MovieVideoCursor) open();
+  
+ private:
+  string _specified_device;
+  int    _specified_x;
+  int    _specified_y;
+  int    _specified_fps;
+  friend class WebcamVideoCursor;
+  
+public:
+  static void init_cursor_type();
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    MovieVideo::init_type();
+    register_type(_type_handle, "WebcamVideo",
+                  MovieVideo::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "webcamVideo.I"
+
+#endif

+ 479 - 0
panda/src/movies/webcamVideoDX.cxx

@@ -0,0 +1,479 @@
+// Filename: webcamVideoDX.cxx
+// Created by: jyelon (01Nov2007)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2007, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+//
+// This code was created by studying and adapting the VDOGRAB
+// library by Shu-Kai Yang.  We owe him a great deal of thanks
+// for figuring all this out.
+//
+// http://shukaiyang.myweb.hinet.net/index.html
+//
+// The license for VDOGRAB is as follows:
+//
+// "The library is agreed to be used in your production WITHOUT any
+// fee. And the binary file vdograb.dll is agreed to be distributed
+// WITHOUT any fee. Any production using the library DOES NOT need to
+// mark the library on its logo. Therefore, I, the author or the
+// library, AM NOT responsible to any problems possibly caused by the
+// library in your production. I have NO DUTY to fixing any damage or
+// providing any support."
+//
+////////////////////////////////////////////////////////////////////
+
+#define WIN32_LEAN_AND_MEAN 
+
+#undef Configure
+
+#pragma warning(disable:4100) // warning C4100: unreferenced formal parameter
+#pragma warning(disable:4201) // warning C4201: nonstandard extension used : nameless struct/union
+#pragma warning(disable:4511) // warning C4511: copy constructor could not be generated
+#pragma warning(disable:4512) // warning C4512: assignment operator could not be generated
+#pragma warning(disable:4514) // warning C4514: "unreferenced inline function has been removed"
+
+#include <windows.h>
+#include <windowsx.h>
+#include <olectl.h>
+#include <mmsystem.h>
+#include <strmif.h>     // Generated IDL header file for streams interfaces
+#include <amvideo.h>    // ActiveMovie video interfaces and definitions
+#include <amaudio.h>    // ActiveMovie audio interfaces and definitions
+#include <control.h>    // generated from control.odl
+#include <evcode.h>     // event code definitions
+#include <uuids.h>      // declaration of type GUIDs and well-known clsids
+#include <errors.h>     // HRESULT status and error definitions
+#include <edevdefs.h>   // External device control interface defines
+#include <audevcod.h>   // audio filter device error event codes
+#include <dvdevcod.h>   // DVD error event codes
+
+#include <wchar.h>
+#include <string.h>
+#include <windows.h>
+#include <qedit.h>
+#include <atlbase.h>
+
+////////////////////////////////////////////////////////////////////
+//
+// I'm hiding the entire definition of class WebcamVideoCursor in
+// the OS specific portion of the WebcamVideo CXX file.  This goes
+// against Panda3D coding conventions: normally, classes get
+// exposed in header files.  However, this class is such a mess
+// of OS-specific code and conditional compilation that it's better
+// to just hide it entirely.  - Josh
+//
+////////////////////////////////////////////////////////////////////
+
+class WebcamVideoCursor: public MovieVideoCursor
+{
+public:
+  WebcamVideoCursor(WebcamVideo *src);
+  virtual ~WebcamVideoCursor();
+  virtual void fetch_into_buffer(double time, unsigned char *block, bool rgba);
+
+public:
+  void cleanup();
+
+  class CSampleGrabberCB : public ISampleGrabberCB 
+  { 
+  public:
+    int width;
+    int height;
+    
+    ULONG __stdcall AddRef() { return 2; }
+    ULONG __stdcall Release() { return 1; }
+    
+    HRESULT __stdcall QueryInterface(REFIID riid, void ** ppv);
+    HRESULT __stdcall SampleCB(double SampleTime, IMediaSample *pSample);
+    HRESULT __stdcall BufferCB(double dblSampleTime, BYTE *pBuffer, long lBufferSize);
+  };
+
+  IGraphBuilder           *_pGraphBuilder;
+  ICaptureGraphBuilder2   *_pCaptureBuilder;
+  IBaseFilter             *_pSrcFilter;
+  CComPtr<ISampleGrabber>  _pSampleGrabber; 
+  IBaseFilter             *_pVMR9;
+  IMediaControl           *_pMediaCtrl;
+  IVMRWindowlessControl   *_pWindowssCtrl;   
+  CSampleGrabberCB         _sample_grabber_cb;
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    MovieVideoCursor::init_type();
+    register_type(_type_handle, "WebcamVideoCursor",
+                  MovieVideoCursor::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+TypeHandle WebcamVideoCursor::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: WebcamVideo::get_num_devices
+//       Access: Static, Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+int WebcamVideo::
+get_num_devices() {
+  return 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WebcamVideo::get_device_name
+//       Access: Static, Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+string WebcamVideo::
+get_device_name(int n) {
+  return "";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WebcamVideo::open
+//       Access: Published, Virtual
+//  Description: Open this video, returning a MovieVideoCursor.
+////////////////////////////////////////////////////////////////////
+PT(MovieVideoCursor) WebcamVideo::
+open() {
+  return new WebcamVideoCursor(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WebcamVideo::init_cursor_type
+//       Access: Static, Public
+//  Description: Calls WebcamVideoCursor::init_type
+////////////////////////////////////////////////////////////////////
+void WebcamVideo::
+init_cursor_type() {
+  WebcamVideoCursor::init_type();
+  CoInitialize(NULL);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WebcamVideoCursor::Constructor
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+WebcamVideoCursor::
+WebcamVideoCursor(WebcamVideo *src) :
+  MovieVideoCursor(src),
+  _pGraphBuilder(NULL),
+  _pCaptureBuilder(NULL),
+  _pSrcFilter(NULL),
+  _pVMR9(NULL),
+  _pMediaCtrl(NULL),
+  _pWindowssCtrl(NULL)
+{
+
+  wchar_t *pFriendlyName = 0; // Put the device name here.
+
+  AM_MEDIA_TYPE mediaType;
+  VIDEOINFOHEADER *pVideoInfo;
+  RECT srcRect, destRect;
+  
+  ICreateDevEnum *pCreateDevEnum=NULL;
+  IEnumMoniker *pEnumMoniker=NULL;
+  IPropertyBag *property=NULL;
+  IMoniker *pMoniker=NULL;
+  IVMRFilterConfig *pFilterConfig;
+  
+  HRESULT hResult;
+  ULONG cFetched;
+  VARIANT name;
+  
+  static wchar_t deviceName[256];
+  
+  hResult=CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,
+                           IID_IGraphBuilder,(void**)&_pGraphBuilder);
+  if(hResult != S_OK) { cleanup(); return; }
+  
+  
+  hResult=CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC,
+                           IID_ICaptureGraphBuilder2, (void**)&_pCaptureBuilder);
+  if(hResult != S_OK) { cleanup(); return; }
+  
+  _pCaptureBuilder->SetFiltergraph(_pGraphBuilder);
+  cerr << "  IID_IGraphBuilder & IID_ICaptureGraphBuilder2 are established.\n";
+  
+  hResult=_pGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&_pMediaCtrl);
+  if(FAILED(hResult))
+    {  cerr << "  Can not get the IID_IMediaControl interface!";
+    cleanup(); return;  }
+  cerr << "  IID_IMediaControl interface is acquired.\n";
+  
+  
+  
+  
+  
+  hResult=CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
+                           IID_ICreateDevEnum, (void**)&pCreateDevEnum);
+  if(hResult != S_OK) {  cleanup(); return;  }
+  cerr << "  IID_ICreateDevEnum of CLSID_SystemDeviceEnum is acquired.\n";
+  
+   
+  hResult=pCreateDevEnum->CreateClassEnumerator
+    (CLSID_VideoInputDeviceCategory, &pEnumMoniker, 0);
+  if(hResult != DD_OK)
+    {  cleanup();  pCreateDevEnum->Release();  return;  }
+  cerr << "  Moniker of CLSID_VideoInputDeviceCategory is acquired.\n";
+  
+  
+  while(pEnumMoniker->Next(1, &pMoniker, &cFetched) == S_OK)
+    {  if(pFriendlyName)
+      {  
+        pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&property);
+        VariantInit(&name);
+        hResult=property->Read(L"FriendlyName", &name, 0);
+        wcscpy(deviceName, name.bstrVal);
+        VariantClear(&name);
+        property->Release();
+        cerr << "  Enumerated device: " << deviceName << "\n";
+        
+        if(wcscmp(deviceName, pFriendlyName) == 0)
+          {  pMoniker->BindToObject
+               (NULL, NULL, IID_IBaseFilter, (void**)&_pSrcFilter);  }
+      }
+    else
+      {  
+        pMoniker->BindToObject
+          (NULL, NULL, IID_IBaseFilter, (void**)&_pSrcFilter);
+      }
+    
+    pMoniker->Release();
+    if(_pSrcFilter != NULL) {  break;  }
+    }
+  
+  
+  pCreateDevEnum->Release();
+  pEnumMoniker->Release();
+  
+  if(_pSrcFilter == NULL)
+    {  cerr << "  Such capture device is not found.\n";
+    cleanup(); return;  }
+  cerr << "  The capture filter is acquired.\n";
+  
+  
+  hResult=_pGraphBuilder->AddFilter(_pSrcFilter, L"Capture Filter");
+  if(hResult != DD_OK)
+    {  cerr << "  The capture filter can not be added to the graph.\n";
+    cleanup(); return;  }
+  cerr << "  The capture filter has been added to the graph.\n";
+  
+   
+  _pSampleGrabber.CoCreateInstance(CLSID_SampleGrabber);
+  if(!_pSampleGrabber)
+    {  cerr << "  Can not create the sample grabber, maybe qedit.dll is not registered?";
+    cleanup(); return;  }
+  
+  
+  CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabberFilter(_pSampleGrabber);
+  cerr << "  IID_IBaseFilter of CLSID_SampleGrabber is acquired.\n";
+  
+  
+  ZeroMemory(&mediaType, sizeof(AM_MEDIA_TYPE));
+  mediaType.majortype=MEDIATYPE_Video;
+  mediaType.subtype=MEDIASUBTYPE_RGB24;
+  hResult=_pSampleGrabber->SetMediaType(&mediaType);
+  if(FAILED(hResult))
+    {  cerr << "  Fail to set the media type!";
+    cleanup(); return;  }
+  cerr << "  The media type of the sample grabber is set 24-bit RGB.\n";
+  
+  
+  hResult=_pGraphBuilder->AddFilter(pGrabberFilter, L"Sample Grabber");
+  if(FAILED(hResult))
+    {  cerr << "  Fail to add the sample grabber to the graph.";
+    cleanup(); return;  }
+  cerr << "  The sample grabber has been added to the graph.\n";
+   
+  hResult=CoCreateInstance(CLSID_VideoMixingRenderer, NULL, CLSCTX_INPROC,
+                           IID_IBaseFilter, (void**)&_pVMR9);
+  if(FAILED(hResult))
+    {  cerr << "  Can not create the video mixing renderer.";
+    cleanup(); return;  }
+  cerr << "  IID_IBaseFilter of CLSID_VideoMixingRenderer is acquired.\n";
+  
+  
+  hResult=_pGraphBuilder->AddFilter(_pVMR9, L"Video Mixing Renderer");
+  if(FAILED(hResult))
+    {  cerr << "  Fail to add the VMR to the graph.";
+    cleanup(); return;  }
+  cerr << "  The VMR has been added to the graph.\n";
+  
+  
+  hResult=_pVMR9->QueryInterface(IID_IVMRFilterConfig, (void**)&pFilterConfig);
+  if(FAILED(hResult))
+    {  cerr << "  Can not get IVMRFilterConfig interface of VMR.";
+    cleanup(); return;  }
+  
+  hResult=pFilterConfig->SetRenderingMode(VMRMode_Windowless);
+  pFilterConfig->Release();
+  
+  if(FAILED(hResult))
+    {  cerr << "  Can not set VMR in windowless mode.";
+    cleanup(); return;  }
+  cerr << "  VMR is set in windowless mode by IVMRFilterConfig interface.\n";
+  
+  hResult=_pVMR9->QueryInterface(IID_IVMRWindowlessControl, (void**)&_pWindowssCtrl);
+  if(FAILED(hResult))
+    {  cerr << "  Can not get the IVMRWindowlessControl interface.";
+    cleanup(); return;  }
+  
+  cerr << "  IID_IVMRWindowlessControl interface is acquired.\n";
+  _pWindowssCtrl->SetVideoClippingWindow(GetDesktopWindow());
+  
+  
+  
+  
+  
+  hResult=_pCaptureBuilder->RenderStream(&PIN_CATEGORY_PREVIEW,
+                                          &MEDIATYPE_Video, _pSrcFilter, pGrabberFilter, _pVMR9);
+  if(FAILED(hResult))
+    {  hResult=_pCaptureBuilder->RenderStream(&PIN_CATEGORY_CAPTURE,
+                                               &MEDIATYPE_Video, _pSrcFilter, pGrabberFilter, _pVMR9);
+    
+    if(FAILED(hResult))
+      {  cerr << "  ICaptureGraphBuilder2::RenderStream() can not connect the pins.\n";
+      cleanup(); return;  }
+    }
+  
+  
+  
+  
+  hResult=_pSampleGrabber->GetConnectedMediaType(&mediaType);
+  if(FAILED(hResult))
+    {  cerr << "  Failed to read the connected media type.";
+    cleanup(); return;  }
+  
+  
+  pVideoInfo=(VIDEOINFOHEADER*)mediaType.pbFormat;
+  _sample_grabber_cb.width=pVideoInfo->bmiHeader.biWidth;
+  _sample_grabber_cb.height=pVideoInfo->bmiHeader.biHeight;
+  
+  
+  if(mediaType.cbFormat != 0)
+    {  CoTaskMemFree((PVOID)mediaType.pbFormat);
+    mediaType.cbFormat=0;
+    mediaType.pbFormat=NULL;  }
+  
+  if(mediaType.pUnk != NULL)
+    {  mediaType.pUnk->Release();
+    mediaType.pUnk=NULL;  }
+  
+  
+  _pSampleGrabber->SetBufferSamples(FALSE);
+  _pSampleGrabber->SetOneShot(FALSE);
+  hResult=_pSampleGrabber->SetCallback(&_sample_grabber_cb, 1);
+  if(FAILED(hResult))
+    {  cerr << "  Can not set the callback interface!";
+    cleanup(); return; }
+  
+  
+  SetRect(&srcRect,  0, 0, _sample_grabber_cb.width, _sample_grabber_cb.height);
+  SetRect(&destRect, 0, 0, _sample_grabber_cb.width, _sample_grabber_cb.height);
+  _pWindowssCtrl->SetVideoPosition(&srcRect, &destRect); 
+
+  if(_pMediaCtrl) {
+    _pMediaCtrl->Run();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WebcamVideoCursor::cleanup
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void WebcamVideoCursor::
+cleanup() {
+  if (_pMediaCtrl) {
+    _pMediaCtrl->Stop();
+  }
+  
+  if(_pWindowssCtrl)    {  _pWindowssCtrl->Release();  _pWindowssCtrl=NULL;  }
+  if(_pMediaCtrl)       {  _pMediaCtrl->Release();  _pMediaCtrl=NULL;  }
+  if(_pCaptureBuilder)  {  _pCaptureBuilder->Release();  _pCaptureBuilder=NULL;  }
+  if(_pGraphBuilder)    {  _pGraphBuilder->Release();  _pGraphBuilder=NULL;  }
+  if(_pSampleGrabber.p) {  _pSampleGrabber.Release();  }
+  if(_pVMR9)            {  _pVMR9->Release();  _pVMR9=NULL;  }
+  if(_pSrcFilter)       {  _pSrcFilter->Release();  _pSrcFilter=NULL;  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WebcamVideoCursor::Destructor
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+WebcamVideoCursor::
+~WebcamVideoCursor() {
+  cleanup();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WebcamVideoCursor::fetch_into_buffer
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void WebcamVideoCursor::
+fetch_into_buffer(double time, unsigned char *block, bool rgba) {
+  MovieVideoCursor::fetch_into_buffer(time, block, rgba);
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: WebcamVideoCursor::CSampleGrabberCB::QueryInterface
+//       Access: Private
+//  Description: 
+////////////////////////////////////////////////////////////////////
+HRESULT __stdcall WebcamVideoCursor::CSampleGrabberCB::QueryInterface(REFIID riid, void **ppv)
+{
+  if((riid == IID_ISampleGrabberCB) || (riid == IID_IUnknown)) {
+    *ppv=(void *)static_cast<ISampleGrabberCB *> (this);
+    return NOERROR;
+  } 
+
+  return E_NOINTERFACE;
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: WebcamVideoCursor::CSampleGrabberCB::SampleCB
+//       Access: Private
+//  Description: 
+////////////////////////////////////////////////////////////////////
+HRESULT __stdcall WebcamVideoCursor::CSampleGrabberCB::SampleCB(double SampleTime, IMediaSample *pSample)
+{
+  return 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WebcamVideoCursor::CSampleGrabberCB::BufferCB
+//       Access: Private
+//  Description: 
+////////////////////////////////////////////////////////////////////
+HRESULT __stdcall WebcamVideoCursor::CSampleGrabberCB::BufferCB(double dblSampleTime, BYTE *pBuffer, long lBufferSize)
+{ 
+  // Store the data!
+  return 0;
+}
+

+ 57 - 0
panda/src/movies/webcamVideoNull.cxx

@@ -0,0 +1,57 @@
+// Filename: webcamVideoNull.cxx
+// Created by: jyelon (01Nov2007)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2007, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: WebcamVideo::get_num_devices
+//       Access: Static, Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+int WebcamVideo::
+get_num_devices() {
+  return 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WebcamVideo::get_device_name
+//       Access: Static, Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+string WebcamVideo::
+get_device_name(int n) {
+  return "";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WebcamVideo::open
+//       Access: Published, Virtual
+//  Description: Open this video, returning a MovieVideoCursor.
+////////////////////////////////////////////////////////////////////
+PT(MovieVideoCursor) WebcamVideo::
+open() {
+  skel_cat.error() << "WebcamVideo support is not compiled in.\n";
+  return NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WebcamVideo::init_cursor_type
+//       Access: Static, Public
+//  Description: Calls WebcamVideoCursor::init_type
+////////////////////////////////////////////////////////////////////
+void WebcamVideo::
+init_cursor_type() {
+}

+ 21 - 0
panda/src/movies/webcamVideoV4L.cxx

@@ -0,0 +1,21 @@
+// Filename: webcamVideoV4L.cxx
+// Created by: jyelon (01Nov2007)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+// Video4Linux version not implemented yet.
+
+#include "webcamVideoNull.cxx"