xref: /reactos/dll/directx/ksproxy/interface.cpp (revision c2c66aff)
1*c2c66affSColin Finck /*
2*c2c66affSColin Finck  * COPYRIGHT:       See COPYING in the top level directory
3*c2c66affSColin Finck  * PROJECT:         ReactOS WDM Streaming ActiveMovie Proxy
4*c2c66affSColin Finck  * FILE:            dll/directx/ksproxy/interface.cpp
5*c2c66affSColin Finck  * PURPOSE:         IKsInterfaceHandler interface
6*c2c66affSColin Finck  *
7*c2c66affSColin Finck  * PROGRAMMERS:     Johannes Anderwald (johannes.anderwald@reactos.org)
8*c2c66affSColin Finck  */
9*c2c66affSColin Finck #include "precomp.h"
10*c2c66affSColin Finck 
11*c2c66affSColin Finck const GUID IID_IKsObject           = {0x423c13a2, 0x2070, 0x11d0, {0x9e, 0xf7, 0x00, 0xaa, 0x00, 0xa2, 0x16, 0xa1}};
12*c2c66affSColin Finck 
13*c2c66affSColin Finck class CKsInterfaceHandler : public IKsInterfaceHandler
14*c2c66affSColin Finck {
15*c2c66affSColin Finck public:
16*c2c66affSColin Finck     STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
17*c2c66affSColin Finck 
AddRef()18*c2c66affSColin Finck     STDMETHODIMP_(ULONG) AddRef()
19*c2c66affSColin Finck     {
20*c2c66affSColin Finck         InterlockedIncrement(&m_Ref);
21*c2c66affSColin Finck         return m_Ref;
22*c2c66affSColin Finck     }
Release()23*c2c66affSColin Finck     STDMETHODIMP_(ULONG) Release()
24*c2c66affSColin Finck     {
25*c2c66affSColin Finck         InterlockedDecrement(&m_Ref);
26*c2c66affSColin Finck 
27*c2c66affSColin Finck         if (!m_Ref)
28*c2c66affSColin Finck         {
29*c2c66affSColin Finck             delete this;
30*c2c66affSColin Finck             return 0;
31*c2c66affSColin Finck         }
32*c2c66affSColin Finck         return m_Ref;
33*c2c66affSColin Finck     }
34*c2c66affSColin Finck     HRESULT STDMETHODCALLTYPE KsSetPin(IKsPin *KsPin);
35*c2c66affSColin Finck     HRESULT STDMETHODCALLTYPE KsProcessMediaSamples(IKsDataTypeHandler *KsDataTypeHandler, IMediaSample** SampleList, PLONG SampleCount, KSIOOPERATION IoOperation, PKSSTREAM_SEGMENT *StreamSegment);
36*c2c66affSColin Finck     HRESULT STDMETHODCALLTYPE KsCompleteIo(PKSSTREAM_SEGMENT StreamSegment);
37*c2c66affSColin Finck 
CKsInterfaceHandler()38*c2c66affSColin Finck     CKsInterfaceHandler() : m_Ref(0), m_Handle(NULL), m_Pin(0) {m_PinName[0] = L'\0';};
~CKsInterfaceHandler()39*c2c66affSColin Finck     virtual ~CKsInterfaceHandler(){};
40*c2c66affSColin Finck 
41*c2c66affSColin Finck protected:
42*c2c66affSColin Finck     LONG m_Ref;
43*c2c66affSColin Finck     HANDLE m_Handle;
44*c2c66affSColin Finck     IKsPinEx * m_Pin;
45*c2c66affSColin Finck     WCHAR m_PinName[129];
46*c2c66affSColin Finck };
47*c2c66affSColin Finck 
48*c2c66affSColin Finck typedef struct
49*c2c66affSColin Finck {
50*c2c66affSColin Finck     KSSTREAM_SEGMENT StreamSegment;
51*c2c66affSColin Finck     OVERLAPPED Overlapped;
52*c2c66affSColin Finck     IMediaSample * MediaSample[64];
53*c2c66affSColin Finck 
54*c2c66affSColin Finck     ULONG SampleCount;
55*c2c66affSColin Finck     ULONG ExtendedSize;
56*c2c66affSColin Finck     PKSSTREAM_HEADER StreamHeader;
57*c2c66affSColin Finck }KSSTREAM_SEGMENT_EXT, *PKSSTREAM_SEGMENT_EXT;
58*c2c66affSColin Finck 
59*c2c66affSColin Finck 
60*c2c66affSColin Finck HRESULT
61*c2c66affSColin Finck STDMETHODCALLTYPE
QueryInterface(IN REFIID refiid,OUT PVOID * Output)62*c2c66affSColin Finck CKsInterfaceHandler::QueryInterface(
63*c2c66affSColin Finck     IN  REFIID refiid,
64*c2c66affSColin Finck     OUT PVOID* Output)
65*c2c66affSColin Finck {
66*c2c66affSColin Finck     if (IsEqualGUID(refiid, IID_IUnknown) ||
67*c2c66affSColin Finck         IsEqualGUID(refiid, IID_IKsInterfaceHandler))
68*c2c66affSColin Finck     {
69*c2c66affSColin Finck         *Output = PVOID(this);
70*c2c66affSColin Finck         reinterpret_cast<IUnknown*>(*Output)->AddRef();
71*c2c66affSColin Finck         return NOERROR;
72*c2c66affSColin Finck     }
73*c2c66affSColin Finck     return E_NOINTERFACE;
74*c2c66affSColin Finck }
75*c2c66affSColin Finck 
76*c2c66affSColin Finck HRESULT
77*c2c66affSColin Finck STDMETHODCALLTYPE
KsSetPin(IKsPin * KsPin)78*c2c66affSColin Finck CKsInterfaceHandler::KsSetPin(
79*c2c66affSColin Finck     IKsPin *KsPin)
80*c2c66affSColin Finck {
81*c2c66affSColin Finck     HRESULT hr;
82*c2c66affSColin Finck     IKsObject * KsObject;
83*c2c66affSColin Finck     IKsPinEx * Pin;
84*c2c66affSColin Finck 
85*c2c66affSColin Finck     // get IKsPinEx interface
86*c2c66affSColin Finck     hr = KsPin->QueryInterface(IID_IKsPinEx, (void**)&Pin);
87*c2c66affSColin Finck     if (SUCCEEDED(hr))
88*c2c66affSColin Finck     {
89*c2c66affSColin Finck         // check if IKsObject is supported
90*c2c66affSColin Finck         hr = KsPin->QueryInterface(IID_IKsObject, (void**)&KsObject);
91*c2c66affSColin Finck 
92*c2c66affSColin Finck         if (SUCCEEDED(hr))
93*c2c66affSColin Finck         {
94*c2c66affSColin Finck             // get pin handle
95*c2c66affSColin Finck             m_Handle = KsObject->KsGetObjectHandle();
96*c2c66affSColin Finck 
97*c2c66affSColin Finck             // release IKsObject interface
98*c2c66affSColin Finck             KsObject->Release();
99*c2c66affSColin Finck 
100*c2c66affSColin Finck             if (!m_Handle)
101*c2c66affSColin Finck             {
102*c2c66affSColin Finck                 // expected a file handle
103*c2c66affSColin Finck                 hr = E_UNEXPECTED;
104*c2c66affSColin Finck                 Pin->Release();
105*c2c66affSColin Finck             }
106*c2c66affSColin Finck             else
107*c2c66affSColin Finck             {
108*c2c66affSColin Finck                 if (m_Pin)
109*c2c66affSColin Finck                 {
110*c2c66affSColin Finck                     // release old interface
111*c2c66affSColin Finck                     m_Pin->Release();
112*c2c66affSColin Finck                 }
113*c2c66affSColin Finck                 m_Pin = Pin;
114*c2c66affSColin Finck             }
115*c2c66affSColin Finck         }
116*c2c66affSColin Finck         else
117*c2c66affSColin Finck         {
118*c2c66affSColin Finck             //release IKsPinEx interface
119*c2c66affSColin Finck             Pin->Release();
120*c2c66affSColin Finck         }
121*c2c66affSColin Finck     }
122*c2c66affSColin Finck #if 1
123*c2c66affSColin Finck     //DBG code
124*c2c66affSColin Finck     PIN_INFO PinInfo;
125*c2c66affSColin Finck     IPin * pPin;
126*c2c66affSColin Finck     if (SUCCEEDED(KsPin->QueryInterface(IID_IPin, (void**)&pPin)))
127*c2c66affSColin Finck     {
128*c2c66affSColin Finck         if (SUCCEEDED(pPin->QueryPinInfo(&PinInfo)))
129*c2c66affSColin Finck         {
130*c2c66affSColin Finck             if (PinInfo.pFilter)
131*c2c66affSColin Finck                 PinInfo.pFilter->Release();
132*c2c66affSColin Finck 
133*c2c66affSColin Finck             wcscpy(m_PinName, PinInfo.achName);
134*c2c66affSColin Finck         }
135*c2c66affSColin Finck         pPin->Release();
136*c2c66affSColin Finck     }
137*c2c66affSColin Finck #endif
138*c2c66affSColin Finck 
139*c2c66affSColin Finck     // done
140*c2c66affSColin Finck     return hr;
141*c2c66affSColin Finck }
142*c2c66affSColin Finck 
143*c2c66affSColin Finck HRESULT
144*c2c66affSColin Finck STDMETHODCALLTYPE
KsProcessMediaSamples(IKsDataTypeHandler * KsDataTypeHandler,IMediaSample ** SampleList,PLONG SampleCount,KSIOOPERATION IoOperation,PKSSTREAM_SEGMENT * OutStreamSegment)145*c2c66affSColin Finck CKsInterfaceHandler::KsProcessMediaSamples(
146*c2c66affSColin Finck      IKsDataTypeHandler *KsDataTypeHandler,
147*c2c66affSColin Finck      IMediaSample** SampleList,
148*c2c66affSColin Finck      PLONG SampleCount,
149*c2c66affSColin Finck      KSIOOPERATION IoOperation,
150*c2c66affSColin Finck      PKSSTREAM_SEGMENT *OutStreamSegment)
151*c2c66affSColin Finck {
152*c2c66affSColin Finck     PKSSTREAM_SEGMENT_EXT StreamSegment;
153*c2c66affSColin Finck     ULONG ExtendedSize, Index, BytesReturned;
154*c2c66affSColin Finck     HRESULT hr = S_OK;
155*c2c66affSColin Finck 
156*c2c66affSColin Finck     // sanity check
157*c2c66affSColin Finck     assert(*SampleCount);
158*c2c66affSColin Finck 
159*c2c66affSColin Finck     if (*SampleCount == 0 || *SampleCount < 0)
160*c2c66affSColin Finck         return E_FAIL;
161*c2c66affSColin Finck 
162*c2c66affSColin Finck     // zero stream segment
163*c2c66affSColin Finck     *OutStreamSegment = NULL;
164*c2c66affSColin Finck 
165*c2c66affSColin Finck     // allocate stream segment
166*c2c66affSColin Finck     StreamSegment = (PKSSTREAM_SEGMENT_EXT)CoTaskMemAlloc(sizeof(KSSTREAM_SEGMENT_EXT));
167*c2c66affSColin Finck     if (!StreamSegment)
168*c2c66affSColin Finck         return E_OUTOFMEMORY;
169*c2c66affSColin Finck 
170*c2c66affSColin Finck     // zero stream segment
171*c2c66affSColin Finck     ZeroMemory(StreamSegment, sizeof(KSSTREAM_SEGMENT_EXT));
172*c2c66affSColin Finck 
173*c2c66affSColin Finck     //allocate event
174*c2c66affSColin Finck     StreamSegment->StreamSegment.CompletionEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
175*c2c66affSColin Finck 
176*c2c66affSColin Finck     if (!StreamSegment->StreamSegment.CompletionEvent)
177*c2c66affSColin Finck     {
178*c2c66affSColin Finck         // failed to create event
179*c2c66affSColin Finck         CoTaskMemFree(StreamSegment);
180*c2c66affSColin Finck         return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
181*c2c66affSColin Finck     }
182*c2c66affSColin Finck 
183*c2c66affSColin Finck     // increase our own reference count
184*c2c66affSColin Finck     AddRef();
185*c2c66affSColin Finck 
186*c2c66affSColin Finck     // setup stream segment
187*c2c66affSColin Finck     StreamSegment->StreamSegment.KsDataTypeHandler = KsDataTypeHandler;
188*c2c66affSColin Finck     StreamSegment->StreamSegment.KsInterfaceHandler = (IKsInterfaceHandler*)this;
189*c2c66affSColin Finck     StreamSegment->StreamSegment.IoOperation = IoOperation;
190*c2c66affSColin Finck     StreamSegment->Overlapped.hEvent = StreamSegment->StreamSegment.CompletionEvent;
191*c2c66affSColin Finck 
192*c2c66affSColin Finck 
193*c2c66affSColin Finck     // ge extension size
194*c2c66affSColin Finck     ExtendedSize = 0;
195*c2c66affSColin Finck     if (KsDataTypeHandler)
196*c2c66affSColin Finck     {
197*c2c66affSColin Finck         // query extension size
198*c2c66affSColin Finck         KsDataTypeHandler->KsQueryExtendedSize(&ExtendedSize);
199*c2c66affSColin Finck 
200*c2c66affSColin Finck         if (ExtendedSize)
201*c2c66affSColin Finck         {
202*c2c66affSColin Finck             // increment reference count
203*c2c66affSColin Finck             KsDataTypeHandler->AddRef();
204*c2c66affSColin Finck         }
205*c2c66affSColin Finck         else
206*c2c66affSColin Finck         {
207*c2c66affSColin Finck             // no need for the datatype handler
208*c2c66affSColin Finck             StreamSegment->StreamSegment.KsDataTypeHandler = NULL;
209*c2c66affSColin Finck         }
210*c2c66affSColin Finck     }
211*c2c66affSColin Finck 
212*c2c66affSColin Finck     StreamSegment->ExtendedSize = ExtendedSize;
213*c2c66affSColin Finck     StreamSegment->SampleCount = (ULONG)*SampleCount;
214*c2c66affSColin Finck 
215*c2c66affSColin Finck     // calculate stream header size count
216*c2c66affSColin Finck     ULONG StreamHeaderSize = StreamSegment->SampleCount * (sizeof(KSSTREAM_HEADER) + ExtendedSize);
217*c2c66affSColin Finck 
218*c2c66affSColin Finck     // allocate stream header
219*c2c66affSColin Finck     StreamSegment->StreamHeader = (PKSSTREAM_HEADER)CoTaskMemAlloc(StreamHeaderSize);
220*c2c66affSColin Finck     if (!StreamSegment->StreamHeader)
221*c2c66affSColin Finck     {
222*c2c66affSColin Finck         // not enough memory
223*c2c66affSColin Finck         CloseHandle(StreamSegment->StreamSegment.CompletionEvent);
224*c2c66affSColin Finck 
225*c2c66affSColin Finck         if (StreamSegment->StreamSegment.KsDataTypeHandler)
226*c2c66affSColin Finck             StreamSegment->StreamSegment.KsDataTypeHandler->Release();
227*c2c66affSColin Finck 
228*c2c66affSColin Finck         // free stream segment
229*c2c66affSColin Finck         CoTaskMemFree(StreamSegment);
230*c2c66affSColin Finck 
231*c2c66affSColin Finck         //release our reference count
232*c2c66affSColin Finck         Release();
233*c2c66affSColin Finck         return E_OUTOFMEMORY;
234*c2c66affSColin Finck     }
235*c2c66affSColin Finck 
236*c2c66affSColin Finck     // zero stream headers
237*c2c66affSColin Finck     ZeroMemory(StreamSegment->StreamHeader, StreamHeaderSize);
238*c2c66affSColin Finck 
239*c2c66affSColin Finck     PKSSTREAM_HEADER CurStreamHeader = StreamSegment->StreamHeader;
240*c2c66affSColin Finck 
241*c2c66affSColin Finck     // initialize all stream headers
242*c2c66affSColin Finck     for(Index = 0; Index < StreamSegment->SampleCount; Index++)
243*c2c66affSColin Finck     {
244*c2c66affSColin Finck          if (ExtendedSize)
245*c2c66affSColin Finck          {
246*c2c66affSColin Finck              // initialize extended size
247*c2c66affSColin Finck              hr = KsDataTypeHandler->KsPrepareIoOperation(SampleList[Index], (CurStreamHeader + 1), IoOperation);
248*c2c66affSColin Finck              // sanity check
249*c2c66affSColin Finck              assert(hr == NOERROR);
250*c2c66affSColin Finck          }
251*c2c66affSColin Finck 
252*c2c66affSColin Finck          // query for IMediaSample2 interface
253*c2c66affSColin Finck          IMediaSample2 * MediaSample;
254*c2c66affSColin Finck          AM_SAMPLE2_PROPERTIES Properties;
255*c2c66affSColin Finck          ZeroMemory(&Properties, sizeof(AM_SAMPLE2_PROPERTIES));
256*c2c66affSColin Finck 
257*c2c66affSColin Finck          hr = SampleList[Index]->QueryInterface(IID_IMediaSample2, (void**)&MediaSample);
258*c2c66affSColin Finck          if (SUCCEEDED(hr))
259*c2c66affSColin Finck          {
260*c2c66affSColin Finck              //get properties
261*c2c66affSColin Finck 
262*c2c66affSColin Finck              hr = MediaSample->GetProperties(sizeof(AM_SAMPLE2_PROPERTIES), (BYTE*)&Properties);
263*c2c66affSColin Finck 
264*c2c66affSColin Finck              //release IMediaSample2 interface
265*c2c66affSColin Finck              MediaSample->Release();
266*c2c66affSColin Finck          }
267*c2c66affSColin Finck          else
268*c2c66affSColin Finck          {
269*c2c66affSColin Finck              // get properties
270*c2c66affSColin Finck              hr = SampleList[Index]->GetPointer((BYTE**)&Properties.pbBuffer);
271*c2c66affSColin Finck              assert(hr == NOERROR);
272*c2c66affSColin Finck              hr = SampleList[Index]->GetTime(&Properties.tStart, &Properties.tStop);
273*c2c66affSColin Finck 
274*c2c66affSColin Finck              Properties.cbBuffer = SampleList[Index]->GetSize();
275*c2c66affSColin Finck              assert(Properties.cbBuffer);
276*c2c66affSColin Finck 
277*c2c66affSColin Finck              Properties.dwSampleFlags = 0;
278*c2c66affSColin Finck 
279*c2c66affSColin Finck              if (SampleList[Index]->IsDiscontinuity() == S_OK)
280*c2c66affSColin Finck                  Properties.dwSampleFlags |= AM_SAMPLE_DATADISCONTINUITY;
281*c2c66affSColin Finck 
282*c2c66affSColin Finck              if (SampleList[Index]->IsPreroll() == S_OK)
283*c2c66affSColin Finck                  Properties.dwSampleFlags |= AM_SAMPLE_PREROLL;
284*c2c66affSColin Finck 
285*c2c66affSColin Finck              if (SampleList[Index]->IsSyncPoint() == S_OK)
286*c2c66affSColin Finck                  Properties.dwSampleFlags |= AM_SAMPLE_SPLICEPOINT;
287*c2c66affSColin Finck          }
288*c2c66affSColin Finck #ifdef KSPROXY_TRACE
289*c2c66affSColin Finck          WCHAR Buffer[200];
290*c2c66affSColin Finck          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);
291*c2c66affSColin Finck          OutputDebugStringW(Buffer);
292*c2c66affSColin Finck #endif
293*c2c66affSColin Finck 
294*c2c66affSColin Finck          CurStreamHeader->Size = sizeof(KSSTREAM_HEADER) + ExtendedSize;
295*c2c66affSColin Finck          CurStreamHeader->PresentationTime.Denominator = 1;
296*c2c66affSColin Finck          CurStreamHeader->PresentationTime.Numerator = 1;
297*c2c66affSColin Finck          CurStreamHeader->FrameExtent = Properties.cbBuffer;
298*c2c66affSColin Finck          CurStreamHeader->Data = Properties.pbBuffer;
299*c2c66affSColin Finck 
300*c2c66affSColin Finck          if (IoOperation == KsIoOperation_Write)
301*c2c66affSColin Finck          {
302*c2c66affSColin Finck              // set flags
303*c2c66affSColin Finck              CurStreamHeader->OptionsFlags = Properties.dwSampleFlags;
304*c2c66affSColin Finck              CurStreamHeader->DataUsed = Properties.lActual;
305*c2c66affSColin Finck              // increment reference count
306*c2c66affSColin Finck              SampleList[Index]->AddRef();
307*c2c66affSColin Finck          }
308*c2c66affSColin Finck 
309*c2c66affSColin Finck          // store sample in stream segment
310*c2c66affSColin Finck          StreamSegment->MediaSample[Index] = SampleList[Index];
311*c2c66affSColin Finck 
312*c2c66affSColin Finck          // move to next header
313*c2c66affSColin Finck          CurStreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)CurStreamHeader + CurStreamHeader->Size);
314*c2c66affSColin Finck     }
315*c2c66affSColin Finck 
316*c2c66affSColin Finck     // submit to device
317*c2c66affSColin Finck     m_Pin->KsIncrementPendingIoCount();
318*c2c66affSColin Finck 
319*c2c66affSColin Finck     if (DeviceIoControl(m_Handle,
320*c2c66affSColin Finck                         IoOperation == KsIoOperation_Write ? IOCTL_KS_WRITE_STREAM : IOCTL_KS_READ_STREAM,
321*c2c66affSColin Finck                         NULL, 0,
322*c2c66affSColin Finck                         StreamSegment->StreamHeader,
323*c2c66affSColin Finck                         StreamHeaderSize,
324*c2c66affSColin Finck                         &BytesReturned,
325*c2c66affSColin Finck                         &StreamSegment->Overlapped))
326*c2c66affSColin Finck     {
327*c2c66affSColin Finck         // signal completion
328*c2c66affSColin Finck         SetEvent(StreamSegment->StreamSegment.CompletionEvent);
329*c2c66affSColin Finck         hr = S_OK;
330*c2c66affSColin Finck         *OutStreamSegment = (PKSSTREAM_SEGMENT)StreamSegment;
331*c2c66affSColin Finck     }
332*c2c66affSColin Finck     else
333*c2c66affSColin Finck     {
334*c2c66affSColin Finck         if (GetLastError() == ERROR_IO_PENDING)
335*c2c66affSColin Finck         {
336*c2c66affSColin Finck             *OutStreamSegment = (PKSSTREAM_SEGMENT)StreamSegment;
337*c2c66affSColin Finck             hr = S_OK;
338*c2c66affSColin Finck         }
339*c2c66affSColin Finck     }
340*c2c66affSColin Finck     return hr;
341*c2c66affSColin Finck }
342*c2c66affSColin Finck 
343*c2c66affSColin Finck HRESULT
344*c2c66affSColin Finck STDMETHODCALLTYPE
KsCompleteIo(PKSSTREAM_SEGMENT InStreamSegment)345*c2c66affSColin Finck CKsInterfaceHandler::KsCompleteIo(
346*c2c66affSColin Finck     PKSSTREAM_SEGMENT InStreamSegment)
347*c2c66affSColin Finck {
348*c2c66affSColin Finck     PKSSTREAM_SEGMENT_EXT StreamSegment;
349*c2c66affSColin Finck     PKSSTREAM_HEADER CurStreamHeader;
350*c2c66affSColin Finck     DWORD dwError = ERROR_SUCCESS, BytesReturned;
351*c2c66affSColin Finck     BOOL bOverlapped;
352*c2c66affSColin Finck     ULONG Index;
353*c2c66affSColin Finck     HRESULT hr;
354*c2c66affSColin Finck     IMediaSample2 * MediaSample;
355*c2c66affSColin Finck     AM_SAMPLE2_PROPERTIES Properties;
356*c2c66affSColin Finck     REFERENCE_TIME Start, Stop;
357*c2c66affSColin Finck 
358*c2c66affSColin Finck     // get private stream segment
359*c2c66affSColin Finck     StreamSegment = (PKSSTREAM_SEGMENT_EXT)InStreamSegment;
360*c2c66affSColin Finck 
361*c2c66affSColin Finck     // get result
362*c2c66affSColin Finck     bOverlapped = GetOverlappedResult(m_Handle, &StreamSegment->Overlapped, &BytesReturned, FALSE);
363*c2c66affSColin Finck     dwError = GetLastError();
364*c2c66affSColin Finck 
365*c2c66affSColin Finck     CurStreamHeader = StreamSegment->StreamHeader;
366*c2c66affSColin Finck 
367*c2c66affSColin Finck     //iterate through all stream headers
368*c2c66affSColin Finck     for(Index = 0; Index < StreamSegment->SampleCount; Index++)
369*c2c66affSColin Finck     {
370*c2c66affSColin Finck         if (!bOverlapped)
371*c2c66affSColin Finck         {
372*c2c66affSColin Finck             // operation failed
373*c2c66affSColin Finck             m_Pin->KsNotifyError(StreamSegment->MediaSample[Index], MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, dwError));
374*c2c66affSColin Finck         }
375*c2c66affSColin Finck 
376*c2c66affSColin Finck         // query IMediaSample2 interface
377*c2c66affSColin Finck         hr = StreamSegment->MediaSample[Index]->QueryInterface(IID_IMediaSample2, (void**)&MediaSample);
378*c2c66affSColin Finck         if (SUCCEEDED(hr))
379*c2c66affSColin Finck         {
380*c2c66affSColin Finck             // media sample properties
381*c2c66affSColin Finck             hr = MediaSample->GetProperties(sizeof(AM_SAMPLE2_PROPERTIES), (BYTE*)&Properties);
382*c2c66affSColin Finck             if (SUCCEEDED(hr))
383*c2c66affSColin Finck             {
384*c2c66affSColin Finck                 //update media sample properties
385*c2c66affSColin Finck                 Properties.dwTypeSpecificFlags = CurStreamHeader->TypeSpecificFlags;
386*c2c66affSColin Finck                 Properties.dwSampleFlags |= (CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TIMEDISCONTINUITY);
387*c2c66affSColin Finck 
388*c2c66affSColin Finck                 MediaSample->SetProperties(sizeof(AM_SAMPLE2_PROPERTIES), (BYTE*)&Properties);
389*c2c66affSColin Finck             }
390*c2c66affSColin Finck             // release IMediaSample2 interface
391*c2c66affSColin Finck             MediaSample->Release();
392*c2c66affSColin Finck         }
393*c2c66affSColin Finck 
394*c2c66affSColin Finck         // was an extended header used
395*c2c66affSColin Finck         if (StreamSegment->ExtendedSize)
396*c2c66affSColin Finck         {
397*c2c66affSColin Finck             // unprepare stream header extension
398*c2c66affSColin Finck             StreamSegment->StreamSegment.KsDataTypeHandler->KsCompleteIoOperation(StreamSegment->MediaSample[Index], (CurStreamHeader + 1), StreamSegment->StreamSegment.IoOperation, bOverlapped == FALSE);
399*c2c66affSColin Finck         }
400*c2c66affSColin Finck 
401*c2c66affSColin Finck         Start = 0;
402*c2c66affSColin Finck         Stop = 0;
403*c2c66affSColin Finck         if (bOverlapped && StreamSegment->StreamSegment.IoOperation == KsIoOperation_Read)
404*c2c66affSColin Finck         {
405*c2c66affSColin Finck             // update common media sample details
406*c2c66affSColin Finck             StreamSegment->MediaSample[Index]->SetSyncPoint((CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_SPLICEPOINT));
407*c2c66affSColin Finck             StreamSegment->MediaSample[Index]->SetPreroll((CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_PREROLL));
408*c2c66affSColin Finck             StreamSegment->MediaSample[Index]->SetDiscontinuity((CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_DATADISCONTINUITY));
409*c2c66affSColin Finck 
410*c2c66affSColin Finck             if (CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TIMEVALID)
411*c2c66affSColin Finck             {
412*c2c66affSColin Finck                 // use valid timestamp
413*c2c66affSColin Finck                 Start = CurStreamHeader->PresentationTime.Time;
414*c2c66affSColin Finck 
415*c2c66affSColin Finck                 if (CurStreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_DURATIONVALID)
416*c2c66affSColin Finck                 {
417*c2c66affSColin Finck                     Stop = CurStreamHeader->PresentationTime.Time + CurStreamHeader->Duration;
418*c2c66affSColin Finck                 }
419*c2c66affSColin Finck             }
420*c2c66affSColin Finck         }
421*c2c66affSColin Finck 
422*c2c66affSColin Finck         // now set time
423*c2c66affSColin Finck         hr = StreamSegment->MediaSample[Index]->SetTime(&Start, &Stop);
424*c2c66affSColin Finck         if (FAILED(hr))
425*c2c66affSColin Finck         {
426*c2c66affSColin Finck             // use start time
427*c2c66affSColin Finck             StreamSegment->MediaSample[Index]->SetTime(&Start, &Start);
428*c2c66affSColin Finck         }
429*c2c66affSColin Finck 
430*c2c66affSColin Finck         // set valid data length
431*c2c66affSColin Finck         StreamSegment->MediaSample[Index]->SetActualDataLength(CurStreamHeader->DataUsed);
432*c2c66affSColin Finck 
433*c2c66affSColin Finck         if (StreamSegment->StreamSegment.IoOperation == KsIoOperation_Read)
434*c2c66affSColin Finck         {
435*c2c66affSColin Finck             if (bOverlapped)
436*c2c66affSColin Finck             {
437*c2c66affSColin Finck                 // deliver sample
438*c2c66affSColin Finck                 m_Pin->KsDeliver(StreamSegment->MediaSample[Index], CurStreamHeader->OptionsFlags);
439*c2c66affSColin Finck             }
440*c2c66affSColin Finck         }
441*c2c66affSColin Finck         else if (StreamSegment->StreamSegment.IoOperation == KsIoOperation_Write)
442*c2c66affSColin Finck         {
443*c2c66affSColin Finck             // release media sample reference
444*c2c66affSColin Finck             StreamSegment->MediaSample[Index]->Release();
445*c2c66affSColin Finck         }
446*c2c66affSColin Finck 
447*c2c66affSColin Finck         CurStreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)CurStreamHeader + CurStreamHeader->Size);
448*c2c66affSColin Finck     }
449*c2c66affSColin Finck 
450*c2c66affSColin Finck     // delete stream headers
451*c2c66affSColin Finck     CoTaskMemFree(StreamSegment->StreamHeader);
452*c2c66affSColin Finck 
453*c2c66affSColin Finck     if (StreamSegment->StreamSegment.KsDataTypeHandler)
454*c2c66affSColin Finck     {
455*c2c66affSColin Finck         // release reference
456*c2c66affSColin Finck         StreamSegment->StreamSegment.KsDataTypeHandler->Release();
457*c2c66affSColin Finck     }
458*c2c66affSColin Finck 
459*c2c66affSColin Finck     // decrement pending i/o count
460*c2c66affSColin Finck     m_Pin->KsDecrementPendingIoCount();
461*c2c66affSColin Finck 
462*c2c66affSColin Finck     //notify of completion
463*c2c66affSColin Finck     m_Pin->KsMediaSamplesCompleted(InStreamSegment);
464*c2c66affSColin Finck 
465*c2c66affSColin Finck     //destroy stream segment
466*c2c66affSColin Finck     CoTaskMemFree(StreamSegment);
467*c2c66affSColin Finck 
468*c2c66affSColin Finck     //release reference to ourselves
469*c2c66affSColin Finck     Release();
470*c2c66affSColin Finck 
471*c2c66affSColin Finck     // done
472*c2c66affSColin Finck     // Event handle is closed by caller
473*c2c66affSColin Finck     return S_OK;
474*c2c66affSColin Finck }
475*c2c66affSColin Finck 
476*c2c66affSColin Finck HRESULT
477*c2c66affSColin Finck WINAPI
CKsInterfaceHandler_Constructor(IUnknown * pUnkOuter,REFIID riid,LPVOID * ppv)478*c2c66affSColin Finck CKsInterfaceHandler_Constructor(
479*c2c66affSColin Finck     IUnknown * pUnkOuter,
480*c2c66affSColin Finck     REFIID riid,
481*c2c66affSColin Finck     LPVOID * ppv)
482*c2c66affSColin Finck {
483*c2c66affSColin Finck #ifdef KSPROXY_TRACE
484*c2c66affSColin Finck     OutputDebugStringW(L"CKsInterfaceHandler_Constructor\n");
485*c2c66affSColin Finck #endif
486*c2c66affSColin Finck 
487*c2c66affSColin Finck     CKsInterfaceHandler * handler = new CKsInterfaceHandler();
488*c2c66affSColin Finck 
489*c2c66affSColin Finck     if (!handler)
490*c2c66affSColin Finck         return E_OUTOFMEMORY;
491*c2c66affSColin Finck 
492*c2c66affSColin Finck     if (FAILED(handler->QueryInterface(riid, ppv)))
493*c2c66affSColin Finck     {
494*c2c66affSColin Finck         /* not supported */
495*c2c66affSColin Finck         delete handler;
496*c2c66affSColin Finck         return E_NOINTERFACE;
497*c2c66affSColin Finck     }
498*c2c66affSColin Finck 
499*c2c66affSColin Finck     return NOERROR;
500*c2c66affSColin Finck }
501