Capture to Play Object Interfacing for C++

The following code demonstrates grabbing samples from the capture object and feeding them to the play object. It is intended to demonstrate the basic function set that would be required to remote the playback of media samples.

// include the LEAD Multimedia TOOLKIT header
#include "ltmm.h"

#include "resource.h"
#include <tchar.h>
#include <stdio.h>
#include <math.h>
#include <assert.h>

#define SZ_WNDCLASS_PLAY _T("PLAY WNDCLASS")
#define WM_PLAYNOTIFY (WM_USER + 1000) 

HINSTANCE g_hInstance;    // application instance handle
HWND g_hwndPlay;      // video frame window
IltmmPlay* g_pPlay;      // play object interface pointer
IltmmCapture* g_pCapture;   // capture object interface pointer
IltmmSampleTarget* g_pTarget;   // target object, used with capture
IltmmSampleSource* g_pSource;   // source object, used with play

//
// PlayWndProc
// video frame window procedure
//
LRESULT CALLBACK PlayWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 
{
   switch (message) 
   {
   case WM_CREATE: 
      g_hwndPlay = hwnd; 

      // window is the video window frame
      g_pPlay->put_VideoWindowFrame((long) hwnd); 

      // assign the media source
      g_pPlay->put_SourceObject(g_pSource); 
#ifdef _DEBUG
   {
      IUnknown* punk; 
      g_pPlay->get_SourceObject(&punk); 
      assert(punk != NULL); 
      if(punk) 
         punk->Release();
   }
#endif
      
      return 0; 
      break; 
   case WM_DESTROY: 
      PostQuitMessage(0); 
      break; 
   }
   return DefWindowProc(hwnd, message, wParam, lParam); 
}



int APIENTRY WinMain(HINSTANCE hInstance, 
                     HINSTANCE hPrevInstance, 
                     LPSTR     lpCmdLine, 
                     int       nCmdShow) 
{
   MSG msg; 
   HRESULT hr; 
   WNDCLASSEX wcex; 
   IltmmDevices* pDevices; 
   VARIANT var; 
   IltmmMediaTypeDisp* pMediaType; 
   BSTR bstr; 
   long index; 
   IltmmCompressors* pCompressors; 

   g_hInstance = hInstance; 

   // initialize COM library
   hr = CoInitialize(NULL); 
   if(FAILED(hr)) 
      goto error; 
   
   
   // register the video frame window class
   wcex.cbSize = sizeof(WNDCLASSEX); 
   wcex.style = CS_HREDRAW | CS_VREDRAW; 
   wcex.lpfnWndProc = PlayWndProc; 
   wcex.cbClsExtra    = 0; 
   wcex.cbWndExtra  = 0; 
   wcex.hInstance = g_hInstance; 
   wcex.hIcon = NULL; 
   wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 
   wcex.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE + 1); 
   wcex.lpszMenuName = NULL; 
   wcex.lpszClassName = SZ_WNDCLASS_PLAY; 
   wcex.hIconSm = NULL; 
   
   if(!RegisterClassEx(&wcex)) 
      goto error; 

   
   // create the play object
   hr = CoCreateInstance(CLSID_ltmmPlay, NULL, CLSCTX_INPROC_SERVER, IID_IltmmPlay, (void**) &g_pPlay); 
   if(FAILED(hr)) 
      goto error; 
   
   // create the capture object
   hr = CoCreateInstance(CLSID_ltmmCapture, NULL, CLSCTX_INPROC_SERVER, IID_IltmmCapture, (void**) &g_pCapture); 
   if(FAILED(hr)) 
      goto error; 

   // create the target object
   hr = CoCreateInstance(CLSID_ltmmSampleTarget, NULL, CLSCTX_INPROC_SERVER, IID_IltmmSampleTarget, (void**) &g_pTarget); 
   if(FAILED(hr)) 
      goto error; 

   // create the source object
   hr = CoCreateInstance(CLSID_ltmmSampleSource, NULL, CLSCTX_INPROC_SERVER, IID_IltmmSampleSource, (void**) &g_pSource); 
   if(FAILED(hr)) 
      goto error; 

   // no preview
   g_pCapture->put_Preview(VARIANT_FALSE); 

   // select the first video device
   g_pCapture->get_VideoDevices(&pDevices); 
   pDevices->put_Selection(0); 
   pDevices->Release();

   // select the LEAD video compressor
   g_pCapture->get_VideoCompressors(&pCompressors); 
   bstr = SysAllocString(L"@device:sw:{33D9A760-90C8-11D0-BD43-00A0C911CE86}\\LEAD MCMP/MJPEG Codec (2.0)");
   pCompressors->Find(bstr, &index); 
   SysFreeString(bstr); 
   pCompressors->put_Selection(index); 
   pCompressors->Release();

   // set the capture output object
   g_pCapture->put_TargetObject(g_pTarget); 
#ifdef _DEBUG
   {
      IUnknown* punk; 
      g_pCapture->get_TargetObject(&punk); 
      assert(punk != NULL); 
      if(punk) 
         punk->Release();
   }
#endif
   // start running
   hr = g_pCapture->StartCapture(ltmmCapture_Mode_Video); 
   if(FAILED(hr)) 
      goto error; 
      
   // retirve the video media type

   g_pTarget->GetConnectedMediaType(&pMediaType); 
   
   // could just assign the media type to the source object, 
   // but let's get the portable type instead
   pMediaType->GetPortableType(&var);   
   
   // have the portable type, don't need this anymore
   pMediaType->Release();

   // create a new media type
   CoCreateInstance(CLSID_ltmmMediaType, NULL, CLSCTX_INPROC_SERVER, IID_IltmmMediaTypeDisp, (void**) &pMediaType); 

   // initialize it with the portable type
   pMediaType->SetPortableType(var); 

   // assign it to the source object
   g_pSource->SetMediaType(pMediaType); 

#ifdef _DEBUG
   {
      IltmmMediaTypeDisp* punk;
      g_pSource->GetMediaType( &punk);
      assert(punk != NULL);
      if(punk)
         punk->Release();
   }
#endif

   // release the media type
   pMediaType->Release();

   // done with portable type
   VariantClear(&var); 

   // create the video frame window
   if(!CreateWindow(SZ_WNDCLASS_PLAY, _T("Play"), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, 
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, g_hInstance, NULL)) 
      goto error; 
   
   ShowWindow(g_hwndPlay, nCmdShow); 

   UpdateWindow(g_hwndPlay); 

   // process until done
   for(;;)
   {
      if(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) 
      {
         if(!GetMessage(&msg, NULL, 0, 0)) 
            break; 
         TranslateMessage(&msg); 
         DispatchMessage(&msg); 
      }
      else
      {
         IltmmMediaSampleDisp* pSample; 
         
         // fetch a sample
         hr = g_pTarget->GetSample(1000, &pSample); 
         if(FAILED(hr)) 
            break; 
         // deliver it
         hr = g_pSource->DeliverSample(1000, pSample); 
         pSample->Release();
         if(FAILED(hr)) 
            goto error; 
      }
   }
   g_pCapture->StopCapture();
   g_pSource->DeliverEndOfStream(1000); 
   g_pPlay->Stop();
error: 
   if(g_pSource) 
      g_pSource->Release();
   if(g_pTarget) 
      g_pTarget->Release();
   if(g_pCapture) 
      g_pCapture->Release();
   if(g_pPlay) 
      g_pPlay->Release();

   CoUninitialize();

   return 0;   
}