Recompressing an AVI File for C++

The following code demonstrates how to recompress an AVI file:

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

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

HINSTANCE g_hInstance; // application instance handle
IltmmConvert* g_pConvert; // convert object's interface pointer

// user defined message id used for conversion events
#define WM_CONVERTNOTIFY (WM_USER + 1000)

//
// ConvertDlgProc
// starts the conversion process and provides status feedback
//
// controls:
// IDC_CONVERTSTATUS - static control used for status messages
// IDC_CONVERTPROGRESS - static control used for conversion progress
// IDC_USERABORT - button control used to abort the conversion or exit the dialog

BOOL CALLBACK ConvertDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
   TCHAR sz[256];
   BSTR bstr1;
   BSTR bstr2;
   HRESULT hr;
   long state;
   long type;
   long streams;
   IltmmVCRControl* pVCR;


   switch (msg) 
   {
   case WM_INITDIALOG:
      // assign the notification window
      g_pConvert->SetNotifyWindow ((long) hwnd, WM_CONVERTNOTIFY);
      
      // set the abort button text
      SetDlgItemText(hwnd, IDC_USERABORT, _T("Abort"));

   
      // uncomment the following line to view the the graph in DirectShow GraphEdit
      // g_pConvert->EditGraph ();

      g_pConvert->get_UnrenderedStreams (&streams);
      if(streams != 0)
         MessageBox(hwnd, _T("Not all the streams could be rendered."), _T("Convert"), MB_ICONEXCLAMATION | MB_OK);

      g_pConvert->get_TargetVCRControl (&pVCR);
      hr = pVCR->Record ();
      pVCR->Release();

      if(SUCCEEDED(hr))
         Sleep(2000);

      // start the conversion
      hr = g_pConvert->StartConvert ();
      if(FAILED(hr))
      {
          bstr1 = ltmmGetErrorText(hr);
         _stprintf(sz, _T("%ls"), bstr1);
         SysFreeString(bstr1);
         UpdateWindow(GetDlgItem(hwnd, IDC_CONVERTSTATUS));
         SetDlgItemText(hwnd, IDC_USERABORT, _T("Exit"));
         MessageBeep(0);

         // stop, if vcr
         g_pConvert->get_TargetVCRControl (&pVCR);
         pVCR->Stop ();
         pVCR->Release();

      }
      return TRUE;
      break;
   case WM_DESTROY:
      // reset the notification window
      g_pConvert->SetNotifyWindow ((long) NULL, 0);
#ifdef _DEBUG
   {
      long state, err, pc;
      double start, end, dur;
      TCHAR sz[1024];
      
      // get the current state
      g_pConvert->get_State (&state);
      
      // get the current state
      g_pConvert->get_ConvertError (&err);

      // get the amount converted
      g_pConvert->get_PercentComplete (&pc);
      
      // get the start
      g_pConvert->get_SelectionStart (&start);

      // get the end
      g_pConvert->get_SelectionEnd (&end);

      // get the duration
      g_pConvert->get_Duration (&dur);

      _stprintf(sz, _T("state = %d, error = 0x%.8X, complete = %d%%, start = %g, end = %g, duration = %g"), state, err, pc, start, end, dur);
      MessageBox(NULL, sz, _T("debug"), MB_OK);
   }
#endif
   
      break;
   case WM_COMMAND:
      switch (LOWORD(wParam))
      {
      case IDC_USERABORT:
         // user abort... stop conversion
         g_pConvert->get_State (&state);
         if(state == ltmmConvert_State_Running)
            g_pConvert->StopConvert ();
         else
         {
            g_pConvert->get_ConvertError ((long*) &hr);
            EndDialog(hwnd, (long) hr);
         }
         return TRUE;
         break;
      }
      break;
   case WM_CONVERTNOTIFY:
      switch(wParam)
      {
      case ltmmConvert_Notify_Started:
         // indicate conversion has started
         g_pConvert->get_SourceType (&type);
         switch(type)
         {
         case ltmmConvert_Source_File:
            g_pConvert->get_SourceFile (&bstr1);
            break;
         case ltmmConvert_Source_HGlobal:
            bstr1 = SysAllocString(L"[hglobal]");
            break;
         case ltmmConvert_Source_Array:
            bstr1 = SysAllocString(L"[array]");
            break;
         case ltmmConvert_Source_Object:
            bstr1 = SysAllocString(L"[object]");
            break;
         }
         g_pConvert->get_TargetType (&type);
         switch(type)
         {
         case ltmmConvert_Target_File:
            g_pConvert->get_TargetFile (&bstr2);
            break;
         case ltmmConvert_Target_Array:
            bstr2 = SysAllocString(L"[array]");
            break;
         case ltmmConvert_Target_Object:
            bstr2 = SysAllocString(L"[object]");
            break;
         case ltmmConvert_Target_Device:
            bstr2 = SysAllocString(L"[device]");
            break;
         }
         g_pConvert->get_RenderedStreams (&streams);
         if((streams & ltmmConvert_Stream_Audio) & !(streams & ltmmConvert_Stream_Video))
            _stprintf(sz, _T("recompressing audio from '%ls' to '%ls'..."), bstr1, bstr2);
         else if(!(streams & ltmmConvert_Stream_Audio) & (streams & ltmmConvert_Stream_Video))
            _stprintf(sz, _T("recompressing video from '%ls' to '%ls'..."), bstr1, bstr2);
         else
            _stprintf(sz, _T("recompressing '%ls' to '%ls'..."), bstr1, bstr2);
         SysFreeString(bstr1);
         SysFreeString(bstr2);
         SetDlgItemText(hwnd, IDC_CONVERTSTATUS, sz);
         UpdateWindow(GetDlgItem(hwnd, IDC_CONVERTSTATUS));
         break;
      case ltmmConvert_Notify_Complete:
         // indicate an conversion complete
         _stprintf(sz, _T("conversion complete"));
         SetDlgItemText(hwnd, IDC_CONVERTSTATUS, sz);
         UpdateWindow(GetDlgItem(hwnd, IDC_CONVERTSTATUS));
         SetDlgItemText(hwnd, IDC_USERABORT, _T("Exit"));
         // stop, if vcr
         g_pConvert->get_TargetVCRControl(&pVCR);
         pVCR->Stop ();
         pVCR->Release();

         break;
      case ltmmConvert_Notify_ErrorAbort:
         // indicate an error
          bstr1 = ltmmGetErrorText(lParam);
         _stprintf(sz, _T("%ls"), bstr1);
         SetDlgItemText(hwnd, IDC_CONVERTSTATUS, sz);
          SysFreeString(bstr1);
         UpdateWindow(GetDlgItem(hwnd, IDC_CONVERTSTATUS));
         SetDlgItemText(hwnd, IDC_USERABORT, _T("Exit"));
         MessageBeep(0);
         // stop, if vcr
         g_pConvert->get_TargetVCRControl (&pVCR);
         pVCR->Stop ();
         pVCR->Release();

         break;
      case ltmmConvert_Notify_UserAbort:
         // indicate user abort
         _stprintf(sz, _T("conversion aborted\n"));
         SetDlgItemText(hwnd, IDC_CONVERTSTATUS, sz);
         UpdateWindow(GetDlgItem(hwnd, IDC_CONVERTSTATUS));
         SetDlgItemText(hwnd, IDC_USERABORT, _T("Exit"));
         MessageBeep(0);
         // stop, if vcr
         g_pConvert->get_TargetVCRControl(&pVCR);
         pVCR->Stop ();
         pVCR->Release();
         break;
      case ltmmConvert_Notify_Progress:
         // indicate conversion progress
         _stprintf(sz, _T("%3d%% complete"), lParam);
         SetDlgItemText(hwnd, IDC_CONVERTPROGRESS, sz);
         UpdateWindow(GetDlgItem(hwnd, IDC_CONVERTPROGRESS));
         break;
      }
      return TRUE;
      break;
   }
   return FALSE;
}


//
// SetAVIRecompression
// sets up LEAD video compression, MP3 audio compression, and AVI file output
//
// hwndParent = parent window for compressor property dialog boxes
//
HRESULT SetAVIRecompression(HWND hwndParent)
{
   IltmmCompressors* pCompressors;
   long index;
   VARIANT_BOOL f;
   BSTR bstr;

   // select the LEAD video compressor
   g_pConvert->get_VideoCompressors (&pCompressors);
   bstr = SysAllocString(L"@device:sw:{33D9A760-90C8-11D0-BD43-00A0C911CE86}\\LEAD MCMP/MJPEG Codec A COmpressor combined with a DECompressor, or encoder and a decoder, which allows you to both compress and decompress that same data.COmpressor Also known as an encoder, this is a module or algorithm to compress data. Playing that data back requires a decompressor, or decoder. combined with a DECompressor, or encoder Also known as compressor, this is a module or algorithm to compress data. Playing that data back requires a decompressor, or decoder. and a decoder Also known as a decompressor, this is a module or algorithm to decompress data., which allows you to both compress and decompress that same data. (2.0)");
   pCompressors->Find (bstr, &index);
   SysFreeString(bstr);
   if(index < 0)
   {
      // compressor isn't registered
      pCompressors->Release ();
      return E_FAIL;
   }
   pCompressors->put_Selection (index);
   pCompressors->Release();
   
   
   // select the MP3 audio video compressor
   g_pConvert->get_AudioCompressors (&pCompressors);
   bstr = SysAllocString(L"@device:cm:{33D9A761-90C8-11D0-BD43-00A0C911CE86}\\85MPEG Layer-3");
   pCompressors->Find (bstr, &index);
   SysFreeString(bstr);
   if(index < 0)
   {
      // compressor isn't registered
      pCompressors->Release ();
      return E_FAIL;
   }
   pCompressors->put_Selection (index);
   pCompressors->Release();

   // set output format to AVI
   g_pConvert->put_TargetFormat (ltmmConvert_TargetFormat_Avi);
#ifdef _DEBUG
   {
      long v;
      g_pConvert->get_TargetFormat (&v);
      assert(v == ltmmConvert_TargetFormat_Avi);
   }
#endif

   // set video compressor properties
   g_pConvert->HasDialog (ltmmConvert_Dlg_VideoCompressor, &f);
   if(f)
      g_pConvert->ShowDialog (ltmmConvert_Dlg_VideoCompressor, (long) hwndParent);
   
   // set audio compressor properties
   g_pConvert->HasDialog(ltmmConvert_Dlg_AudioCompressor, &f);
   if(f)
      g_pConvert->ShowDialog(ltmmConvert_Dlg_AudioCompressor, (long) hwndParent);

   return S_OK;
}


//
// RecompressFile
// recompresses a file using the LEAD video and MP3 audio compressors
//
// pszSource = source file path
// pszTarget = target file path
//
HRESULT RecompressFile(LPCTSTR pszSource, LPCTSTR pszTarget)
{
   HRESULT hr;
   BSTR bstr;
#ifndef _UNICODE
   WCHAR wsz[MAX_PATH];
#endif
   
   
   // set source file
#ifdef _UNICODE
   bstr = SysAllocString(pszSource);
#else
   swprintf(wsz, L"%hs", pszSource);
   bstr = SysAllocString(wsz);
#endif
   hr = g_pConvert->put_SourceFile (bstr);
   SysFreeString(bstr);
   if(FAILED(hr))
      return hr;

   // set target file
#ifdef _UNICODE
   bstr = SysAllocString(pszTarget);
#else
   swprintf(wsz, L"%hs", pszTarget);
   bstr = SysAllocString(wsz);
#endif
   hr = g_pConvert->put_TargetFile (bstr);
   SysFreeString(bstr);
   if(FAILED(hr))
      return hr;

   // setup AVI recompression
   hr = SetAVIRecompression(NULL);
   if(FAILED(hr))
      return hr;

   // do conversion
   hr = (HRESULT) DialogBox(g_hInstance, (LPCTSTR)IDD_CONVERTDLG, NULL, ConvertDlgProc);
   
      
   return hr;
}
int APIENTRY WinMain(HINSTANCE hInstance,
                HINSTANCE hPrevInstance,
                LPSTR      lpCmdLine,
                int      nCmdShow)
{
   HRESULT hr;
   
   g_hInstance = hInstance;

   // initialize COM library
   hr = CoInitialize(NULL);
   if(FAILED(hr))
      goto error;
   
   // create the convert object
   hr = CoCreateInstance(CLSID_ltmmConvert, NULL, CLSCTX_INPROC_SERVER, IID_IltmmConvert, (void**) &g_pConvert);
   if(FAILED(hr))
      goto error;
   
   
   hr = RecompressFile(_T("c:\\source.avi"), _T("c:\\target1.avi"));
   if(FAILED(hr))
      goto error;


error:
   // cleanup

   if(g_pConvert)
      g_pConvert->Release ();

   CoUninitialize();
   
   return 0;
}