303 lines
8.1 KiB
C++
303 lines
8.1 KiB
C++
/*
|
|
* CMP compression method
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include "CODEC.h"
|
|
|
|
#ifdef CODEC_CMP
|
|
|
|
#include "ltmm.h"
|
|
#include "ILMDSKernel2.h"
|
|
#include "IMCMPCodec2.h"
|
|
#include <amvideo.h>
|
|
|
|
IltmmCompressors *gp_Compressors;
|
|
IltmmConvert *gp_Convert;
|
|
ILMDSKernel2 *gp_Kernel;
|
|
|
|
bool b_ContextCreated = false;
|
|
long l_CodecIndex;
|
|
|
|
bool CMP_SetEncodingMethod()
|
|
{
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
VARIANT_BOOL f;
|
|
BSTR bstr, bstrKernel1, bstrKernel2;
|
|
long i;
|
|
HRESULT hr;
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
|
|
// Create kernel and unlock video filters on computer level
|
|
bstrKernel1 = SysAllocString(L"All video filters serial number");
|
|
bstrKernel2 = SysAllocString(L"Application ID");
|
|
hr = CoCreateInstance(CLSID_LMDSKernel2, NULL, CLSCTX_INPROC_SERVER, IID_ILMDSKernel2, (void**) &gp_Kernel);
|
|
gp_Kernel->UnlockModule(bstrKernel1, UNLOCK_COMPUTER, bstrKernel2);
|
|
SysFreeString(bstrKernel1);
|
|
SysFreeString(bstrKernel2);
|
|
|
|
// Create the convert object
|
|
if (!gp_Convert)
|
|
{
|
|
CoInitialize(NULL);
|
|
hr = CoCreateInstance(CLSID_ltmmConvert, NULL, CLSCTX_INPROC_SERVER, IID_IltmmConvert, (void**) &gp_Convert);
|
|
if (FAILED(hr))
|
|
return false;
|
|
}
|
|
|
|
// Select the LEAD video compressor
|
|
gp_Convert->get_VideoCompressors(&gp_Compressors);
|
|
bstr = SysAllocString(L"@device:sw:{33D9A760-90C8-11D0-BD43-00A0C911CE86}\\LEAD MCMP/MJPEG Codec (2.0)");
|
|
gp_Compressors->Find(bstr, &l_CodecIndex);
|
|
SysFreeString(bstr);
|
|
if(l_CodecIndex < 0)
|
|
{
|
|
// Compressor isn't registered
|
|
gp_Compressors->Release();
|
|
return false;
|
|
}
|
|
gp_Compressors->put_Selection(l_CodecIndex);
|
|
gp_Compressors->Release();
|
|
|
|
// Assign the notification window (NULL not to receive messages)
|
|
gp_Convert->SetNotifyWindow(NULL, 0);
|
|
|
|
return true;
|
|
}
|
|
|
|
void *CMP_Encode_INIT(MAP *PPicture)
|
|
{
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
IltmmCompressor *pCompressor;
|
|
static bool b_CompressionSet = false;
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
|
|
// Create converter and set compressor if necessary
|
|
if (!b_CompressionSet)
|
|
if (!CMP_SetEncodingMethod())
|
|
return NULL;
|
|
|
|
b_ContextCreated = true;
|
|
|
|
// Get appropriate compressor
|
|
gp_Compressors->Item(l_CodecIndex, &pCompressor);
|
|
|
|
return (void *)pCompressor;
|
|
}
|
|
|
|
u32 CMP_Encode_FRAME(void *H, MAP *PPicture, char *Buffer, u32 FROMSCRATCH)
|
|
{
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
//IltmmMemory *pSource = NULL, *pTarget = NULL;
|
|
IltmmSampleSource *pSampleSource = NULL;
|
|
IltmmSampleTarget *pSampleTarget = NULL;
|
|
IltmmMediaTypeDisp *pMediaType = NULL;
|
|
HRESULT hr;
|
|
long l_State;
|
|
SAFEARRAY sa;
|
|
VARIANT var;
|
|
IUnknown* pUnk = NULL;
|
|
VARIANT_BOOL f;
|
|
BSTR bstr;
|
|
SAFEARRAY* psaSource;
|
|
SAFEARRAY* psaTarget;
|
|
long index[1];
|
|
IltmmVCRControl *pVCR;
|
|
u32 i,j;
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
|
|
/*
|
|
// Create the source and target objects (they are samples)
|
|
CoCreateInstance(CLSID_ltmmSampleSource, NULL, CLSCTX_INPROC_SERVER, IID_IltmmSampleSource, (void**) &pSampleSource);
|
|
CoCreateInstance(CLSID_ltmmSampleTarget, NULL, CLSCTX_INPROC_SERVER, IID_IltmmSampleTarget, (void**) &pSampleTarget);
|
|
CoCreateInstance(CLSID_ltmmMediaType, NULL, CLSCTX_INPROC_SERVER, IID_IltmmMediaTypeDisp, (void**) &pMediaType);
|
|
CoCreateInstance(CLSID_ltmmMemory, NULL, CLSCTX_INPROC_SERVER, IID_IltmmMemory, (void**) &pSource);
|
|
CoCreateInstance(CLSID_ltmmMemory, NULL, CLSCTX_INPROC_SERVER, IID_IltmmMemory, (void**) &pTarget);
|
|
|
|
// 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;
|
|
bstr = SysAllocString(L"{e436eb7d-524f-11ce-9f53-0020af0ba770}");
|
|
hr = pMediaType->put_Type (bstr);
|
|
SysFreeString(bstr);
|
|
|
|
// set subtype to MEDIASUBTYPE_RGB24
|
|
bstr = SysAllocString(L"{e436eb7d-524f-11ce-9f53-0020af0ba770}");
|
|
hr = pMediaType->put_Subtype (bstr);
|
|
SysFreeString(bstr);
|
|
|
|
// set the accepted media type
|
|
//hr = pSampleSource->SetMediaType(pMediaType);
|
|
hr = pSampleTarget->SetAcceptedMediaType(pMediaType);
|
|
|
|
// Set the source buffer size
|
|
//pSource->put_BufferSize(PPicture->SX * PPicture->SY);
|
|
|
|
// Pass data from the arr BYTE array...
|
|
memset(&sa, 0, sizeof(sa));
|
|
sa.cbElements = sizeof(unsigned char);
|
|
sa.cDims = 1;
|
|
sa.fFeatures = (FADF_AUTO | FADF_FIXEDSIZE);
|
|
sa.pvData = (char *)PPicture->BASE; //data to fill
|
|
sa.rgsabound[0].cElements = PPicture->SX * PPicture->SY;
|
|
|
|
//pSource->SetData(0, PPicture->SX * PPicture->SY, var);
|
|
|
|
pMediaType->SetFormatData(sizeof(VIDEOINFOHEADER), var);
|
|
|
|
// Fixed image size samples
|
|
pMediaType->put_FixedSizeSamples(VARIANT_TRUE);
|
|
pMediaType->put_SampleSize(PPicture->SX * PPicture->SY);
|
|
|
|
// Set the source media type
|
|
hr = pSampleSource->SetMediaType(pMediaType);
|
|
|
|
pMediaType->Release();
|
|
pMediaType = NULL;
|
|
*/
|
|
|
|
// Create the source array
|
|
psaSource = SafeArrayCreateVector(VT_UI1, 0, PPicture->SX * PPicture->SY);
|
|
if (!psaSource)
|
|
{
|
|
gp_Convert->ResetSource();
|
|
SafeArrayDestroy(psaSource);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
// Fill the source array with the image to convert
|
|
SafeArrayAccessData(psaSource, (void **) &PPicture->BASE);
|
|
for (i = 0 ; i < PPicture->SY ; i += PPicture->PITCH)
|
|
{
|
|
for (j = 0 ; j < PPicture->SX ; j++)
|
|
{
|
|
index[0] = j + i*PPicture->PITCH;
|
|
SafeArrayPutElement(psaSource, index, (void *) &PPicture->BASE[index[0]]);
|
|
}
|
|
}
|
|
SafeArrayUnaccessData(psaSource);
|
|
|
|
// Assign the source array
|
|
VariantInit(&var);
|
|
V_VT(&var) = (VT_ARRAY | VT_UI1);
|
|
V_ARRAY(&var) = psaSource;
|
|
|
|
// Set input array
|
|
gp_Convert->ResetSource();
|
|
hr = gp_Convert->put_SourceArray(var);
|
|
if(FAILED(hr)) return -1;
|
|
|
|
/* ~~~~~~~~~~~~ Code to use for internet targeting ~~~~~~~~~~~~*/
|
|
// Set the server address as a target file
|
|
/*BSTR sServer;
|
|
char *server;
|
|
OLECHAR *server2;
|
|
sprintf(server, "%d:255.255.255.255", port);
|
|
|
|
sServer = SysAllocString(server); // use the default port, 27015
|
|
pCapture->put_TargetFile(sServer);
|
|
SysFreeString(sServer);
|
|
|
|
// Change the NET Mux settings if needed:
|
|
// Get the mux object and query for the interface
|
|
IUnknown* pUnk = NULL;
|
|
ILMNetMux* pMux = NULL;
|
|
pCapture->GetSubObject(ltmmCapture_Object_TargetFilter, &pUnk);
|
|
pUnk->QueryInterface(IID_ILMNetMux, (void**) &pMux);
|
|
pUnk->Release();
|
|
|
|
// This is a live source
|
|
pMux->put_LiveSource(VARIANT_TRUE);
|
|
|
|
// I can afford 128 kbps only
|
|
pMux->put_BitRateLimit(128*1024);
|
|
pMux->Release();*/
|
|
/* ~~~~~~~~~~ End of code to use for internet targeting ~~~~~~~~~~*/
|
|
|
|
// Create the target array
|
|
psaTarget = SafeArrayCreateVector(VT_UI1, 0, 0);
|
|
if (!psaTarget)
|
|
{
|
|
gp_Convert->ResetSource();
|
|
gp_Convert->ResetTarget();
|
|
SafeArrayDestroy(psaSource);
|
|
SafeArrayDestroy(psaTarget);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
// Assign the target array
|
|
VariantInit(&var);
|
|
V_VT(&var) = (VT_ARRAY | VT_UI1);
|
|
V_ARRAY(&var) = psaTarget;
|
|
|
|
// Set output array
|
|
gp_Convert->ResetTarget();
|
|
hr = gp_Convert->put_TargetArray(var);
|
|
if(FAILED(hr)) return -1;
|
|
|
|
// Target format is a network stream
|
|
// gp_Convert->put_TargetFormat(ltmmCapture_TargetFormat_NET);
|
|
// gp_Convert->put_TargetFormat(ltmmCapture_TargetFormat_Avi);
|
|
gp_Convert->put_TargetFormat(ltmmCapture_TargetFormat_Stream);
|
|
|
|
// Get network multiplexer
|
|
//gp_Target->GetSubObject(ltmmCapture_Object_TargetFilter, &pUnk);
|
|
|
|
long source, target;
|
|
gp_Convert->get_SourceType(&source);
|
|
gp_Convert->get_TargetType(&target);
|
|
gp_Convert->get_State(&l_State);
|
|
|
|
// start the conversion
|
|
if (l_State != ltmmConvert_State_NotReady && l_State != ltmmConvert_State_Running)
|
|
{
|
|
hr = gp_Convert->StartConvert();
|
|
if(FAILED(hr))
|
|
return -1;
|
|
}
|
|
|
|
// Don't need the source anymore
|
|
SafeArrayDestroy(psaSource);
|
|
|
|
Buffer = (char *)psaTarget->pvData;
|
|
return sizeof(Buffer);
|
|
}
|
|
|
|
void CMP_Encode_CLOSE(void *H)
|
|
{
|
|
/*~~~~~~~~~~~~~~~~~~*/
|
|
BSTR bstr;
|
|
/*~~~~~~~~~~~~~~~~~~*/
|
|
|
|
bstr = SysAllocString(L"All video filters serial number");
|
|
|
|
gp_Kernel->LockModules(bstr, LOCK_COMPUTER);
|
|
gp_Kernel->Release();
|
|
CoUninitialize();
|
|
}
|
|
|
|
void *Encode_INIT(MAP *PPicture)
|
|
{
|
|
return CMP_Encode_INIT(PPicture);
|
|
}
|
|
|
|
u32 Encode_FRAME(void *H, MAP *PPicture, char *Buffer, u32 FROMSCRATCH)
|
|
{
|
|
return CMP_Encode_FRAME(H, PPicture, Buffer, FROMSCRATCH);
|
|
}
|
|
|
|
/*u32 Encode_FRAME(void *H, MAP *PPicture, char *Buffer, unsigned short port, u32 FROMSCRATCH)
|
|
{
|
|
return CMP_Encode_FRAME(H, PPicture, Buffer, port, FROMSCRATCH);
|
|
}*/
|
|
|
|
void Encode_CLOSE(void *H)
|
|
{
|
|
CMP_Encode_CLOSE(H);
|
|
}
|
|
|
|
#endif
|
|
|