fFeatures needs to equal 2194? - c++

Currently, I am trying hard to get a safearray of variants to work in my c++ code below. As you can see I call QueueInputReport which has a signature of (SAFEARRAY * psainputreport, UNIT timeoutduration):
CComSafeArray<VARIANT> savt;
//LONG j[5];
LONG length = 4;
//SafeArrayLock(psaValues);
for(LONG i = 0; i <= length; ++i)
{
//j[i] = i;
MessageBox(NULL,L"inputreport assigned to variable",NULL,NULL);
//VariantInit(&pDescriptorData[i]);
//pDescriptorData[i].vt = VT_UI1;
//pDescriptorData[i].bVal = inputreport[i];
//SafeArrayPutElement(psaValues,&i,&pDescriptorData[i]);
// VariantClear(&pDescriptorData[i]);
savt.Add(CComVariant(inputreport[i]));
}
//SafeArrayUnlock(psaValues);
MessageBox(NULL,L"data is successfully assigned to safearray",L"correct data format",NULL);
//FADF_STATIC+FADF_FIXEDSIZE+FADF_HAVEVARTYPE+FADF_VARIANT;
/* _TCHAR szBuffer2[100];
_stprintf_s(szBuffer2, _T("%i"),&psaValues->fFeatures);
MessageBox(NULL,L"safe array type",szBuffer2,NULL);*/
piSoftHidDevice1[devindex]->QueueInputReport(savt,8);
piSoftHidDevice1[devindex]->StartProcessing();
piSoftHidDevice1[devindex]->StopProcessing();
Edit: below is the code for queueinputreport which I needed to pass data to.
STDMETHODIMP CHIDDevice::QueueInputReport( SAFEARRAY* psaInputReport, UINT timeoutDuration )
/*++
Routine Description: Queues additional input reports
Arguments:
IdleTimeout - used to set the value of the log level
Return value:
S_OK
--*/
{
VARIANT * pArrayData = NULL;
UINT cbData = 5;
LONG lLBound = 0;
LONG lUBound = 0;
HRESULT hr = S_OK;
HID_INPUT_REPORT inputReport;
BOOLEAN result = TRUE;
// Initialize Structure
inputReport.timeout = timeoutDuration;
inputReport.cbInputReport = 0;
inputReport.pbInputReport = NULL;
MessageBox(NULL,L"report initialized",L"initial report",NULL);
// Get SAFEARRAY size
IfFailHrGo(SafeArrayGetLBound(psaInputReport, 1, &lLBound));
IfFailHrGo(SafeArrayGetUBound(psaInputReport, 1, &lUBound));
IfFalseHrGo(lUBound > lLBound, E_UNEXPECTED);
cbData = lUBound - lLBound + 1;
//psaInputReport->fFeatures = 0x892;
//psaInputReport->fFeatures = 0x892;
inputReport.pbInputReport = (BYTE*)CoTaskMemAlloc( cbData * sizeof(BYTE) );
_TCHAR szBuffer3[100];
_stprintf_s(szBuffer3, _T("%i"), &psaInputReport->fFeatures);
MessageBox(NULL,L"array content features",szBuffer3,NULL);
// If the memory Allocation fails, then fail and exit
if( inputReport.pbInputReport == NULL )
{
hr = E_UNEXPECTED;
goto Exit;
}
//void HUGEP** cast orginally
IfFailHrGo( SafeArrayAccessData( psaInputReport,
reinterpret_cast<void HUGEP**>(&pArrayData) ) );
// Step through the SAFEARRAY and populating only BYTE input report
// and bail out if the type is not correct
for( LONG i = 0; i <= lUBound; ++i )
{
if (pArrayData[i].vt == VT_UI1)
{
inputReport.pbInputReport[i] = pArrayData[i].bVal;
}
else
{
hr = E_FAIL;
goto Exit;
}
}
SafeArrayUnaccessData(psaInputReport);
inputReport.cbInputReport = cbData;
//MessageBox(NULL,L"report being sent next",L"sent report",NULL);
// Add the report to the input queue (does a shallow copy so no need to free the array data)
result = m_InputReportQueue.insert( inputReport );
if (result == FALSE)
{
MessageBox(NULL,L"failed to queue the input",NULL,NULL);
hr = E_FAIL;
}
return hr;
Exit:
SafeArrayUnaccessData(psaInputReport);
if( FAILED(hr) )
{
CoTaskMemFree(inputReport.pbInputReport);
}
return hr;
}
Edit: The problem is I need the fFeatures to equal 2194 and it is currently its a very high number. What could I be doing wrong?
In vbscript, I have some working code for the queueinputreport:
........(too numerous code to list here but it represents the device I am sending input to (i.e. device #1,#2,#3))
Here's some more information on the fFeatures Iam talking about:
http://msdn.microsoft.com/en-us/library/cc237824.aspx
Dim inputreport(5)
inputreport(0) = CByte(0)
inputreport(1) = CByte(100)
inputreport(2) = CByte(100)
inputreport(3) = CByte(0)
inputreport(4) = Cbyte(0)
pisofthiddevice1(i).QueueInputReport(inputreport, 8)
However, when I try replicating this in C++ above it does not work.

Related

Cannot get hyperlink from winword document: TYPE MISMATCH

I have the following code in my COM Add-In for MS Office to go through all hyperlinks in winword document and then parse them:
...
HRESULT hr;
ULONG nRet;
CComQIPtr<MSWORD::Hyperlinks> hylinks = doc->Hyperlinks; // CComQIPtr<_Document> doc
ATLASSERT(hylinks);
IEnumVARIANTPtr pEnum = hylinks->Get_NewEnum();
for (int i = 1; i <= hylinks->Count; i++)
{
VARIANT v = {};
hr = pEnum->Next(1, &v, &nRet);
if (FAILED(hr)) continue;
CComQIPtr<MSWORD::Hyperlink> link;
ATLASSERT(link);
hr = hylinks->raw_Item(&v, &link);
if (FAILED(hr)) continue;
...
// parse hyperlink's address
}
...
The result (hr) when raw_Item() is called, is 80020005 (DISP_E_TYPEMISMATCH)). And there is no trouble with code like this one when I go through Shapes.
Does anyone can help me?
Finally, found out. How many collections have office application, so many ways to iterate them. Here we can do it like following, assign index of type VARIANT manually, not with enumerator:
CComQIPtr<MSWORD::Hyperlinks> hylinks = doc->Hyperlinks; // CComQIPtr<_Document> doc
ATLASSERT(hylinks);
for (int i = 1; i <= hylinks->Count; i++)
{
VARIANT ind;
ind.iVal = i;
ind.vt = VT_I2;
CComQIPtr<MSWORD::Hyperlink> link;
ATLASSERT(link);
link = hylinks->Item(&ind);
// do your magic
}

OLE DB Bulk Copy Operation Always Loads True into Bit Columns

I'm using the OLE DB bulk copy operation against a SQL Server database but I'm having trouble while loading data into bit columns - they are always populated with true!
I created a simple reproduction program from Microsoft's sample code with the snippet that I adjusted below. My program includes a little SQL script to create the destination table. I had to download and install the x64 version of the SQL Server OLE DB driver to build this.
// Set up custom bindings.
oneBinding.dwPart = DBPART_VALUE | DBPART_LENGTH | DBPART_STATUS;
oneBinding.iOrdinal = 1;
oneBinding.pTypeInfo = NULL;
oneBinding.obValue = ulOffset + offsetof(COLUMNDATA, bData);
oneBinding.obLength = ulOffset + offsetof(COLUMNDATA, dwLength);
oneBinding.obStatus = ulOffset + offsetof(COLUMNDATA, dwStatus);
oneBinding.cbMaxLen = 1; // Size of varchar column.
oneBinding.pTypeInfo = NULL;
oneBinding.pObject = NULL;
oneBinding.pBindExt = NULL;
oneBinding.dwFlags = 0;
oneBinding.eParamIO = DBPARAMIO_NOTPARAM;
oneBinding.dwMemOwner = DBMEMOWNER_CLIENTOWNED;
oneBinding.bPrecision = 0;
oneBinding.bScale = 0;
oneBinding.wType = DBTYPE_BOOL;
ulOffset = oneBinding.cbMaxLen + offsetof(COLUMNDATA, bData);
ulOffset = ROUND_UP(ulOffset, COLUMN_ALIGNVAL);
if (FAILED(hr =
pIFastLoad->QueryInterface(IID_IAccessor, (void**)&pIAccessor)))
return hr;
if (FAILED(hr = pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,
1,
&oneBinding,
ulOffset,
&hAccessor,
&oneStatus)))
return hr;
// Set up memory buffer.
pData = new BYTE[40];
if (!(pData /* = new BYTE[40]*/)) {
hr = E_FAIL;
goto cleanup;
}
pcolData = (COLUMNDATA*)pData;
pcolData->dwLength = 1;
pcolData->dwStatus = 0;
for (i = 0; i < 10; i++)
{
if (i % 2 == 0)
{
pcolData->bData[0] = 0x00;
}
else
{
pcolData->bData[0] = 0xFF;
}
if (FAILED(hr = pIFastLoad->InsertRow(hAccessor, pData)))
goto cleanup;
}
It's entirely likely that I'm putting the wrong value into the buffer, or have some other constant value incorrect. I did find an article describing the safety of various data type conversions and it looks like byte to bool is safe... but how would the buffer know what kind of data I'm putting in there if it's just a byte array?
Figured this out, I had not correctly switched over the demo from loading strings to fixed-width values. For strings, the data blob gets a 1-width pointer to the value whereas fixed-width values get the actual data.
So my COLUMNDATA struct now looks like this:
// How to lay out each column in memory.
struct COLUMNDATA {
DBLENGTH dwLength; // Length of data (not space allocated).
DWORD dwStatus; // Status of column.
VARIANT_BOOL bData; // Value, or if a string, a pointer to the value.
};
With the relevant length fix here:
pcolData = (COLUMNDATA*)pData;
pcolData->dwLength = sizeof(VARIANT_BOOL); // using a short.. make it two
pcolData->dwStatus = DBSTATUS_S_OK; // Indicates that the data value is to be used, not null
And the little value-setting for loop looks like this:
for (i = 0; i < 10; i++)
{
if (i % 2 == 0)
{
pcolData->bData = VARIANT_TRUE;
}
else
{
pcolData->bData = VARIANT_FALSE;
}
if (FAILED(hr = pIFastLoad->InsertRow(hAccessor, pData)))
goto cleanup;
}
I've updated the repository with the working code. I was inspired to make this change after reading the documentation for the obValue property.

Getting digital signature from mmc.exe at windows 8

I have an application that tries to verify the mmc.exe (services) signature. (the context of the application I think is irrelevant) I am trying with winapi function which both fails with
WinVerifyTrust. I get TRUST_E_BAD_DIGEST when I am trying with verification from catalog, and
TRUST_E_NOSIGNATURE when trying from file info. it is very important to mention that my function succeeds on win7, XP but fails on win8.
this is the code snippet for the function
CATALOG_INFO InfoStruct = {0};
InfoStruct.cbStruct = sizeof(CATALOG_INFO);
WINTRUST_CATALOG_INFO WintrustCatalogStructure = {0};
WintrustCatalogStructure.cbStruct = sizeof(WINTRUST_CATALOG_INFO);
WINTRUST_FILE_INFO WintrustFileStructure = {0};
WintrustFileStructure.cbStruct = sizeof(WINTRUST_FILE_INFO);
GUID ActionGuid = WINTRUST_ACTION_GENERIC_VERIFY_V2;
//Get a context for signature verification.
HCATADMIN Context = NULL;
if(!::CryptCATAdminAcquireContext(&Context, NULL, 0) ){
return false;
}
//Open file.
cx_handle hFile(::CreateFileW(filename_.c_str(), GENERIC_READ, 7, NULL, OPEN_EXISTING, 0, NULL));
if( INVALID_HANDLE_VALUE == (HANDLE)hFile )
{
CryptCATAdminReleaseContext(Context, 0);
return false;
}
//Get the size we need for our hash.
DWORD HashSize = 0;
::CryptCATAdminCalcHashFromFileHandle(hFile, &HashSize, NULL, 0);
if( HashSize == 0 )
{
//0-sized has means error!
::CryptCATAdminReleaseContext(Context, 0);
return false;
}
//Allocate memory.
buffer hashbuf(HashSize);
//Actually calculate the hash
if( !CryptCATAdminCalcHashFromFileHandle(hFile, &HashSize, hashbuf.data, 0) )
{
CryptCATAdminReleaseContext(Context, 0);
return false;
}
//Convert the hash to a string.
buffer MemberTag(((HashSize * 2) + 1) * sizeof(wchar_t));
for( unsigned int i = 0; i < HashSize; i++ ){
swprintf(&((PWCHAR)MemberTag.data)[i * 2], L"%02X", hashbuf.data[i ]);
}
//Get catalog for our context.
HCATINFO CatalogContext = CryptCATAdminEnumCatalogFromHash(Context, hashbuf, HashSize, 0, NULL);
if ( CatalogContext )
{
//If we couldn't get information
if ( !CryptCATCatalogInfoFromContext(CatalogContext, &InfoStruct, 0) )
{
//Release the context and set the context to null so it gets picked up below.
CryptCATAdminReleaseCatalogContext(Context, CatalogContext, 0);
CatalogContext = NULL;
}
}
//If we have a valid context, we got our info.
//Otherwise, we attempt to verify the internal signature.
WINTRUST_DATA WintrustStructure = {0};
WintrustStructure.cbStruct = sizeof(WINTRUST_DATA);
if( !CatalogContext )
{
load_signature_verification_from_file_info(WintrustFileStructure, WintrustStructure);
}
else
{
load_signature_verification_from_catalog(WintrustStructure, WintrustCatalogStructure, InfoStruct, MemberTag);
}
//Call our verification function.
long verification_res = ::WinVerifyTrust(0, &ActionGuid, &WintrustStructure);
//Check return.
bool is_success = SUCCEEDED(verification_res) ? true : false;
// if failed with CatalogContext, try with FILE_INFO
if(!is_success && CatalogContext && verification_res != TRUST_E_NOSIGNATURE)
{
//warning2(L"Failed verification with Catalog Context: 0x%x %s ; Retrying with FILE_INFO.", verification_res, (const wchar_t*)format_last_error(verification_res));
load_signature_verification_from_file_info(WintrustFileStructure, WintrustStructure);
verification_res = ::WinVerifyTrust(0, &ActionGuid, &WintrustStructure);
is_success = SUCCEEDED(verification_res) ? true : false;
}
if(perr && !is_success && verification_res != TRUST_E_NOSIGNATURE)
{
perr->code = verification_res;
perr->description = format_last_error(verification_res);
}
//Free context.
if( CatalogContext ){
::CryptCATAdminReleaseCatalogContext(Context, CatalogContext, 0);
}
//If we successfully verified, we need to free.
if( is_success )
{
WintrustStructure.dwStateAction = WTD_STATEACTION_CLOSE;
::WinVerifyTrust(0, &ActionGuid, &WintrustStructure);
}
::CryptCATAdminReleaseContext(Context, 0);
return is_success;
I don't think any thing had changed in this function from win7 to win 8 so what could possibly go wrong?
UPDATE
I did notice that my function does work for task manager at win 8.
but again for the mmc it does not work.
It appears that your general approach is correct and the functions themselves haven't changed. However there are subtle changes; namely the data on which they operate has changed. The hashes stored for files on Windows 8, according to comments on CryptCATAdminCalcHashFromFileHandle, are calculated using SHA-256 hashes.
The SHA-256 hashing algorithm is not supported by CryptCATAdminCalcHashFromFileHandle, so you must update the code to use CryptCATAdminAcquireContext2 and CryptCATAdminCalcHashFromFileHandle2 on Windows 8; the former allows you to acquire a HCATADMIN with a specified hash algorithm, and the latter allows using that HCATADMIN.
(Interestingly, WINTRUST_CATALOG_INFO also points this direction with its HCATADMIN hCatAdmin member, documented as "Windows 8 and Windows Server 2012: Support for this member begins.")

How to pass an array of doubles from VB6 to VC++..What is wrong with this code?

How to pass an array of doubles from VB6 to VC++..What is wrong with this code?
VB Code: dSelfCdArr is my array of double values
Public Sub FilterDocTypeByPriv(colEventSets As Collection)
Dim lCount As Long
Dim oColItem As Object
Dim objDBEventSetRow As DB_EventSetRow
Dim evYes As Boolean
Dim dSelfCdArr() As Double
For lCount = 1 To colEventSets.Count
Set objDBEventSetRow = colEventSets(lCount)
ReDim Preserve dSelfCdArr(1 To lCount)
dSelfCdArr(lCount) = CDbl(objDBEventSetRow.dSelf_cd)
Next
Call m_dtsAppForm.DocController.HasPrivCreateResultEventCode(m_dUserId, m_dPositionCd, m_dPPRCd, dSelfCdArr)
End Sub
C++ Idl file:
[id(51), helpstring("method HasPrivCreateResultEventCode")] HRESULT HasPrivCreateResultEventCode([in]double dUserId,[in]double dPosCd,[in]double dPPRCd, [in, out] VARIANT* pEventCode);
C++ Code: I get bad pointers in the first line for VARIANT* pEventCode
STDMETHODIMP CDocumentController::HasPrivCreateResultEventCode(double dUserId,double dPosCd,double dPPRCd, VARIANT* pEventCode)
{
HRESULT hr = E_FAIL;
AFX_MANAGE_STATE(AfxGetStaticModuleState())
if (V_VT(pEventCode) == VT_ARRAY | VT_R8)
{
CComSafeArray<double> arrECode;
arrECode.Attach(pEventCode->parray);
double pVals;
int iCount = arrECode.GetCount();
CMap<double,double,bool,bool> mapEventCds;
for(int iIndex = 0; iIndex < iCount; iIndex++)
{
double pVals = arrECode.GetAt(iIndex);
mapEventCds.SetAt(pVals, false);
std::cout << "element " << iIndex << ": value = " << pVals << std::endl;
}
CheckPrivViewResultEventCds(dUserId, dPosCd, dPPRCd, mapEventCds);
//pEventCode->c
double dEventCd(0.0);
bool bPriv(false);
POSITION pos(mapEventCds.GetStartPosition());
INT_PTR nEventCnt(mapEventCds.GetCount());
CComSafeArray<double> pSafeArraypEventCode = NULL;
for(INT_PTR count(0); count < nEventCnt; ++count)
{
mapEventCds.GetNextAssoc(pos, dEventCd, bPriv);
if (bPriv)
{
pSafeArraypEventCode.Add(dEventCd);
}
}
pEventCode->parray = pSafeArraypEventCode.Detach();
// Empty the CMap
mapEventCds.RemoveAll();
}
return S_OK;
}
Your problem is here:
if (V_VT(pEventCode) == VT_ARRAY | VT_R8)
The VB equivalent to that would be:
If V_VT(pEventCode) = VT_ARRAY Or True Then
//Do stuff
End If
The | VT_R8 is evaluating to boolean true because:
1) == takes precedence over |, so the comparison is performed, THEN VT_R8 is evaluated.
And
2) Anything that is non-zero equals "true" in C. Since VT_R8 gets evaluated by itself (and not as part of the comparison), it is always true.
You need to use parentheses so that your statements are evaluated in the order you want.
Here is the answer..I had to destroy the original safearray data, create a new safearray to fill the data from maps and then copy the new safearray data to the original safearray using SafeArrayCopy.. It worked.
STDMETHODIMP CDocumentController::GetEventCodesWithAddDocumentationPriv(double dUserId,double dPosCd,double dPPRCd,SAFEARRAY** pArrayOfEventCode)
{
HRESULT lResult(S_OK); // return code for OLE functions
// checking if it is a one-dimensional array
if ( (*pArrayOfEventCode)->cDims != 1 )
{
MsgWrite(MSG_DEFAULT, eMsgLog_Commit, _T("PVClinDocMiscCom"), eMsgLvl_Error, _T("CDocumentController::GetEventCodesWithAddDocumentationPriv() SafeArray pEventCode is not one dimensional"));
return(E_FAIL);
}
// locking the array before using its elements
lResult=SafeArrayLock(*pArrayOfEventCode);
if (lResult != S_OK)
{
MsgWrite(MSG_DEFAULT, eMsgLog_Commit, _T("PVClinDocMiscCom"), eMsgLvl_Error, _T("CDocumentController::GetEventCodesWithAddDocumentationPriv() SafeArray pEventCode is not locked"));
SafeArrayUnlock(*pArrayOfEventCode);
return(E_FAIL);
}
double *pArrayOfElements; // pointer to the elements of the array
// using the array
pArrayOfElements=(double*) (*pArrayOfEventCode)->pvData;
CMap<double,double,bool,bool> mapEventCds;
// number of elements in the array
long lElements=(*pArrayOfEventCode)->rgsabound[0].cElements;
double lVal(0);
for (long lCount=0; lCount<lElements; lCount++)
{
lVal = pArrayOfElements[lCount];
mapEventCds.SetAt(lVal, false);
}
CheckPrivViewResultEventCds(dUserId, dPosCd, dPPRCd, mapEventCds);
SafeArrayUnlock(*pArrayOfEventCode);
lResult = SafeArrayDestroyData(*pArrayOfEventCode);
if (lResult != S_OK)
{
MsgWrite(MSG_DEFAULT, eMsgLog_Commit, _T("PVClinDocMiscCom"), eMsgLvl_Error, _T("CDocumentController::GetEventCodesWithAddDocumentationPriv() SafeArray could not be destroyed"));
return(E_FAIL);
}
SAFEARRAYBOUND rgsabound[1]; //Create a one dimensional array
rgsabound[0].lLbound = (*pArrayOfEventCode)->rgsabound->lLbound; //Set the lowerbound for the array
rgsabound[0].cElements = (*pArrayOfEventCode)->rgsabound->cElements; //Set the upperbound for the array
//Create a new safearray of double to fill from the mapeventcodes
SAFEARRAY* newArray = SafeArrayCreate(VT_R8, 1, rgsabound);
double dEventCd(0.0);
bool bPriv(false);
//Get the starting index of the SafeArray
long lEventCdIdx = (*pArrayOfEventCode)->rgsabound->lLbound;
POSITION pos(mapEventCds.GetStartPosition());
while(pos != NULL)
{
mapEventCds.GetNextAssoc(pos, dEventCd, bPriv);
if (bPriv)
{
lResult = SafeArrayPutElement(newArray, &lEventCdIdx, &dEventCd);
if (lResult != S_OK)
{
MsgWrite(MSG_DEFAULT, eMsgLog_Commit, _T("PVClinDocMiscCom"), eMsgLvl_Debug, _T("CDocumentController::GetEventCodesWithAddDocumentationPriv() Failed to add element to array"));
}
lEventCdIdx++;
}
}
// Empty the CMap
mapEventCds.RemoveAll();
//Copy the contents from new safearray to the existing safearray
SafeArrayCopy(newArray, pArrayOfEventCode);
//Destroy the new safearray
SafeArrayDestroy(newArray);
// releasing the array
return S_OK;
}

Get continuous frames from camera filter when source filter stops sending?

Hi All,
I have a transform filter which takes two inputs, one from camera and other from a file source. Inside my transform filter I am blending the inputs from two sources.
Transform filter is derived from CTransformFilter
class CWMTransformFilter : public CTransformFilter
and extra pin is derived from: CTransformInputPin(which inturn derives from CBaseInputPin)
class CFileInputPin : public CTransformInputPin
In my case what is happening is, if the file source is small (assume 10 secs), I get input from camera also for 10 secs, later camera stops sending frames to the input pin.
So what i now need is :
1. How to inform camera to send frames even when source filter stops sending ?
2. How to restart the source filter when the playing of the source file is stopped? (something like playing file in loop)
Update:
STDMETHODIMP CFileInputPin::EndOfStream()
{
//return CTransformInputPin::EndOfStream();
return S_OK;
}
STDMETHODIMP CFileInputPin::Receive(IMediaSample* pSample)
{
HRESULT hr;
BYTE* pBufferIn;
long lBufferLength, lBufferSize;
hr = CBaseInputPin::Receive(pSample);
if (FAILED(hr))
{
printf("Error !!\n");
return hr;
}
hr = pSample->GetPointer(&pBufferIn);
DWORD stat = WaitForSingleObject(m_pFil->m_QSem,0L);
BOOL bSem = FALSE;
if( WAIT_OBJECT_0 == stat )
{
BYTE *pBuf = (BYTE *) malloc( Wsize*2 );
memcpy(pBuf,pBufferIn,Wsize); //lBufferLength);
sEncodedFrame CurFrame={pBuf,Wsize};
m_pFil->m_Q.push(CurFrame); //push it onto the queue
bSem = ReleaseSemaphore(m_pFil->m_QSem,1,NULL);
if(!bSem)
{
printf("ReleaseSemaphore error: %d \n", GetLastError());
}
return S_OK;
}
else
{
printf("Cant Receive frame 0x%x \n",stat);
return E_FAIL;
}
return S_OK;
}
HRESULT CWMTransformFilter::Transform(IMediaSample *pSource, IMediaSample *pDest)
{
unsigned char r,g,b;
unsigned char y,u,v;
BYTE *pBufferIn, *pBufferOut, *pBuf;
HRESULT hr = pSource->GetPointer(&pBufferIn);
hr = pDest->GetPointer(&pBufferOut);
if (FAILED(hr))
{
return hr;
}
long srclen = pSource->GetActualDataLength();
long dstlen = pDest->GetActualDataLength();
LONG pLastCnt;
BOOL bSem = FALSE;
//printf("Waiting to fill buffer %d\n",pSource);
//return S_OK;
//try
//{
while(1)
{
//if(1)
DWORD ret = WaitForSingleObject(m_QSem,0L);
if(ret != WAIT_OBJECT_0)
{
printf("Get error %d \n",GetLastError());
}
if( WAIT_OBJECT_0 == ret )
{
sEncodedFrame Frame;
if( m_Q.empty() == false )
{
Frame = m_Q.front();
m_Q.pop();
pBuf = (BYTE*) malloc(dstlen*2);
pLastCnt = Frame.iValidSize;
printf("Copy onto queue \n");
memcpy(pBuf,Frame.pFrame,pLastCnt); //Frame.iValidSize);
free(Frame.pFrame);
//delete &Frame;
bSem = ReleaseSemaphore(m_QSem,1,NULL);
if(!bSem)
{
printf("ReleaseSemaphore error: %d \n", GetLastError());
}
hr = S_OK;
break;
}
else
{
bSem = ReleaseSemaphore(m_QSem,1,NULL);
if(!bSem)
{
printf("ReleaseSemaphore error: %d \n", GetLastError());
}
//return S_OK;
hr = E_FAIL;
}
}
else
{
//return S_OK;
hr = E_FAIL;
}
}
for(i = 0; i < windowWidth*2*windowHeight ; i+=4)
{
y = pBufferIn[i];
u = pBufferIn[i+1];
v = pBufferIn[i+3];
r = y + 1.4075 * (v - 128);
g = y - 0.3455 * (u - 128) - (0.7169 * (v - 128));
b = y + 1.7790 * (u - 128);
if(((r > b) &&(g > b)) && (g <= 200) )
{
pBufferIn[i] = pBuf[i];
pBufferIn[i+1] = pBuf[i+1];
pBufferIn[i+2] = pBuf[i+2];
pBufferIn[i+3] = pBuf[i+3];
}
}
// Process the data.
memcpy(pBufferOut,pBufferIn,pSource->GetSize()); //after blend
pDest->SetActualDataLength(pDest->GetSize());
pDest->SetSyncPoint(TRUE);
return S_OK;
}
CFileInputPin::Receive is where I receive samples from file input pin,
CFileInputPin::EndOfStream(), notifies that samples are completed.
CWMTransformFilter::Transform(), is where the samples are given out to the outpin to renderer.
Thanks,
Shyam
There are many tricky things taken into the question.
First of all, the first point of interest is custom dual input filter. Whatever input filters do, this transform filter can rule things out - it solely depends on its implementation whether it is going to allow both input legs stream, or it will block one of it. The common (typical) rule is that if a filter has 2+ inputs, it is either of the two:
One of the streams is master, and the other inputs are either taken into processing if they make sense or they are discarded
The filter blocks input input legs to keep getting data with matching time stamps, then merges streams over the course of its internal processing.
The input streams are typically sequences of samples followed by EOS notification. In particular, a freeze might take place if one of the sources does not send EOS, or transform filter does not process it properly.
The second big issue is seeking. You normally don't seek a part of the graph. However, here it is exactly what you are trying to do. You can try seek the source filter independently locating its own seeking interfaces, or otherwise you can implement a buffer and hold everything it sends and looping this infinitely once source sends EOS. There is no advice on this - you decide what is appropriate in your scenario.
Another option is to split graphs and bridge them so that you could seek/restart source graph the regular way.