// 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];
HRESULT hr;
long state;
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"));
// start the conversion
hr = g_pConvert->StartConvert();
if(FAILED(hr))
{
_stprintf(sz, _T("conversion error 0x%.8X"), lParam);
SetDlgItemText(hwnd, IDC_CONVERTSTATUS, sz);
UpdateWindow(GetDlgItem(hwnd, IDC_CONVERTSTATUS));
SetDlgItemText(hwnd, IDC_USERABORT, _T("Exit"));
MessageBeep(0);
}
return TRUE;
break;
case WM_DESTROY:
// reset the notification window
g_pConvert->SetNotifyWindow((long) NULL, 0);
#ifdef _DEBUG
{
long state, err, pc;
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);
_stprintf(sz, _T("state = %d, error = 0x%.8X, complete = %d%%"), state, err, pc);
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
SetDlgItemText(hwnd, IDC_CONVERTSTATUS, TEXT("Starting conversion"));
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"));
break;
case ltmmConvert_Notify_ErrorAbort:
// indicate an error
_stprintf(sz, _T("conversion error 0x%.8X"), lParam);
SetDlgItemText(hwnd, IDC_CONVERTSTATUS, sz);
UpdateWindow(GetDlgItem(hwnd, IDC_CONVERTSTATUS));
SetDlgItemText(hwnd, IDC_USERABORT, _T("Exit"));
MessageBeep(0);
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);
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 (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);
// 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;
}
//
// RecompressMemory
// recompresses from global memory to a file using the LEAD video and MP3 audio compressors
//
// 1. the source file is preloaded into memory object
// 2. the source memory is recompressed to the target file
//
// pszSource = source file path
// pszTarget = target file path
//
HRESULT RecompressMemory(LPCTSTR pszSource, LPCTSTR pszTarget)
{
HRESULT hr;
HANDLE hfile;
DWORD size, dwRead;
VARIANT var;
IltmmMemory *pMemSource = NULL, *pMemTarget = NULL;
#ifndef _UNICODE
WCHAR wsz[MAX_PATH];
#endif
// open the source file
hfile = CreateFile(pszSource, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if(hfile == INVALID_HANDLE_VALUE)
return E_FAIL;
// allocate same-sized buffer
size = GetFileSize(hfile, NULL);
// create the source memory object
hr = CoCreateInstance(CLSID_ltmmMemory, NULL, CLSCTX_ALL, IID_IltmmMemory, (void**) &pMemSource);
if (FAILED(hr))
{
AfxMessageBox(TEXT("Error allocating source memory object. Conversion aborted."));
goto error;
}
hr = pMemSource->put_BufferSize(size);
if (FAILED(hr))
goto error;
VariantInit(&var);
pMemSource->LockBuffer(&var);
// read the source file contents
ReadFile(hfile, var.parray->pvData, size, &dwRead, NULL);
pMemSource->Unlock();
VariantClear(&var);
CloseHandle(hfile);
hfile = NULL;
// assign the source object
hr = g_pConvert->put_SourceStream(pMemSource);
if(FAILED(hr))
goto error;
// create the target memory stream
hr = CoCreateInstance(CLSID_ltmmMemory, NULL, CLSCTX_ALL, IID_IltmmMemory, (void**)&pMemTarget);
if (FAILED(hr))
{
AfxMessageBox(TEXT("Error allocating target memory object. Conversion aborted."));
goto error;
}
// set target stream
hr = g_pConvert->put_TargetStream(pMemTarget);
if (FAILED(hr))
goto error;
// setup AVI recompression
hr = SetAVIRecompression(NULL);
if (FAILED(hr))
goto error;
// do conversion
hr = (HRESULT)DialogBox(g_hInstance, (LPCTSTR)IDD_CONVERTDLG, NULL, ConvertDlgProc);
if (FAILED(hr))
goto error;
// write the data to a file
hfile = CreateFile(pszTarget, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
long fl = 0;
unsigned long lBytesWritten;
IltmmMemory *pTarget = NULL;
VARIANT varData;
unsigned char *pBuffer = NULL;
SAFEARRAY sa;
hr = g_pConvert->get_TargetStream((IUnknown**)&pTarget);
if (FAILED(hr))
goto error;
pTarget->get_BufferSize(&fl);
VariantInit(&varData);
// pass data
memset(&sa, 0, sizeof(sa));
sa.cbElements = sizeof(unsigned char);
sa.cDims = 1;
sa.fFeatures = (FADF_AUTO | FADF_FIXEDSIZE);
sa.pvData = new UCHAR[fl];
sa.rgsabound[0].cElements = fl;
V_VT(&varData) = (VT_ARRAY | VT_UI1);
V_ARRAY(&varData) = &sa;
//
// To lock the buffer for synchronization, use the following
// line instead of the line below :
// pTarget->LockBuffer(&varData);
// or
// pTarget->LockRegion(0, fl, &varData);
// You may also use the GetData() function
// To get the data without allocating a SAFEARRAY :
// pTarget->GetData(0, fl, &varData);
//
pTarget->CopyData(0, fl, &varData);
SafeArrayAccessData(V_ARRAY(&varData), (void**)&pBuffer);
// to manipulate the buffer bytes directly without a buffer pointer
// use the SetByte method, for example to change the first two
// bytes in the buffer :
// pTarget->SetByte(0, 0x10);
// pTarget->SetByte(1, 0x13);
WriteFile(hfile, pBuffer, fl, &lBytesWritten, NULL);
// if LockBuffer() or LockRegion() is used, Unloack() must be called :
// g_pTarget->Unlock();
SafeArrayUnaccessData(V_ARRAY(&varData));
VariantClear(&varData);
CloseHandle(hfile);
hfile = NULL;
pTarget->Release();
error:
g_pConvert->ResetSource();
g_pConvert->ResetTarget();
if(pMemSource)
pMemSource->Release();
if(pMemTarget)
pMemTarget->Release();
if (hfile)
CloseHandle(hfile);
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 = RecompressMemory(MAKE_MEDIA_PATH("source.avi"), MAKE_MEDIA_PATH("target.avi"));
if(FAILED(hr))
goto error;
error:
// cleanup
if (g_pConvert)
g_pConvert->Release();
CoUninitialize();
return 0;
}
Help Collections
Raster .NET | C API | C++ Class Library | HTML5 JavaScript
Document .NET | C API | C++ Class Library | HTML5 JavaScript
Medical .NET | C API | C++ Class Library | HTML5 JavaScript
Medical Web Viewer .NET
Multimedia
Direct Show .NET | C API | Filters
Media Foundation .NET | C API | Transforms
Supported Platforms
.NET, Java, Android, and iOS/macOS Assemblies
Imaging, Medical, and Document
C API/C++ Class Libraries
Imaging, Medical, and Document
HTML5 JavaScript Libraries
Imaging, Medical, and Document