Using Memory Conversions for C
The following code demonstrates how to implement memory conversions:
The following code demonstrates how to implement memory conversions:
// define helper macros for using interfaces under C #ifndef COBJMACROS #define COBJMACROS #endif // 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 = NULL; BSTR bstr2 = NULL; HRESULT hr; long state; long type; switch (msg) { case WM_INITDIALOG: // assign the notification window IltmmConvert_SetNotifyWindow (g_pConvert, (long) hwnd, WM_CONVERTNOTIFY); // set the abort button text SetDlgItemText(hwnd, IDC_USERABORT, _T("Abort")); // start the conversion hr = IltmmConvert_StartConvert(g_pConvert); 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 IltmmConvert_SetNotifyWindow (g_pConvert, (long) NULL, 0); #ifdef _DEBUG { long state, err, pc; TCHAR sz[1024]; // get the current state IltmmConvert_get_State (g_pConvert, &state); // get the current state IltmmConvert_get_ConvertError (g_pConvert, &err); // get the amount converted IltmmConvert_get_PercentComplete (g_pConvert, &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 IltmmConvert_get_State (g_pConvert, &state); if(state == ltmmConvert_State_Running) IltmmConvert_StopConvert(g_pConvert); else { IltmmConvert_get_ConvertError (g_pConvert, (long*) &hr); EndDialog(hwnd, (long) hr); } return TRUE; break; } break; case WM_CONVERTNOTIFY: switch(wParam) { case ltmmConvert_Notify_Started: // indicate conversion has started IltmmConvert_get_SourceType (g_pConvert, &type); switch(type) { case ltmmConvert_Source_File: IltmmConvert_get_SourceFile (g_pConvert, &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; } IltmmConvert_get_TargetType (g_pConvert, &type); switch(type) { case ltmmConvert_Target_File: IltmmConvert_get_TargetFile (g_pConvert, &bstr2); break; case ltmmConvert_Target_Array: bstr2 = SysAllocString(L"[array]"); break; case ltmmConvert_Target_Object: bstr2 = SysAllocString(L"[object]"); break; } _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")); 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 IltmmConvert_get_VideoCompressors (g_pConvert, &pCompressors); bstr = SysAllocString(L"@device:sw:{33D9A760-90C8-11D0-BD43-00A0C911CE86}\\LEAD MCMP/MJPEG Codec (2.0)"); IltmmCompressors_Find(pCompressors, bstr, &index); SysFreeString(bstr); if(index < 0) { // compressor isn't registered IUnknown_Release(pCompressors); return E_FAIL; } IltmmCompressors_put_Selection (pCompressors, index); IUnknown_Release(pCompressors); // select the MP3 audio video compressor IltmmConvert_get_AudioCompressors (g_pConvert, &pCompressors); bstr = SysAllocString(L"@device:cm:{33D9A761-90C8-11D0-BD43-00A0C911CE86}\\85MPEG Layer-3"); IltmmCompressors_Find(pCompressors, bstr, &index); SysFreeString(bstr); if(index < 0) { // compressor isn't registered IUnknown_Release(pCompressors); return E_FAIL; } IltmmCompressors_put_Selection (pCompressors, index); IUnknown_Release(pCompressors); // set output format to AVI IltmmConvert_put_TargetFormat (g_pConvert, ltmmConvert_TargetFormat_Avi); #ifdef _DEBUG { long v; IltmmConvert_get_TargetFormat(g_pConvert, &v); assert(v == ltmmConvert_TargetFormat_Avi); } #endif // set video compressor properties IltmmConvert_HasDialog (g_pConvert, ltmmConvert_Dlg_VideoCompressor, &f); if(f) IltmmConvert_ShowDialog (g_pConvert, ltmmConvert_Dlg_VideoCompressor, (long) hwndParent); // set audio compressor properties IltmmConvert_HasDialog (g_pConvert, ltmmConvert_Dlg_AudioCompressor, &f); if(f) IltmmConvert_ShowDialog (g_pConvert, ltmmConvert_Dlg_AudioCompressor, (long) hwndParent); return S_OK; } // // RecompressArray // recompresses array to array using the LEAD video and MP3 audio compressors // // 1. the source file is preloaded into a source array // 2. the source array is recompressed to a target array // 3. the target array is written to the target file // // pszSource = source file path // pszTarget = target file path // HRESULT RecompressArray(LPCTSTR pszSource, LPCTSTR pszTarget) { HRESULT hr; HANDLE hfile; DWORD size, cb; void* buffer; VARIANT var; SAFEARRAY* psaSource; SAFEARRAY* psaTarget; // 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 SAFEARRAY size = GetFileSize(hfile, NULL); psaSource = SafeArrayCreateVector(VT_UI1, 0, size); if(!psaSource) { CloseHandle(hfile); return E_OUTOFMEMORY; } // read entire source into array SafeArrayAccessData(psaSource, (void**) &buffer); if(!ReadFile(hfile, buffer, size, &cb, NULL) || cb != size) { SafeArrayUnaccessData(psaSource); CloseHandle(hfile); SafeArrayDestroy(psaSource); return E_FAIL; } SafeArrayUnaccessData(psaSource); // close file CloseHandle(hfile); // assign the source array VariantInit(&var); V_VT(&var) = (VT_ARRAY | VT_UI1); V_ARRAY(&var) = psaSource; hr = IltmmConvert_put_SourceArray (g_pConvert, var); if(FAILED(hr)) { SafeArrayDestroy(psaSource); return hr; } #ifdef _DEBUG { VARIANT var; VariantInit(&var); IltmmConvert_get_SourceArray(g_pConvert, &var); assert(var.vt == (VT_ARRAY | VT_UI1)); } #endif // create the target array psaTarget = SafeArrayCreateVector(VT_UI1, 0, 0); if(!psaTarget) { IltmmConvert_ResetSource (g_pConvert); SafeArrayDestroy(psaSource); return E_OUTOFMEMORY; } // assign the target array VariantInit(&var); V_VT(&var) = (VT_ARRAY | VT_UI1); V_ARRAY(&var) = psaTarget; hr = IltmmConvert_put_TargetArray (g_pConvert, var); if(FAILED(hr)) { IltmmConvert_ResetSource (g_pConvert); SafeArrayDestroy(psaSource); SafeArrayDestroy(psaTarget); return hr; } #ifdef _DEBUG { VARIANT var; VariantInit(&var); IltmmConvert_get_TargetArray(g_pConvert, &var); assert(var.vt == (VT_ARRAY | VT_UI1)); } #endif // setup AVI recompression hr = SetAVIRecompression(NULL); if(FAILED(hr)) { IltmmConvert_ResetTarget (g_pConvert); IltmmConvert_ResetSource (g_pConvert); SafeArrayDestroy(psaSource); SafeArrayDestroy(psaTarget); return hr; } // do conversion hr = (HRESULT) DialogBox(g_hInstance, (LPCTSTR)IDD_CONVERTDLG, NULL, ConvertDlgProc); // kill the convert objects interest in the arrays IltmmConvert_ResetTarget (g_pConvert); IltmmConvert_ResetSource (g_pConvert); // don't need the source anymore SafeArrayDestroy(psaSource); // return if the conversion failed if(FAILED(hr)) { SafeArrayDestroy(psaTarget); return hr; } // write the output to file hfile = CreateFile(pszTarget, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL); if(hfile == INVALID_HANDLE_VALUE) { SafeArrayDestroy(psaTarget); return E_FAIL; } SafeArrayAccessData(psaTarget, (void**) &buffer); if(!WriteFile(hfile, buffer, psaTarget->rgsabound[0].cElements, &cb, NULL) || cb != psaTarget->rgsabound[0].cElements) { SafeArrayUnaccessData(psaTarget); CloseHandle(hfile); SafeArrayDestroy(psaTarget); return E_FAIL; } SafeArrayUnaccessData(psaTarget); CloseHandle(hfile); SafeArrayDestroy(psaTarget); return hr; } // // RecompressHGlobal // recompresses from global memory to a file using the LEAD video and MP3 audio compressors // // 1. the source file is preloaded into global memory // 2. the source memory is recompressed to the target file // // pszSource = source file path // pszTarget = target file path // HRESULT RecompressHGlobal(LPCTSTR pszSource, LPCTSTR pszTarget) { HRESULT hr; HANDLE hfile; BSTR bstr; DWORD size, cb; void* buffer; HGLOBAL hglobal; #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); hglobal = GlobalAlloc(GMEM_MOVEABLE, size); if(!hglobal) { CloseHandle(hfile); return E_OUTOFMEMORY; } // read entire source into buffer buffer = GlobalLock(hglobal); if(!ReadFile(hfile, buffer, size, &cb, NULL) || cb != size) { GlobalUnlock(hglobal); CloseHandle(hfile); GlobalFree(hglobal); return E_FAIL; } GlobalUnlock(hglobal); // close file CloseHandle(hfile); // assign the source buffer hr = IltmmConvert_put_SourceHGlobal(g_pConvert, (long) hglobal); if(FAILED(hr)) { GlobalFree(hglobal); return hr; } #ifdef _DEBUG { HGLOBAL hGlobal; IltmmConvert_get_SourceHGlobal(g_pConvert, (long*) &hGlobal); assert(hGlobal != NULL); } #endif // set target file #ifdef _UNICODE bstr = SysAllocString(pszTarget); #else swprintf(wsz, L"%hs", pszTarget); bstr = SysAllocString(wsz); #endif hr = IltmmConvert_put_TargetFile (g_pConvert, bstr); SysFreeString(bstr); if(FAILED(hr)) { IltmmConvert_ResetSource (g_pConvert); GlobalFree(hglobal); return hr; } // setup AVI recompression hr = SetAVIRecompression(NULL); if(FAILED(hr)) { IltmmConvert_ResetSource (g_pConvert); GlobalFree(hglobal); return hr; } // do conversion hr = (HRESULT) DialogBox(g_hInstance, (LPCTSTR)IDD_CONVERTDLG, NULL, ConvertDlgProc); IltmmConvert_ResetSource (g_pConvert); GlobalFree(hglobal); return hr; } L_MULTIMEDIATEX_API void UsingMemoryConversions_Example (HINSTANCE hInstance) { 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 = RecompressArray(_T("c:\\source.avi"), _T("c:\\target1.avi")); if(FAILED(hr)) goto error; hr = RecompressHGlobal(_T("c:\\source.avi"), _T("c:\\target2.avi")); if(FAILED(hr)) goto error; error: // cleanup if(g_pConvert) IUnknown_Release(g_pConvert); CoUninitialize(); }