168
|
1 #include "outputpin.h"
|
|
2 #include "allocator.h"
|
|
3 #include "iunk.h"
|
2069
|
4 #include "wine/winerror.h"
|
2072
|
5
|
|
6 #include "stdio.h"
|
|
7 //#include "string.h"
|
|
8
|
|
9 //#include <cstdio>
|
|
10 //#include <cstring>
|
713
|
11
|
168
|
12 /*
|
|
13 An object beyond interface IEnumMediaTypes.
|
|
14 Returned by COutputPin through call IPin::EnumMediaTypes().
|
|
15 */
|
|
16
|
1063
|
17 using namespace std;
|
|
18
|
168
|
19 class CEnumMediaTypes: public IEnumMediaTypes
|
|
20 {
|
1545
|
21 public:
|
168
|
22 AM_MEDIA_TYPE type;
|
|
23 static GUID interfaces[];
|
|
24 DECLARE_IUNKNOWN(CEnumMediaTypes)
|
|
25 CEnumMediaTypes(const AM_MEDIA_TYPE&);
|
1545
|
26 ~CEnumMediaTypes() {delete vt;}
|
|
27 };
|
168
|
28
|
|
29 GUID CEnumMediaTypes::interfaces[]=
|
|
30 {
|
|
31 IID_IUnknown,
|
|
32 IID_IEnumMediaTypes,
|
|
33 };
|
1545
|
34
|
|
35 // IPin->IUnknown methods
|
168
|
36 IMPLEMENT_IUNKNOWN(CEnumMediaTypes)
|
1545
|
37
|
168
|
38
|
1545
|
39 static HRESULT STDCALL CEnumMediaTypes_Next(IEnumMediaTypes * This,
|
|
40 /* [in] */ ULONG cMediaTypes,
|
|
41 /* [size_is][out] */ AM_MEDIA_TYPE **ppMediaTypes,
|
|
42 /* [out] */ ULONG *pcFetched)
|
168
|
43 {
|
|
44 AM_MEDIA_TYPE& type=((CEnumMediaTypes*)This)->type;
|
|
45 Debug printf("CEnumMediaTypes::Next() called\n");
|
1545
|
46 if (!ppMediaTypes)
|
|
47 return E_INVALIDARG;
|
|
48 if (!pcFetched && (cMediaTypes!=1))
|
|
49 return E_INVALIDARG;
|
|
50 if (cMediaTypes <= 0)
|
|
51 return 0;
|
|
52
|
|
53 if (pcFetched)
|
|
54 *pcFetched=1;
|
|
55 ppMediaTypes[0] = (AM_MEDIA_TYPE *)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
|
168
|
56 memcpy(*ppMediaTypes, &type, sizeof(AM_MEDIA_TYPE));
|
1545
|
57 if (ppMediaTypes[0]->pbFormat)
|
168
|
58 {
|
|
59 ppMediaTypes[0]->pbFormat=(char *)CoTaskMemAlloc(ppMediaTypes[0]->cbFormat);
|
|
60 memcpy(ppMediaTypes[0]->pbFormat, type.pbFormat, ppMediaTypes[0]->cbFormat);
|
|
61 }
|
1545
|
62 if (cMediaTypes == 1)
|
|
63 return 0;
|
168
|
64 return 1;
|
|
65 }
|
1545
|
66
|
|
67 /* I expect that these methods are unused. */
|
|
68 static HRESULT STDCALL CEnumMediaTypes_Skip(IEnumMediaTypes * This,
|
|
69 /* [in] */ ULONG cMediaTypes)
|
168
|
70 {
|
|
71 Debug printf("CEnumMediaTypes::Skip() called\n");
|
|
72 return E_NOTIMPL;
|
|
73 }
|
|
74
|
1545
|
75 static HRESULT STDCALL CEnumMediaTypes_Reset(IEnumMediaTypes * This)
|
168
|
76 {
|
|
77 Debug printf("CEnumMediaTypes::Reset() called\n");
|
|
78 return 0;
|
|
79 }
|
|
80
|
1545
|
81 static HRESULT STDCALL CEnumMediaTypes_Clone(IEnumMediaTypes * This,
|
|
82 /* [out] */ IEnumMediaTypes **ppEnum)
|
168
|
83 {
|
|
84 Debug printf("CEnumMediaTypes::Clone() called\n");
|
|
85 return E_NOTIMPL;
|
|
86 }
|
|
87
|
1545
|
88
|
|
89 CEnumMediaTypes::CEnumMediaTypes(const AM_MEDIA_TYPE& amtype)
|
|
90 {
|
|
91 refcount = 1;
|
|
92 type = amtype;
|
|
93
|
|
94 vt = new IEnumMediaTypes_vt;
|
|
95 vt->QueryInterface = QueryInterface;
|
|
96 vt->AddRef = AddRef;
|
|
97 vt->Release = Release;
|
|
98 vt->Next = CEnumMediaTypes_Next;
|
|
99 vt->Skip = CEnumMediaTypes_Skip;
|
|
100 vt->Reset = CEnumMediaTypes_Reset;
|
|
101 vt->Clone = CEnumMediaTypes_Clone;
|
|
102 }
|
|
103
|
|
104
|
|
105 static HRESULT STDCALL COutputPin_AddRef(IUnknown* This)
|
|
106 {
|
|
107 Debug printf("COutputPin_AddRef(%p) called (%d)\n",
|
|
108 This, ((COutputPin*)This)->refcount);
|
|
109 ((COutputPin*)This)->refcount++;
|
|
110 return 0;
|
|
111 }
|
168
|
112
|
1545
|
113 static HRESULT STDCALL COutputPin_Release(IUnknown* This)
|
|
114 {
|
|
115 Debug printf("COutputPin_Release(%p) called (%d)\n",
|
|
116 This, ((COutputPin*)This)->refcount);
|
|
117 if (--((COutputPin*)This)->refcount<=0)
|
|
118 delete (COutputPin*)This;
|
|
119
|
|
120 return 0;
|
|
121 }
|
|
122
|
|
123 static HRESULT STDCALL COutputPin_M_AddRef(IUnknown* This)
|
|
124 {
|
|
125 COutputMemPin* p = (COutputMemPin*) This;
|
|
126 Debug printf("COutputPin_MAddRef(%p) called (%p, %d)\n",
|
|
127 p, p->parent, p->parent->refcount);
|
|
128 p->parent->refcount++;
|
|
129 return 0;
|
|
130 }
|
|
131
|
|
132 static HRESULT STDCALL COutputPin_M_Release(IUnknown* This)
|
|
133 {
|
|
134 COutputMemPin* p = (COutputMemPin*) This;
|
|
135 Debug printf("COutputPin_MRelease(%p) called (%p, %d)\n",
|
|
136 p, p->parent, p->parent->refcount);
|
|
137 if (--p->parent->refcount <= 0)
|
|
138 delete p->parent;
|
|
139 return 0;
|
|
140 }
|
|
141
|
|
142 /* Implementation of output pin object. */
|
168
|
143 // Constructor
|
|
144
|
1545
|
145
|
|
146 static HRESULT STDCALL COutputPin_QueryInterface(IUnknown* This, GUID* iid, void** ppv)
|
168
|
147 {
|
1545
|
148 Debug printf("COutputPin_QueryInterface(%p) called\n", This);
|
|
149 if (!ppv)
|
|
150 return E_INVALIDARG;
|
|
151
|
|
152 COutputPin* p = (COutputPin*) This;
|
168
|
153
|
1545
|
154 if (memcmp(iid, &IID_IUnknown, 16) == 0)
|
168
|
155 {
|
1545
|
156 *ppv = p;
|
|
157 p->vt->AddRef(This);
|
|
158 return 0;
|
168
|
159 }
|
1545
|
160 if (memcmp(iid, &IID_IMemInputPin, 16) == 0)
|
168
|
161 {
|
1545
|
162 *ppv = p->mempin;
|
|
163 p->mempin->vt->AddRef((IUnknown*)*ppv);
|
168
|
164 return 0;
|
|
165 }
|
|
166
|
|
167 Debug printf("Unknown interface : %08x-%04x-%04x-%02x%02x-" \
|
713
|
168 "%02x%02x%02x%02x%02x%02x\n",
|
|
169 iid->f1, iid->f2, iid->f3,
|
|
170 (unsigned char)iid->f4[1], (unsigned char)iid->f4[0],
|
|
171 (unsigned char)iid->f4[2], (unsigned char)iid->f4[3],
|
|
172 (unsigned char)iid->f4[4], (unsigned char)iid->f4[5],
|
|
173 (unsigned char)iid->f4[6], (unsigned char)iid->f4[7]);
|
1545
|
174 return E_NOINTERFACE;
|
168
|
175 }
|
|
176
|
|
177 // IPin methods
|
1545
|
178 static HRESULT STDCALL COutputPin_Connect(IPin * This,
|
|
179 /* [in] */ IPin *pReceivePin,
|
|
180 /* [in] */ /* const */ AM_MEDIA_TYPE *pmt)
|
168
|
181 {
|
1545
|
182 Debug printf("COutputPin_Connect() called\n");
|
168
|
183 /*
|
|
184 *pmt=((COutputPin*)This)->type;
|
|
185 if(pmt->cbFormat>0)
|
|
186 {
|
|
187 pmt->pbFormat=CoTaskMemAlloc(pmt->cbFormat);
|
|
188 memcpy(pmt->pbFormat, ((COutputPin*)This)->type.pbFormat, pmt->cbFormat);
|
|
189 }
|
|
190 */
|
1545
|
191 //return E_NOTIMPL;
|
|
192 return 0;// XXXXXXXXXXXXX CHECKME XXXXXXXXXXXXXXX
|
168
|
193 // if I put return 0; here, it crashes
|
|
194 }
|
|
195
|
1545
|
196 static HRESULT STDCALL COutputPin_ReceiveConnection(IPin * This,
|
|
197 /* [in] */ IPin *pConnector,
|
|
198 /* [in] */ const AM_MEDIA_TYPE *pmt)
|
168
|
199 {
|
1545
|
200 Debug printf("COutputPin_ReceiveConnection() called\n");
|
168
|
201 ((COutputPin*)This)->remote=pConnector;
|
|
202 return 0;
|
|
203 }
|
1545
|
204
|
|
205 static HRESULT STDCALL COutputPin_Disconnect(IPin * This)
|
168
|
206 {
|
1545
|
207 Debug printf("COutputPin_Disconnect() called\n");
|
168
|
208 return 1;
|
|
209 }
|
|
210
|
1545
|
211 static HRESULT STDCALL COutputPin_ConnectedTo(IPin * This,
|
|
212 /* [out] */ IPin **pPin)
|
|
213 {
|
|
214 Debug printf("COutputPin_ConnectedTo() called\n");
|
|
215 if (!pPin)
|
|
216 return E_INVALIDARG;
|
|
217 *pPin = ((COutputPin*)This)->remote;
|
|
218 return 0;
|
|
219 }
|
168
|
220
|
1545
|
221 static HRESULT STDCALL COutputPin_ConnectionMediaType(IPin * This,
|
|
222 /* [out] */ AM_MEDIA_TYPE *pmt)
|
|
223 {
|
|
224 Debug printf("CInputPin::ConnectionMediaType() called\n");
|
|
225 if (!pmt)
|
|
226 return E_INVALIDARG;
|
|
227 *pmt = ((COutputPin*)This)->type;
|
|
228 if (pmt->cbFormat>0)
|
|
229 {
|
|
230 pmt->pbFormat=(char *)CoTaskMemAlloc(pmt->cbFormat);
|
|
231 memcpy(pmt->pbFormat, ((COutputPin*)This)->type.pbFormat, pmt->cbFormat);
|
|
232 }
|
|
233 return 0;
|
|
234 }
|
|
235
|
|
236 static HRESULT STDCALL COutputPin_QueryPinInfo(IPin * This,
|
|
237 /* [out] */ PIN_INFO *pInfo)
|
|
238 {
|
|
239 Debug printf("COutputPin_QueryPinInfo() called\n");
|
|
240 return E_NOTIMPL;
|
|
241 }
|
|
242
|
|
243 static HRESULT STDCALL COutputPin_QueryDirection(IPin * This,
|
|
244 /* [out] */ PIN_DIRECTION *pPinDir)
|
|
245 {
|
|
246 Debug printf("COutputPin_QueryDirection() called\n");
|
|
247 if (!pPinDir)
|
|
248 return E_INVALIDARG;
|
|
249 *pPinDir = PINDIR_INPUT;
|
|
250 return 0;
|
|
251 }
|
|
252
|
|
253 static HRESULT STDCALL COutputPin_QueryId(IPin * This,
|
|
254 /* [out] */ LPWSTR *Id)
|
|
255 {
|
|
256 Debug printf("COutputPin_QueryId() called\n");
|
|
257 return E_NOTIMPL;
|
|
258 }
|
|
259
|
|
260 static HRESULT STDCALL COutputPin_QueryAccept(IPin * This,
|
|
261 /* [in] */ const AM_MEDIA_TYPE *pmt)
|
168
|
262 {
|
1545
|
263 Debug printf("COutputPin_QueryAccept() called\n");
|
|
264 return E_NOTIMPL;
|
|
265 }
|
|
266
|
|
267 static HRESULT STDCALL COutputPin_EnumMediaTypes(IPin * This,
|
|
268 /* [out] */ IEnumMediaTypes **ppEnum)
|
|
269 {
|
|
270 Debug printf("COutputPin_EnumMediaTypes() called\n");
|
|
271 if (!ppEnum)
|
|
272 return E_INVALIDARG;
|
|
273 *ppEnum=new CEnumMediaTypes(((COutputPin*)This)->type);
|
|
274 return 0;
|
|
275 }
|
|
276
|
|
277 static HRESULT STDCALL COutputPin_QueryInternalConnections(IPin * This,
|
|
278 /* [out] */ IPin **apPin,
|
|
279 /* [out][in] */ ULONG *nPin)
|
|
280 {
|
|
281 Debug printf("COutputPin_QueryInternalConnections() called\n");
|
|
282 return E_NOTIMPL;
|
|
283 }
|
|
284
|
|
285 static HRESULT STDCALL COutputPin_EndOfStream(IPin * This)
|
|
286 {
|
|
287 Debug printf("COutputPin_EndOfStream() called\n");
|
|
288 return E_NOTIMPL;
|
|
289 }
|
|
290
|
|
291 static HRESULT STDCALL COutputPin_BeginFlush(IPin * This)
|
|
292 {
|
|
293 Debug printf("COutputPin_BeginFlush() called\n");
|
|
294 return E_NOTIMPL;
|
|
295 }
|
|
296
|
|
297 static HRESULT STDCALL COutputPin_EndFlush(IPin * This)
|
|
298 {
|
|
299 Debug printf("COutputPin_EndFlush() called\n");
|
|
300 return E_NOTIMPL;
|
|
301 }
|
|
302
|
|
303 static HRESULT STDCALL COutputPin_NewSegment(IPin * This,
|
|
304 /* [in] */ REFERENCE_TIME tStart,
|
|
305 /* [in] */ REFERENCE_TIME tStop,
|
|
306 /* [in] */ double dRate)
|
|
307 {
|
|
308 Debug printf("COutputPin_NewSegment(%ld,%ld,%f) called\n",
|
|
309 tStart, tStop, dRate);
|
168
|
310 return 0;
|
|
311 }
|
|
312
|
|
313
|
|
314
|
|
315 // IMemInputPin->IUnknown methods
|
|
316
|
1545
|
317 static HRESULT STDCALL COutputPin_M_QueryInterface(IUnknown* This, GUID* iid, void** ppv)
|
168
|
318 {
|
1545
|
319 Debug printf("COutputPin_M_QueryInterface() called\n");
|
|
320 if (!ppv)
|
|
321 return E_INVALIDARG;
|
|
322
|
|
323 COutputPin* p = (COutputPin*)This;
|
168
|
324 if(!memcmp(iid, &IID_IUnknown, 16))
|
|
325 {
|
1545
|
326 *ppv=p;
|
|
327 p->vt->AddRef(This);
|
168
|
328 return 0;
|
|
329 }
|
1545
|
330 /*if(!memcmp(iid, &IID_IPin, 16))
|
168
|
331 {
|
|
332 COutputPin* ptr=(COutputPin*)(This-1);
|
|
333 *ppv=(void*)ptr;
|
|
334 AddRef((IUnknown*)ptr);
|
|
335 return 0;
|
|
336 }*/
|
|
337 if(!memcmp(iid, &IID_IMemInputPin, 16))
|
|
338 {
|
1545
|
339 *ppv=p->mempin;
|
|
340 p->mempin->vt->AddRef(This);
|
168
|
341 return 0;
|
|
342 }
|
|
343 Debug printf("Unknown interface : %08x-%04x-%04x-%02x%02x-" \
|
1545
|
344 "%02x%02x%02x%02x%02x%02x\n",
|
|
345 iid->f1, iid->f2, iid->f3,
|
|
346 (unsigned char)iid->f4[1], (unsigned char)iid->f4[0],
|
|
347 (unsigned char)iid->f4[2], (unsigned char)iid->f4[3],
|
|
348 (unsigned char)iid->f4[4], (unsigned char)iid->f4[5],
|
|
349 (unsigned char)iid->f4[6], (unsigned char)iid->f4[7]);
|
|
350 return E_NOINTERFACE;
|
168
|
351 }
|
|
352
|
|
353 // IMemInputPin methods
|
|
354
|
1545
|
355 static HRESULT STDCALL COutputPin_GetAllocator(IMemInputPin * This,
|
|
356 /* [out] */ IMemAllocator **ppAllocator)
|
168
|
357 {
|
1545
|
358 Debug printf("COutputPin_GetAllocator(%p, %p) called\n", This->vt, ppAllocator);
|
168
|
359 *ppAllocator=new MemAllocator;
|
|
360 return 0;
|
|
361 }
|
|
362
|
1545
|
363 static HRESULT STDCALL COutputPin_NotifyAllocator(IMemInputPin * This,
|
|
364 /* [in] */ IMemAllocator *pAllocator,
|
|
365 /* [in] */ int bReadOnly)
|
168
|
366 {
|
1545
|
367 Debug printf("COutputPin_NotifyAllocator(%p, %p) called\n", This, pAllocator);
|
|
368 ((COutputMemPin*)This)->pAllocator = (MemAllocator*) pAllocator;
|
168
|
369 return 0;
|
|
370 }
|
|
371
|
1545
|
372 static HRESULT STDCALL COutputPin_GetAllocatorRequirements(IMemInputPin * This,
|
|
373 /* [out] */ ALLOCATOR_PROPERTIES *pProps)
|
168
|
374 {
|
1545
|
375 Debug printf("COutputPin_GetAllocatorRequirements() called\n");
|
168
|
376 return E_NOTIMPL;
|
|
377 }
|
|
378
|
1545
|
379 static HRESULT STDCALL COutputPin_Receive(IMemInputPin * This,
|
|
380 /* [in] */ IMediaSample *pSample)
|
168
|
381 {
|
1545
|
382 Debug printf("COutputPin_Receive(%p) called\n", This);
|
|
383 if (!pSample)
|
|
384 return E_INVALIDARG;
|
168
|
385 char* pointer;
|
1545
|
386 if (pSample->vt->GetPointer(pSample, (BYTE **)&pointer))
|
168
|
387 return -1;
|
1545
|
388 int len = pSample->vt->GetActualDataLength(pSample);
|
|
389 if (len == 0)
|
|
390 len = pSample->vt->GetSize(pSample);//for iv50
|
168
|
391 //if(me.frame_pointer)memcpy(me.frame_pointer, pointer, len);
|
1545
|
392
|
|
393 COutputMemPin* mp= (COutputMemPin*)This;
|
|
394 if (mp->frame_pointer)
|
|
395 *(mp->frame_pointer) = pointer;
|
|
396 if (mp->frame_size_pointer)
|
|
397 *(mp->frame_size_pointer) = len;
|
168
|
398 /*
|
|
399 FILE* file=fopen("./uncompr.bmp", "wb");
|
|
400 char head[14]={0x42, 0x4D, 0x36, 0x10, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00};
|
|
401 *(int*)(&head[2])=len+0x36;
|
|
402 fwrite(head, 14, 1, file);
|
|
403 fwrite(&((VIDEOINFOHEADER*)me.type.pbFormat)->bmiHeader, sizeof(BITMAPINFOHEADER), 1, file);
|
|
404 fwrite(pointer, len, 1, file);
|
|
405 fclose(file);
|
|
406 */
|
|
407 // pSample->vt->Release((IUnknown*)pSample);
|
|
408 return 0;
|
|
409 }
|
|
410
|
1545
|
411 static HRESULT STDCALL COutputPin_ReceiveMultiple(IMemInputPin * This,
|
|
412 /* [size_is][in] */ IMediaSample **pSamples,
|
|
413 /* [in] */ long nSamples,
|
|
414 /* [out] */ long *nSamplesProcessed)
|
168
|
415 {
|
1545
|
416 Debug printf("COutputPin_ReceiveMultiple() called (UNIMPLEMENTED)\n");
|
|
417 return E_NOTIMPL;
|
|
418 }
|
|
419
|
|
420 static HRESULT STDCALL COutputPin_ReceiveCanBlock(IMemInputPin * This)
|
|
421 {
|
|
422 Debug printf("COutputPin_ReceiveCanBlock() called (UNIMPLEMENTED)\n");
|
168
|
423 return E_NOTIMPL;
|
|
424 }
|
|
425
|
1545
|
426 COutputPin::COutputPin(const AM_MEDIA_TYPE& vh)
|
|
427 :refcount(1), type(vh), remote(0)
|
168
|
428 {
|
1545
|
429 vt = new IPin_vt;
|
|
430 vt->QueryInterface = COutputPin_QueryInterface;
|
|
431 vt->AddRef = COutputPin_AddRef;
|
|
432 vt->Release = COutputPin_Release;
|
|
433 vt->Connect = COutputPin_Connect;
|
|
434 vt->ReceiveConnection = COutputPin_ReceiveConnection;
|
|
435 vt->Disconnect = COutputPin_Disconnect;
|
|
436 vt->ConnectedTo = COutputPin_ConnectedTo;
|
|
437 vt->ConnectionMediaType = COutputPin_ConnectionMediaType;
|
|
438 vt->QueryPinInfo = COutputPin_QueryPinInfo;
|
|
439 vt->QueryDirection = COutputPin_QueryDirection;
|
|
440 vt->QueryId = COutputPin_QueryId;
|
|
441 vt->QueryAccept = COutputPin_QueryAccept;
|
|
442 vt->EnumMediaTypes = COutputPin_EnumMediaTypes;
|
|
443 vt->QueryInternalConnections = COutputPin_QueryInternalConnections;
|
|
444 vt->EndOfStream = COutputPin_EndOfStream;
|
|
445 vt->BeginFlush = COutputPin_BeginFlush;
|
|
446 vt->EndFlush = COutputPin_EndFlush;
|
|
447 vt->NewSegment = COutputPin_NewSegment;
|
|
448
|
|
449 mempin = new COutputMemPin;
|
|
450 mempin->vt = new IMemInputPin_vt;
|
|
451 mempin->vt->QueryInterface = COutputPin_M_QueryInterface;
|
|
452 mempin->vt->AddRef = COutputPin_M_AddRef;
|
|
453 mempin->vt->Release = COutputPin_M_Release;
|
|
454 mempin->vt->GetAllocator = COutputPin_GetAllocator;
|
|
455 mempin->vt->NotifyAllocator = COutputPin_NotifyAllocator;
|
|
456 mempin->vt->GetAllocatorRequirements = COutputPin_GetAllocatorRequirements;
|
|
457 mempin->vt->Receive = COutputPin_Receive;
|
|
458 mempin->vt->ReceiveMultiple = COutputPin_ReceiveMultiple;
|
|
459 mempin->vt->ReceiveCanBlock = COutputPin_ReceiveCanBlock;
|
|
460
|
|
461 mempin->frame_size_pointer = 0;
|
|
462 mempin->frame_pointer = 0;
|
|
463 mempin->pAllocator = 0;
|
|
464 mempin->parent = this;
|
168
|
465 }
|
1545
|
466
|
|
467 COutputPin::~COutputPin()
|
|
468 {
|
|
469 delete vt;
|
|
470 delete mempin->vt;
|
|
471 }
|