ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

interface.cpp
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       See COPYING in the top level directory
00003  * PROJECT:         ReactOS WDM Streaming ActiveMovie Proxy
00004  * FILE:            dll/directx/ksproxy/interface.cpp
00005  * PURPOSE:         IKsInterfaceHandler interface
00006  *
00007  * PROGRAMMERS:     Johannes Anderwald (janderwald@reactos.org)
00008  */
00009 #include "precomp.h"
00010 
00011 const GUID IID_IKsObject           = {0x423c13a2, 0x2070, 0x11d0, {0x9e, 0xf7, 0x00, 0xaa, 0x00, 0xa2, 0x16, 0xa1}};
00012 
00013 class CKsInterfaceHandler : public IKsInterfaceHandler
00014 {
00015 public:
00016     STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
00017 
00018     STDMETHODIMP_(ULONG) AddRef()
00019     {
00020         InterlockedIncrement(&m_Ref);
00021         return m_Ref;
00022     }
00023     STDMETHODIMP_(ULONG) Release()
00024     {
00025         InterlockedDecrement(&m_Ref);
00026 
00027         if (!m_Ref)
00028         {
00029             delete this;
00030             return 0;
00031         }
00032         return m_Ref;
00033     }
00034     HRESULT STDMETHODCALLTYPE KsSetPin(IKsPin *KsPin);
00035     HRESULT STDMETHODCALLTYPE KsProcessMediaSamples(IKsDataTypeHandler *KsDataTypeHandler, IMediaSample** SampleList, PLONG SampleCount, KSIOOPERATION IoOperation, PKSSTREAM_SEGMENT *StreamSegment);
00036     HRESULT STDMETHODCALLTYPE KsCompleteIo(PKSSTREAM_SEGMENT StreamSegment);
00037 
00038     CKsInterfaceHandler() : m_Ref(0), m_Handle(NULL), m_Pin(0) {m_PinName[0] = L'\0';};
00039     virtual ~CKsInterfaceHandler(){};
00040 
00041 protected:
00042     LONG m_Ref;
00043     HANDLE m_Handle;
00044     IKsPinEx * m_Pin;
00045     WCHAR m_PinName[129];
00046 };
00047 
00048 typedef struct
00049 {
00050     KSSTREAM_SEGMENT StreamSegment;
00051     OVERLAPPED Overlapped;
00052     IMediaSample * MediaSample[64];
00053 
00054     ULONG SampleCount;
00055     ULONG ExtendedSize;
00056     PKSSTREAM_HEADER StreamHeader;
00057 }KSSTREAM_SEGMENT_EXT, *PKSSTREAM_SEGMENT_EXT;
00058 
00059 
00060 HRESULT
00061 STDMETHODCALLTYPE
00062 CKsInterfaceHandler::QueryInterface(
00063     IN  REFIID refiid,
00064     OUT PVOID* Output)
00065 {
00066     if (IsEqualGUID(refiid, IID_IUnknown) ||
00067         IsEqualGUID(refiid, IID_IKsInterfaceHandler))
00068     {
00069         *Output = PVOID(this);
00070         reinterpret_cast<IUnknown*>(*Output)->AddRef();
00071         return NOERROR;
00072     }
00073     return E_NOINTERFACE;
00074 }
00075 
00076 HRESULT
00077 STDMETHODCALLTYPE
00078 CKsInterfaceHandler::KsSetPin(
00079     IKsPin *KsPin)
00080 {
00081     HRESULT hr;
00082     IKsObject * KsObject;
00083     IKsPinEx * Pin;
00084 
00085     // get IKsPinEx interface
00086     hr = KsPin->QueryInterface(IID_IKsPinEx, (void**)&Pin);
00087     if (SUCCEEDED(hr))
00088     {
00089         // check if IKsObject is supported
00090         hr = KsPin->QueryInterface(IID_IKsObject, (void**)&KsObject);
00091 
00092         if (SUCCEEDED(hr))
00093         {
00094             // get pin handle
00095             m_Handle = KsObject->KsGetObjectHandle();
00096 
00097             // release IKsObject interface
00098             KsObject->Release();
00099 
00100             if (!m_Handle)
00101             {
00102                 // expected a file handle
00103                 hr = E_UNEXPECTED;
00104                 Pin->Release();
00105             }
00106             else
00107             {
00108                 if (m_Pin)
00109                 {
00110                     // release old interface
00111                     m_Pin->Release();
00112                 }
00113                 m_Pin = Pin;
00114             }
00115         }
00116         else
00117         {
00118             //release IKsPinEx interface
00119             Pin->Release();
00120         }
00121     }
00122 #if 1
00123     //DBG code
00124     PIN_INFO PinInfo;
00125     IPin * pPin;
00126     if (SUCCEEDED(KsPin->QueryInterface(IID_IPin, (void**)&pPin)))
00127     {
00128         if (SUCCEEDED(pPin->QueryPinInfo(&PinInfo)))
00129         {
00130             if (PinInfo.pFilter)
00131                 PinInfo.pFilter->Release();
00132 
00133             wcscpy(m_PinName, PinInfo.achName);
00134         }
00135         pPin->Release();
00136     }
00137 #endif
00138 
00139     // done
00140     return hr;
00141 }
00142 
00143 HRESULT
00144 STDMETHODCALLTYPE
00145 CKsInterfaceHandler::KsProcessMediaSamples(
00146      IKsDataTypeHandler *KsDataTypeHandler,
00147      IMediaSample** SampleList,
00148      PLONG SampleCount,
00149      KSIOOPERATION IoOperation,
00150      PKSSTREAM_SEGMENT *OutStreamSegment)
00151 {
00152     PKSSTREAM_SEGMENT_EXT StreamSegment;
00153     ULONG ExtendedSize, Index, BytesReturned;
00154     HRESULT hr = S_OK;
00155 
00156     // sanity check
00157     assert(*SampleCount);
00158 
00159     if (*SampleCount == 0 || *SampleCount < 0)
00160         return E_FAIL;
00161 
00162     // zero stream segment
00163     *OutStreamSegment = NULL;
00164 
00165     // allocate stream segment
00166     StreamSegment = (PKSSTREAM_SEGMENT_EXT)CoTaskMemAlloc(sizeof(KSSTREAM_SEGMENT_EXT));
00167     if (!StreamSegment)
00168         return E_OUTOFMEMORY;
00169 
00170     // zero stream segment
00171     ZeroMemory(StreamSegment, sizeof(KSSTREAM_SEGMENT_EXT));
00172 
00173     //allocate event
00174     StreamSegment->StreamSegment.CompletionEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
00175 
00176     if (!StreamSegment->StreamSegment.CompletionEvent)
00177     {
00178         // failed to create event
00179         CoTaskMemFree(StreamSegment);
00180         return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
00181     }
00182 
00183     // increase our own reference count
00184     AddRef();
00185 
00186     // setup stream segment
00187     StreamSegment->StreamSegment.KsDataTypeHandler = KsDataTypeHandler;
00188     StreamSegment->StreamSegment.KsInterfaceHandler = (IKsInterfaceHandler*)this;
00189     StreamSegment->StreamSegment.IoOperation = IoOperation;
00190     StreamSegment->Overlapped.hEvent = StreamSegment->StreamSegment.CompletionEvent;
00191 
00192 
00193     // ge extension size
00194     ExtendedSize = 0;
00195     if (KsDataTypeHandler)
00196     {
00197         // query extension size
00198         KsDataTypeHandler->KsQueryExtendedSize(&ExtendedSize);
00199 
00200         if (ExtendedSize)
00201         {
00202             // increment reference count
00203             KsDataTypeHandler->AddRef();
00204         }
00205         else
00206         {
00207             // no need for the datatype handler
00208             StreamSegment->StreamSegment.KsDataTypeHandler = NULL;
00209         }
00210     }
00211 
00212     StreamSegment->ExtendedSize = ExtendedSize;
00213     StreamSegment->SampleCount = (ULONG)*SampleCount;
00214 
00215     // calculate stream header size count
00216     ULONG StreamHeaderSize = StreamSegment->SampleCount * (sizeof(KSSTREAM_HEADER) + ExtendedSize);
00217 
00218     // allocate stream header
00219     StreamSegment->StreamHeader = (PKSSTREAM_HEADER)CoTaskMemAlloc(StreamHeaderSize);
00220     if (!StreamSegment->StreamHeader)
00221     {
00222         // not enough memory
00223         CloseHandle(StreamSegment->StreamSegment.CompletionEvent);
00224 
00225         if (StreamSegment->StreamSegment.KsDataTypeHandler)
00226             StreamSegment->StreamSegment.KsDataTypeHandler->Release();
00227 
00228         // free stream segment
00229         CoTaskMemFree(StreamSegment);
00230 
00231         //release our reference count
00232         Release();
00233         return E_OUTOFMEMORY;
00234     }
00235 
00236     // zero stream headers
00237     ZeroMemory(StreamSegment->StreamHeader, StreamHeaderSize);
00238 
00239     PKSSTREAM_HEADER CurStreamHeader = StreamSegment->StreamHeader;
00240 
00241     // initialize all stream headers
00242     for(Index = 0; Index < StreamSegment->SampleCount; Index++)
00243     {
00244          if (ExtendedSize)
00245          {
00246              // initialize extended size
00247              hr = KsDataTypeHandler->KsPrepareIoOperation(SampleList[Index], (CurStreamHeader + 1), IoOperation);
00248              // sanity check
00249              assert(hr == NOERROR);
00250          }
00251 
00252          // query for IMediaSample2 interface
00253          IMediaSample2 * MediaSample;
00254          AM_SAMPLE2_PROPERTIES Properties;
00255          ZeroMemory(&Properties, sizeof(AM_SAMPLE2_PROPERTIES));
00256 
00257          hr = SampleList[Index]->QueryInterface(IID_IMediaSample2, (void**)&MediaSample);
00258          if (SUCCEEDED(hr))
00259          {
00260              //get properties
00261 
00262              hr = MediaSample->GetProperties(sizeof(AM_SAMPLE2_PROPERTIES), (BYTE*)&Properties);
00263 
00264              //release IMediaSample2 interface
00265              MediaSample->Release();
00266          }
00267          else
00268          {
00269              // get properties
00270              hr = SampleList[Index]->GetPointer((BYTE**)&Properties.pbBuffer);
00271              assert(hr == NOERROR);
00272              hr = SampleList[Index]->GetTime(&Properties.tStart, &Properties.tStop);
00273 
00274              Properties.cbBuffer = SampleList[Index]->GetSize();
00275              assert(Properties.cbBuffer);
00276 
00277              Properties.dwSampleFlags = 0;
00278 
00279              if (SampleList[Index]->IsDiscontinuity() == S_OK)
00280                  Properties.dwSampleFlags |= AM_SAMPLE_DATADISCONTINUITY;
00281 
00282              if (SampleList[Index]->IsPreroll() == S_OK)
00283                  Properties.dwSampleFlags |= AM_SAMPLE_PREROLL;
00284 
00285              if (SampleList[Index]->IsSyncPoint() == S_OK)
00286                  Properties.dwSampleFlags |= AM_SAMPLE_SPLICEPOINT;
00287          }
00288 #ifdef KSPROXY_TRACE
00289          WCHAR Buffer[200];
00290          swprintf(Buffer, L"CKsInterfaceHandler::KsProcessMediaSamples PinName %s BufferLength %lu Property Buffer %p ExtendedSize %u lActual %u dwSampleFlags %lx\n", m_PinName, Properties.cbBuffer, Properties.pbBuffer, ExtendedSize, Properties.lActual, Properties.dwSampleFlags);
00291          OutputDebugStringW(Buffer);
00292 #endif
00293 
00294          CurStreamHeader->Size = sizeof(KSSTREAM_HEADER) + ExtendedSize;
00295          CurStreamHeader->PresentationTime.Denominator = 1;
00296          CurStreamHeader->PresentationTime.Numerator = 1;
00297          CurStreamHeader->FrameExtent = Properties.cbBuffer;
00298          CurStreamHeader->Data = Properties.pbBuffer;
00299 
00300          if (IoOperation == KsIoOperation_Write)
00301          {
00302              // set flags
00303              CurStreamHeader->OptionsFlags = Properties.dwSampleFlags;
00304              CurStreamHeader->DataUsed = Properties.lActual;
00305              // increment reference count
00306              SampleList[Index]->AddRef();
00307          }
00308 
00309          // store sample in stream segment
00310          StreamSegment->MediaSample[Index] = SampleList[Index];
00311 
00312          // move to next header
00313          CurStreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)CurStreamHeader + CurStreamHeader->Size);
00314     }
00315 
00316     // submit to device
00317     m_Pin->KsIncrementPendingIoCount();
00318 
00319     if (DeviceIoControl(m_Handle,
00320                         IoOperation == KsIoOperation_Write ? IOCTL_KS_WRITE_STREAM : IOCTL_KS_READ_STREAM,
00321                         NULL, 0,
00322                         StreamSegment->StreamHeader,
00323                         StreamHeaderSize,
00324                         &BytesReturned,
00325                         &StreamSegment->Overlapped))
00326     {
00327         // signal completion
00328         SetEvent(StreamSegment->StreamSegment.CompletionEvent);
00329         hr = S_OK;
00330         *OutStreamSegment = (PKSSTREAM_SEGMENT)StreamSegment;
00331     }
00332     else
00333     {
00334         if (GetLastError() == ERROR_IO_PENDING)
00335         {
00336             *OutStreamSegment = (PKSSTREAM_SEGMENT)StreamSegment;
00337             hr = S_OK;
00338         }
00339     }
00340     return hr;
00341 }
00342 
00343 HRESULT
00344 STDMETHODCALLTYPE
00345 CKsInterfaceHandler::KsCompleteIo(
00346     PKSSTREAM_SEGMENT InStreamSegment)
00347 {
00348     PKSSTREAM_SEGMENT_EXT StreamSegment;
00349     PKSSTREAM_HEADER CurStreamHeader;
00350     DWORD dwError = ERROR_SUCCESS, BytesReturned;
00351     BOOL bOverlapped;
00352     ULONG Index;
00353     HRESULT hr;
00354     IMediaSample2 * MediaSample;
00355     AM_SAMPLE2_PROPERTIES Properties;
00356     REFERENCE_TIME Start, Stop;
00357 
00358     // get private stream segment
00359     StreamSegment = (PKSSTREAM_SEGMENT_EXT)InStreamSegment;
00360 
00361     // get result
00362     bOverlapped = GetOverlappedResult(m_Handle, &StreamSegment->Overlapped, &BytesReturned, FALSE);
00363     dwError = GetLastError();
00364 
00365     CurStreamHeader = StreamSegment->StreamHeader;
00366 
00367     //iterate through all stream headers
00368     for(Index = 0; Index < StreamSegment->SampleCount; Index++)
00369     {
00370         if (!bOverlapped)
00371         {
00372             // operation failed
00373             m_Pin->KsNotifyError(StreamSegment->MediaSample[Index], MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, dwError));
00374         }
00375 
00376         // query IMediaSample2 interface
00377         hr = StreamSegment->MediaSample[Index]->QueryInterface(IID_IMediaSample2, (void**)&MediaSample);
00378         if (SUCCEEDED(hr))
00379         {
00380             // media sample properties
00381             hr = MediaSample->GetProperties(sizeof(AM_SAMPLE2_PROPERTIES), (BYTE*)&Properties);
00382             if (SUCCEEDED(hr))
00383             {
00384                 //update media sample properties
00385                 Properties.dwTypeSpecificFlags = CurStreamHeader->TypeSpecificFlags;
00386                 Properties.dwSampleFlags |= (CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TIMEDISCONTINUITY);
00387 
00388                 MediaSample->SetProperties(sizeof(AM_SAMPLE2_PROPERTIES), (BYTE*)&Properties);
00389             }
00390             // release IMediaSample2 interface
00391             MediaSample->Release();
00392         }
00393 
00394         // was an extended header used
00395         if (StreamSegment->ExtendedSize)
00396         {
00397             // unprepare stream header extension
00398             StreamSegment->StreamSegment.KsDataTypeHandler->KsCompleteIoOperation(StreamSegment->MediaSample[Index], (CurStreamHeader + 1), StreamSegment->StreamSegment.IoOperation, bOverlapped == FALSE);
00399         }
00400 
00401         Start = 0;
00402         Stop = 0;
00403         if (bOverlapped && StreamSegment->StreamSegment.IoOperation == KsIoOperation_Read)
00404         {
00405             // update common media sample details
00406             StreamSegment->MediaSample[Index]->SetSyncPoint((CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_SPLICEPOINT));
00407             StreamSegment->MediaSample[Index]->SetPreroll((CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_PREROLL));
00408             StreamSegment->MediaSample[Index]->SetDiscontinuity((CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY));
00409 
00410             if (CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TIMEVALID)
00411             {
00412                 // use valid timestamp
00413                 Start = CurStreamHeader->PresentationTime.Time;
00414 
00415                 if (CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_DURATIONVALID)
00416                 {
00417                     Stop = CurStreamHeader->PresentationTime.Time + CurStreamHeader->Duration;
00418                 }
00419             }
00420         }
00421 
00422         // now set time
00423         hr = StreamSegment->MediaSample[Index]->SetTime(&Start, &Stop);
00424         if (FAILED(hr))
00425         {
00426             // use start time
00427             StreamSegment->MediaSample[Index]->SetTime(&Start, &Start);
00428         }
00429 
00430         // set valid data length
00431         StreamSegment->MediaSample[Index]->SetActualDataLength(CurStreamHeader->DataUsed);
00432 
00433         if (StreamSegment->StreamSegment.IoOperation == KsIoOperation_Read)
00434         {
00435             if (bOverlapped)
00436             {
00437                 // deliver sample
00438                 m_Pin->KsDeliver(StreamSegment->MediaSample[Index], CurStreamHeader->OptionsFlags);
00439             }
00440         }
00441         else if (StreamSegment->StreamSegment.IoOperation == KsIoOperation_Write)
00442         {
00443             // release media sample reference
00444             StreamSegment->MediaSample[Index]->Release();
00445         }
00446 
00447         CurStreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)CurStreamHeader + CurStreamHeader->Size);
00448     }
00449 
00450     // delete stream headers
00451     CoTaskMemFree(StreamSegment->StreamHeader);
00452 
00453     if (StreamSegment->StreamSegment.KsDataTypeHandler)
00454     {
00455         // release reference
00456         StreamSegment->StreamSegment.KsDataTypeHandler->Release();
00457     }
00458 
00459     // decrement pending i/o count
00460     m_Pin->KsDecrementPendingIoCount();
00461 
00462     //notify of completion
00463     m_Pin->KsMediaSamplesCompleted(InStreamSegment);
00464 
00465     //destroy stream segment
00466     CoTaskMemFree(StreamSegment);
00467 
00468     //release reference to ourselves
00469     Release();
00470 
00471     // done
00472     // Event handle is closed by caller
00473     return S_OK;
00474 }
00475 
00476 HRESULT
00477 WINAPI
00478 CKsInterfaceHandler_Constructor(
00479     IUnknown * pUnkOuter,
00480     REFIID riid,
00481     LPVOID * ppv)
00482 {
00483 #ifdef KSPROXY_TRACE
00484     OutputDebugStringW(L"CKsInterfaceHandler_Constructor\n");
00485 #endif
00486 
00487     CKsInterfaceHandler * handler = new CKsInterfaceHandler();
00488 
00489     if (!handler)
00490         return E_OUTOFMEMORY;
00491 
00492     if (FAILED(handler->QueryInterface(riid, ppv)))
00493     {
00494         /* not supported */
00495         delete handler;
00496         return E_NOINTERFACE;
00497     }
00498 
00499     return NOERROR;
00500 }

Generated on Sun May 27 2012 04:21:51 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.