Splitting an AVI File into a Multipage TIFF File Using ltmmSampleTarget for C
// define helper macros for using interfaces under C
#define COBJMACROS
#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_CHAR L_FAR* 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 = IltmmMediaTypeDisp_put_Type (pMediaType, bstr);
SysFreeString(bstr);
if(FAILED(hr))
goto error;
// set subtype to MEDIASUBTYPE_RGB24
bstr = SysAllocString(L"{e436eb7d-524f-11ce-9f53-0020af0ba770}");
hr = IltmmMediaTypeDisp_put_Subtype (pMediaType, bstr);
SysFreeString(bstr);
if(FAILED(hr))
goto error;
// set the accepted media type
hr = IltmmSampleTarget_SetAcceptedMediaType(pSampleTarget, pMediaType);
if(FAILED(hr))
goto error;
// release the media type, since we don't need it anymore
IltmmMediaTypeDisp_Release(pMediaType);
pMediaType = NULL;
// set the convert input file name
bstr = SysAllocString(pszAviFile);
hr = IltmmConvert_put_SourceFile(pConvert, bstr);
SysFreeString(bstr);
if(FAILED(hr))
goto error;
// set the convert object target
hr = IltmmConvert_put_TargetObject(pConvert, (IUnknown*)pSampleTarget);
if(FAILED(hr))
goto error;
// start the conversion
hr = IltmmConvert_StartConvert(pConvert);
if(FAILED(hr))
goto error;
// get the connected media type
hr = IltmmSampleTarget_GetConnectedMediaType(pSampleTarget, &pMediaType);
if(FAILED(hr))
goto error;
// get the VIDEOINFOHEADER
hr = IltmmMediaTypeDisp_get_Format(pMediaType, &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, 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, 1, 1, 1);
goto converterror;
}
for(n = 0; n < 1 * nMaxFrames; n++)
{
// fetch a sample
hr = IltmmSampleTarget_GetSample(pSampleTarget, 1000, &pMediaSample);
if(FAILED(hr) || !pMediaSample)
break;
// access the image bits
hr = IltmmMediaSampleDisp_get_Buffer(pMediaSample, &varBuffer);
if(FAILED(hr))
{
IltmmMediaSampleDisp_Release(pMediaSample);
IltmmConvert_StopConvert(pConvert);
goto converterror;
}
hr = SafeArrayAccessData(V_ARRAY(&varBuffer), &pBuffer);
if(FAILED(hr))
{
VariantClear(&varBuffer);
IltmmMediaSampleDisp_Release(pMediaSample);
IltmmConvert_StopConvert(pConvert);
goto converterror;
}
// set the data pointer for the bitmap to be the sample
nRet = L_SetBitmapDataPointer(&Bitmap, (L_UCHAR L_FAR*)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);
IltmmMediaSampleDisp_Release(pMediaSample);
if(nRet != SUCCESS)
{
// an error occured - abort the process
hr = E_FAIL;
IltmmConvert_StopConvert(pConvert);
goto converterror;
}
}
// stop
hr = IltmmConvert_StopConvert(pConvert);
if(FAILED(hr))
goto converterror;
// cleanup and exit
hr = S_OK;
converterror:
SafeArrayUnaccessData(V_ARRAY(&varFormat));
VariantClear(&varFormat);
error:
if(pConvert)
IltmmConvert_Release(pConvert);
if(pSampleTarget)
IltmmSampleTarget_Release(pSampleTarget);
if(pMediaType)
IltmmMediaType_Release(pMediaType);
CoUninitialize();
return hr;
}
int main(int argc, char* argv[])
{
AviToTIFF(L"c:\\count.avi", "c:\\multi.tif", 100);
return 0;
}
// define helper macros for using interfaces under C #ifndef COBJMACROS #define COBJMACROS #endif #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_CHAR* 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 = IltmmMediaTypeDisp_put_Type (pMediaType, bstr); SysFreeString(bstr); if(FAILED(hr)) goto error; // set subtype to MEDIASUBTYPE_RGB24 bstr = SysAllocString(L"{e436eb7d-524f-11ce-9f53-0020af0ba770}"); hr = IltmmMediaTypeDisp_put_Subtype (pMediaType, bstr); SysFreeString(bstr); if(FAILED(hr)) goto error; // set the accepted media type hr = IltmmSampleTarget_SetAcceptedMediaType(pSampleTarget, pMediaType); if(FAILED(hr)) goto error; // release the media type, since we don't need it anymore IltmmMediaTypeDisp_Release(pMediaType); pMediaType = NULL; // set the convert input file name bstr = SysAllocString(pszAviFile); hr = IltmmConvert_put_SourceFile(pConvert, bstr); SysFreeString(bstr); if(FAILED(hr)) goto error; // set the convert object target hr = IltmmConvert_put_TargetObject(pConvert, (IUnknown*)pSampleTarget); if(FAILED(hr)) goto error; // start the conversion hr = IltmmConvert_StartConvert(pConvert); if(FAILED(hr)) goto error; // get the connected media type hr = IltmmSampleTarget_GetConnectedMediaType(pSampleTarget, &pMediaType); if(FAILED(hr)) goto error; // get the VIDEOINFOHEADER hr = IltmmMediaTypeDisp_get_Format(pMediaType, &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 = IltmmSampleTarget_GetSample(pSampleTarget, 1000, &pMediaSample); if(FAILED(hr) || !pMediaSample) break; // access the image bits hr = IltmmMediaSampleDisp_get_Buffer(pMediaSample, &varBuffer); if(FAILED(hr)) { IltmmMediaSampleDisp_Release(pMediaSample); IltmmConvert_StopConvert(pConvert); goto converterror; } hr = SafeArrayAccessData(V_ARRAY(&varBuffer), &pBuffer); if(FAILED(hr)) { VariantClear(&varBuffer); IltmmMediaSampleDisp_Release(pMediaSample); IltmmConvert_StopConvert(pConvert); 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); IltmmMediaSampleDisp_Release(pMediaSample); if(nRet != SUCCESS) { // an error occured - abort the process hr = E_FAIL; IltmmConvert_StopConvert(pConvert); goto converterror; } } // stop hr = IltmmConvert_StopConvert(pConvert); if(FAILED(hr)) goto converterror; // cleanup and exit hr = S_OK; converterror: SafeArrayUnaccessData(V_ARRAY(&varFormat)); VariantClear(&varFormat); error: if(pConvert) IltmmConvert_Release(pConvert); if(pSampleTarget) IltmmSampleTarget_Release(pSampleTarget); if(pMediaType) IltmmMediaType_Release(pMediaType); CoUninitialize(); return hr; } L_MULTIMEDIATEX_API void SplittingAVIFileIntoMultipageTIFFFileUsingltmmSampleTarget_Example ( ) { AviToTIFF(L"c:\\count.avi", "c:\\multi.tif", 100); }