Splitting an AVI File into Multiple Bitmaps Using ltmmSampleTarget for C
The following code utilizes ltmmSampleTarget and ltmmConvert to generate multiple device independent bitmaps from an AVI file.
// define helper macros for using interfaces under C
#define COBJMACROS
// include the LEAD Multimedia TOOLKIT header
#include "ltmm.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>
/////////////////////////////////////////////////////////////////
// SaveBMP24
// saves a bitmap to a file (supports only 24 BPP)
// pszFile - output file name
// pHeader - BITMAPINFOHEADER
// pBits - bitmap image data
//
BOOL SaveBMP24(LPCWSTR pszFile, BITMAPINFOHEADER* pHeader, void* pBits)
{
HANDLE hFile;
TCHAR szFile[MAX_PATH];
BITMAPFILEHEADER bfh;
DWORD nWritten;
#if defined(_UNICODE)
wcscpy(szFile, pszFile);
#else
WideCharToMultiByte(CP_ACP, 0, pszFile, -1, szFile, MAX_PATH, NULL, NULL);
#endif
hFile = CreateFile(szFile, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE)
return FALSE;
bfh.bfType = 0x4D42;
bfh.bfOffBits = sizeof(bfh) + pHeader->biSize;
bfh.bfSize = bfh.bfOffBits + pHeader->biSizeImage;
bfh.bfReserved1 = 0;
bfh.bfReserved2 = 0;
if(!WriteFile(hFile, &bfh, sizeof(bfh), &nWritten, NULL) || nWritten != sizeof(bfh))
{
CloseHandle(hFile);
return FALSE;
}
if(!WriteFile(hFile, pHeader, pHeader->biSize, &nWritten, NULL) || nWritten != pHeader->biSize)
{
CloseHandle(hFile);
return FALSE;
}
if(!WriteFile(hFile, pBits, pHeader->biSizeImage, &nWritten, NULL) || nWritten != pHeader->biSizeImage)
{
CloseHandle(hFile);
return FALSE;
}
CloseHandle(hFile);
return TRUE;
}
/////////////////////////////////////////////////////////////////
// SplitAvi
// splits an avi file into individual BMP files
// pszAviFile - source file name
// pszOutputDir - directory of output BMP files (split?.bmp)
// nMaxFrames - maximum number of BMP files (frames) to generate
//
HRESULT SplitAvi(LPCWSTR pszAviFile, LPCWSTR pszOutputDir, 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;
WCHAR szFile[MAX_PATH];
// 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;
IUnknown_Release(pMediaType);
pMediaType = NULL;
#ifdef _DEBUG
// get it back for debugging
hr = IltmmSampleTarget_GetAcceptedMediaType (pSampleTarget, &pMediaType);
if(FAILED(hr))
goto error;
IUnknown_Release(pMediaType);
pMediaType = NULL;
#endif
// 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;
}
for(n = 0; n < 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))
{
IUnknown_Release(pMediaSample);
goto converterror;
}
hr = SafeArrayAccessData(V_ARRAY(&varBuffer), &pBuffer);
if(FAILED(hr))
{
VariantClear(&varBuffer);
IUnknown_Release(pMediaSample);
goto converterror;
}
// save the image
swprintf(szFile, L"%ssplit%u.bmp", pszOutputDir, n + 1);
if(!SaveBMP24(szFile, &pVIH->bmiHeader, pBuffer))
{
SafeArrayUnaccessData(V_ARRAY(&varBuffer));
VariantClear(&varBuffer);
IUnknown_Release(pMediaSample);
hr = E_FAIL;
goto error;
}
SafeArrayUnaccessData(V_ARRAY(&varBuffer));
VariantClear(&varBuffer);
IUnknown_Release(pMediaSample);
}
// 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)
IUnknown_Release(pConvert);
if(pSampleTarget)
IUnknown_Release(pSampleTarget);
if(pMediaType)
IUnknown_Release(pMediaType);
CoUninitialize();
return hr;
}
int main(int argc, char* argv[])
{
SplitAvi(L"c:\\count.avi", L"c:\\", 10);
return 0;
}
The following code utilizes ltmmSampleTarget and ltmmConvert to generate multiple device independent bitmaps from an AVI file.
// define helper macros for using interfaces under C #ifndef COBJMACROS #define COBJMACROS #endif // include the LEAD Multimedia TOOLKIT header #include "ltmm.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> ///////////////////////////////////////////////////////////////// // SaveBMP24 // saves a bitmap to a file (supports only 24 BPP) // pszFile - output file name // pHeader - BITMAPINFOHEADER // pBits - bitmap image data // BOOL SaveBMP24(LPCWSTR pszFile, BITMAPINFOHEADER* pHeader, void* pBits) { HANDLE hFile; TCHAR szFile[MAX_PATH]; BITMAPFILEHEADER bfh; DWORD nWritten; #if defined(_UNICODE) wcscpy(szFile, pszFile); #else WideCharToMultiByte(CP_ACP, 0, pszFile, -1, szFile, MAX_PATH, NULL, NULL); #endif hFile = CreateFile(szFile, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if(hFile == INVALID_HANDLE_VALUE) return FALSE; bfh.bfType = 0x4D42; bfh.bfOffBits = sizeof(bfh) + pHeader->biSize; bfh.bfSize = bfh.bfOffBits + pHeader->biSizeImage; bfh.bfReserved1 = 0; bfh.bfReserved2 = 0; if(!WriteFile(hFile, &bfh, sizeof(bfh), &nWritten, NULL) || nWritten != sizeof(bfh)) { CloseHandle(hFile); return FALSE; } if(!WriteFile(hFile, pHeader, pHeader->biSize, &nWritten, NULL) || nWritten != pHeader->biSize) { CloseHandle(hFile); return FALSE; } if(!WriteFile(hFile, pBits, pHeader->biSizeImage, &nWritten, NULL) || nWritten != pHeader->biSizeImage) { CloseHandle(hFile); return FALSE; } CloseHandle(hFile); return TRUE; } ///////////////////////////////////////////////////////////////// // SplitAvi // splits an avi file into individual BMP files // pszAviFile - source file name // pszOutputDir - directory of output BMP files (split?.bmp) // nMaxFrames - maximum number of BMP files (frames) to generate // HRESULT SplitAvi(LPCWSTR pszAviFile, LPCWSTR pszOutputDir, 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; WCHAR szFile[MAX_PATH]; // 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; IUnknown_Release(pMediaType); pMediaType = NULL; #ifdef _DEBUG // get it back for debugging hr = IltmmSampleTarget_GetAcceptedMediaType (pSampleTarget, &pMediaType); if(FAILED(hr)) goto error; IUnknown_Release(pMediaType); pMediaType = NULL; #endif // 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; } for(n = 0; n < 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)) { IUnknown_Release(pMediaSample); goto converterror; } hr = SafeArrayAccessData(V_ARRAY(&varBuffer), &pBuffer); if(FAILED(hr)) { VariantClear(&varBuffer); IUnknown_Release(pMediaSample); goto converterror; } // save the image sprintf(szFile, "%ssplit%u.bmp", pszOutputDir, n + 1); if(!SaveBMP24(szFile, &pVIH->bmiHeader, pBuffer)) { SafeArrayUnaccessData(V_ARRAY(&varBuffer)); VariantClear(&varBuffer); IUnknown_Release(pMediaSample); hr = E_FAIL; goto error; } SafeArrayUnaccessData(V_ARRAY(&varBuffer)); VariantClear(&varBuffer); IUnknown_Release(pMediaSample); } // 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) IUnknown_Release(pConvert); if(pSampleTarget) IUnknown_Release(pSampleTarget); if(pMediaType) IUnknown_Release(pMediaType); CoUninitialize(); return hr; } L_MULTIMEDIATEX_API void SplittingAVIFileIntoMultipleBitmapsUsingltmmSampleTarget_Example ( ) { SplitAvi(L"c:\\count.avi", L"c:\\", 10); }