Splitting an AVI File into a Multipage TIFF File Using ltmmSampleTarget for C++

#define MAKE_MEDIA_PATH(pFileName) (TEXT("C:\\LEADTOOLS 17.5\\Media\\")TEXT(pFileName))


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

// include amvideo.h for VIDEOINFOHEADER, available in the Visual Studio 6.0 or the DirectX SDK
#include <amvideo.h>

// includes for string handling
#include <tchar.h>
#include <wchar.h>
#include <string.h>
#include <stdio.h>

/////////////////////////////////////////////////////////////////
// AviToTIFF
// Creates a multipage TIFF file from an AVI file
// pszAviFile - source file name
// pszOutputFile - the name of the output TIF file
// nMaxFrames - maximum number of pages (frames) to append to the file
//
HRESULT AviToTIFF(LPCWSTR pszAviFile, L_TCHAR *pszOutputFile, int nMaxFrames)
{
   HRESULT hr;
   IltmmConvert* pConvert = NULL;
   IltmmSampleTarget* pSampleTarget = NULL;
   IltmmMediaTypeDisp* pMediaType = NULL;
   IltmmMediaSampleDisp* pMediaSample;
   VARIANT varFormat;
   VARIANT varBuffer;
   VIDEOINFOHEADER* pVIH;
   void* pBuffer;
   BSTR bstr;
   int n;
   BITMAPHANDLE Bitmap;
   L_INT nRet;
   // 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**) &pConvert);
   if(FAILED(hr))
      goto error;
   // create the target object
   hr = CoCreateInstance(CLSID_ltmmSampleTarget, NULL, CLSCTX_INPROC_SERVER, IID_IltmmSampleTarget, (void**) &pSampleTarget);
   if(FAILED(hr))
      goto error;
   // create the media type object
   hr = CoCreateInstance(CLSID_ltmmMediaType, NULL, CLSCTX_INPROC_SERVER, IID_IltmmMediaTypeDisp, (void**) &pMediaType);
   if(FAILED(hr))
      goto error;
   // set type to MEDIATYPE_Video
   bstr = SysAllocString(L"{73646976-0000-0010-8000-00AA00389B71}");
   hr = pMediaType->put_Type(bstr);
   SysFreeString(bstr);
   if(FAILED(hr))
      goto error;
   // set subtype to MEDIASUBTYPE_RGB24
   bstr = SysAllocString(L"{e436eb7d-524f-11ce-9f53-0020af0ba770}");
   hr = pMediaType->put_Subtype(bstr);
   SysFreeString(bstr);
   if(FAILED(hr))
      goto error;
   // set the accepted media type
   hr = pSampleTarget->SetAcceptedMediaType(pMediaType);
   if(FAILED(hr))
      goto error;
   // release the media type, since we don't need it anymore
   pMediaType->Release();
   pMediaType = NULL;
   // set the convert input file name
   bstr = SysAllocString(pszAviFile);
   hr = pConvert->put_SourceFile(bstr);
   SysFreeString(bstr);
   if(FAILED(hr))
      goto error;
   // set the convert object target
   hr = pConvert->put_TargetObject(pSampleTarget);
   if(FAILED(hr))
      goto error;
   // start the conversion
   hr = pConvert->StartConvert();
   if(FAILED(hr))
      goto error;
   // get the connected media type
   hr = pSampleTarget->GetConnectedMediaType(&pMediaType);
   if(FAILED(hr))
      goto error;
   // get the VIDEOINFOHEADER
   hr = pMediaType->get_Format(&varFormat);
   if(FAILED(hr))
      goto error;
   hr = SafeArrayAccessData(V_ARRAY(&varFormat), (void**) &pVIH);
   if(FAILED(hr))
   {
      VariantClear(&varFormat);
      goto error;
   }   
   
   // set the shell bitmap handle to match the sample data
   nRet = L_CreateBitmap(&Bitmap, sizeof(BITMAPHANDLE), TYPE_USER,
      pVIH->bmiHeader.biWidth, abs(pVIH->bmiHeader.biHeight),
      pVIH->bmiHeader.biBitCount, ORDER_BGR, NULL,
      pVIH->bmiHeader.biHeight > 0 ? BOTTOM_LEFT : TOP_LEFT,
      NULL, pVIH->bmiHeader.biSizeImage);
   if(nRet != SUCCESS)
   {
      hr = FAILURE;
      // make sure the bitmap handle is initialized so L_FreeBitmap doesn't crash
      L_InitBitmap(&Bitmap, sizeof(BITMAPHANDLE), 1, 1, 1);
      goto converterror;
   }
   for(n = 0; n < 1 * nMaxFrames; n++)
   {
      // fetch a sample
      hr = pSampleTarget->GetSample(1000, &pMediaSample);
      if(FAILED(hr) || !pMediaSample)
         break;
      // access the image bits
      hr = pMediaSample->get_Buffer(&varBuffer);
      if(FAILED(hr))
      {
         pMediaSample->Release();
         pConvert->StopConvert();
         goto converterror;
      }
      hr = SafeArrayAccessData(V_ARRAY(&varBuffer), &pBuffer);
      if(FAILED(hr))
      {
         VariantClear(&varBuffer);
         pMediaSample->Release();
         pConvert->StopConvert();
         goto converterror;
      }
      // set the data pointer for the bitmap to be the sample
      nRet = L_SetBitmapDataPointer(&Bitmap, (L_UCHAR *)pBuffer, pVIH->bmiHeader.biSizeImage);
      if(nRet == SUCCESS)
         // append a JPEG-compressed page to the output file
         nRet = L_SaveFile(pszOutputFile, &Bitmap, FILE_LEAD1JTIF, 0, 25, SAVEFILE_MULTIPAGE, NULL, NULL, NULL);
      // release the sample
      SafeArrayUnaccessData(V_ARRAY(&varBuffer));
      VariantClear(&varBuffer);
      pMediaSample->Release();
      if(nRet != SUCCESS)
      {
         // an error occured - abort the process
         hr = E_FAIL;
         pConvert->StopConvert();
         goto converterror;
      }
   }
   // stop
   hr = pConvert->StopConvert();
   if(FAILED(hr))
      goto converterror;
   // cleanup and exit
   hr = S_OK; converterror:
   SafeArrayUnaccessData(V_ARRAY(&varFormat));
   VariantClear(&varFormat); error:
   if(pConvert)
      pConvert->Release();
   if(pSampleTarget)
      pSampleTarget->Release();
   if(pMediaType)
      pMediaType->Release();
   CoUninitialize();
   return hr;
}
int main(int argc, char* argv[])
{
   AviToTIFF((OLECHAR*)MAKE_MEDIA_PATH("count.avi"), MAKE_MEDIA_PATH("multi.tif"), 100);
   return 0;
}