1 /*
2 * Modified for use with MPlayer, detailed changelog at
3 * http://svn.mplayerhq.hu/mplayer/trunk/
4 */
5
6 #include "loader/wine/winerror.h"
7 #include "loader/wine/windef.h"
8 #include "outputpin.h"
9 #include "mediatype.h"
10 #include <stdio.h>
11 #include <string.h>
12 #include <stdlib.h>
13
output_unimplemented(const char * s,void * p)14 static inline int output_unimplemented(const char* s, void* p)
15 {
16 Debug printf("%s(%p) called (UNIMPLEMENTED)", s, p);
17 return E_NOTIMPL;
18 }
19
20 /**
21 An object beyond interface IEnumMediaTypes.
22 Returned by COutputPin through call IPin::EnumMediaTypes().
23 */
24 typedef struct CEnumMediaTypes
25 {
26 IEnumMediaTypes_vt* vt;
27 DECLARE_IUNKNOWN();
28 AM_MEDIA_TYPE type;
29 GUID interfaces[2];
30 } CEnumMediaTypes;
31
32 /**
33 IMemOutput interface implementation
34 */
35 struct COutputMemPin
36 {
37 IMemInputPin_vt* vt;
38 DECLARE_IUNKNOWN();
39 char** frame_pointer;
40 long* frame_size_pointer;
41 MemAllocator* pAllocator;
42 COutputPin* parent;
43 };
44
45 /**
46 * \brief IEnumMediaTypes:Next (retrives a specified number of media types )
47 *
48 * \param[in] This pointer to CEnumMediaTypes object
49 * \param[in] cMediaTypes number of media types to retrive
50 * \param[out] ppMediaTypes array of AM_MEDIA_TYPE structure pointers of size cMediaTypes
51 * \param[out] pcFetched address of variables that receives number of returned media types
52 *
53 * \return S_OK - success
54 * \return S_FALSE - did not return as meny structures as requested
55 * \return E_INVALIDARG Invalid argument
56 * \return E_POINTER Null pointer
57 * \return VFW_E_ENUM_OUT_OF_SYNC - pin's state has changed and is now inconsistent with enumerator
58 *
59 */
CEnumMediaTypes_Next(IEnumMediaTypes * This,ULONG cMediaTypes,AM_MEDIA_TYPE ** ppMediaTypes,ULONG * pcFetched)60 static HRESULT STDCALL CEnumMediaTypes_Next(IEnumMediaTypes * This,
61 /* [in] */ ULONG cMediaTypes,
62 /* [size_is][out] */ AM_MEDIA_TYPE **ppMediaTypes,
63 /* [out] */ ULONG *pcFetched)
64 {
65 AM_MEDIA_TYPE* type = &((CEnumMediaTypes*)This)->type;
66 Debug printf("CEnumMediaTypes::Next(%p) called\n", This);
67 if (!ppMediaTypes)
68 return E_INVALIDARG;
69 if (!pcFetched && (cMediaTypes!=1))
70 return E_INVALIDARG;
71 if (cMediaTypes <= 0)
72 return 0;
73
74 if (pcFetched)
75 *pcFetched=1;
76 ppMediaTypes[0] = CreateMediaType(type);
77
78 if (cMediaTypes == 1)
79 return 0;
80 return 1;
81 }
82
83 /* I expect that these methods are unused. */
84
85 /**
86 * \brief IEnumMediaTypes::Skip (skips over a specified number of media types)
87 *
88 * \param[in] This pointer to CEnumMEdiaTypes object
89 * \param[in] cMediaTypes number of media types to skip
90 *
91 * \return S_OK - success
92 * \return S_FALSE - skipped past the end of the sequence
93 * \return VFW_E_ENUM_OUT_OF_SYNC - pin's state has changed and is now inconsistent with enumerator
94 *
95 */
CEnumMediaTypes_Skip(IEnumMediaTypes * This,ULONG cMediaTypes)96 static HRESULT STDCALL CEnumMediaTypes_Skip(IEnumMediaTypes * This,
97 /* [in] */ ULONG cMediaTypes)
98 {
99 return output_unimplemented("CEnumMediaTypes::Skip", This);
100 }
101
102 /**
103 * \brief IEnumMediaTypes::Reset (resets enumeration sequence to beginning)
104 *
105 * \param[in] This pointer to CEnumMEdiaTypes object
106 *
107 * \return S_OK - success
108 *
109 */
CEnumMediaTypes_Reset(IEnumMediaTypes * This)110 static HRESULT STDCALL CEnumMediaTypes_Reset(IEnumMediaTypes * This)
111 {
112 Debug printf("CEnumMediaTypes::Reset(%p) called\n", This);
113 return 0;
114 }
115
116 /**
117 * \brief IEnumMediaTypes::Clone (makes a copy of enumerator, returned object
118 * starts at the same position as original)
119 *
120 * \param[in] This pointer to CEnumMEdiaTypes object
121 * \param[out] ppEnum address of variable that receives pointer to IEnumMediaTypes interface
122 *
123 * \return S_OK - success
124 * \return E_OUTOFMEMRY - Insufficient memory
125 * \return E_POINTER - Null pointer
126 * \return VFW_E_ENUM_OUT_OF_SYNC - pin's state has changed and is now inconsistent with enumerator
127 *
128 */
CEnumMediaTypes_Clone(IEnumMediaTypes * This,IEnumMediaTypes ** ppEnum)129 static HRESULT STDCALL CEnumMediaTypes_Clone(IEnumMediaTypes * This,
130 /* [out] */ IEnumMediaTypes **ppEnum)
131 {
132 Debug printf("CEnumMediaTypes::Clone(%p) called\n", This);
133 return E_NOTIMPL;
134 }
135
136 /**
137 * \brief CEnumMediaTypes destructor
138 *
139 * \param[in] This pointer to CEnumMediaTypes object
140 *
141 */
CEnumMediaTypes_Destroy(CEnumMediaTypes * This)142 static void CEnumMediaTypes_Destroy(CEnumMediaTypes* This)
143 {
144 FreeMediaType(&(This->type));
145 free(This->vt);
146 free(This);
147 }
148
149 // IEnumMediaTypes->IUnknown methods
IMPLEMENT_IUNKNOWN(CEnumMediaTypes)150 IMPLEMENT_IUNKNOWN(CEnumMediaTypes)
151
152 /**
153 * \brief CEnumMediaTypes constructor
154 *
155 * \param[in] amt media type for enumerating
156 *
157 * \return pointer to CEnumMEdiaTypes object or NULL if error occured
158 *
159 */
160 static CEnumMediaTypes* CEnumMediaTypesCreate(const AM_MEDIA_TYPE* amt)
161 {
162 CEnumMediaTypes *This = malloc(sizeof(CEnumMediaTypes)) ;
163
164 if (!This)
165 return NULL;
166
167 This->vt = malloc(sizeof(IEnumMediaTypes_vt));
168 if (!This->vt)
169 {
170 free(This);
171 return NULL;
172 }
173
174 This->refcount = 1;
175 CopyMediaType(&(This->type),amt);
176
177 This->vt->QueryInterface = CEnumMediaTypes_QueryInterface;
178 This->vt->AddRef = CEnumMediaTypes_AddRef;
179 This->vt->Release = CEnumMediaTypes_Release;
180 This->vt->Next = CEnumMediaTypes_Next;
181 This->vt->Skip = CEnumMediaTypes_Skip;
182 This->vt->Reset = CEnumMediaTypes_Reset;
183 This->vt->Clone = CEnumMediaTypes_Clone;
184
185 This->interfaces[0] = IID_IUnknown;
186 This->interfaces[1] = IID_IEnumMediaTypes;
187
188 return This;
189 }
190
191
192 /*************
193 * COutputPin
194 *
195 * WARNING:
196 * This is implementation of INPUT pin in DirectShow's terms
197 *
198 *************/
199
200
201 /**
202 *
203 * \brief IUnknown::QueryInterface (query object for interface)
204 * \param[in] This pointer to IUnknown interface
205 * \param[in] iid GUID of requested interface
206 * \param[out] ppv receives pointer to interface
207 *
208 * \return S_OK - success (and *ppv contains valid pointer)
209 * \return E_NOINTERFACE - interface not found (and *ppv was set NULL)
210 *
211 * \note
212 * Make sure to call Release on received interface when you are done
213 *
214 */
COutputPin_QueryInterface(IUnknown * This,const GUID * iid,void ** ppv)215 static HRESULT STDCALL COutputPin_QueryInterface(IUnknown* This, const GUID* iid, void** ppv)
216 {
217 COutputPin* p = (COutputPin*) This;
218
219 Debug printf("COutputPin_QueryInterface(%p) called\n", This);
220 if (!ppv)
221 return E_INVALIDARG;
222
223 if (memcmp(iid, &IID_IUnknown, 16) == 0)
224 {
225 *ppv = p;
226 p->vt->AddRef(This);
227 return 0;
228 }
229 if (memcmp(iid, &IID_IMemInputPin, 16) == 0)
230 {
231 *ppv = p->mempin;
232 p->mempin->vt->AddRef((IUnknown*)*ppv);
233 return 0;
234 }
235
236 Debug printf("Unknown interface : %08x-%04x-%04x-%02x%02x-"
237 "%02x%02x%02x%02x%02x%02x\n",
238 iid->f1, iid->f2, iid->f3,
239 (unsigned char)iid->f4[1], (unsigned char)iid->f4[0],
240 (unsigned char)iid->f4[2], (unsigned char)iid->f4[3],
241 (unsigned char)iid->f4[4], (unsigned char)iid->f4[5],
242 (unsigned char)iid->f4[6], (unsigned char)iid->f4[7]);
243 return E_NOINTERFACE;
244 }
245
246 // IPin methods
247
248 /**
249 * \brief IPin::Connect (connects pin to another pin)
250 *
251 * \param[in] This pointer to IPin interface
252 * \param[in] pReceivePin pointer to IPin interface of remote pin
253 * \param[in] pmt suggested media type for link. Can be NULL (any media type)
254 *
255 * \return S_OK - success.
256 * \return VFW_E_ALREADY_CONNECTED - pin already connected
257 * \return VFW_E_NOT_STOPPED - filter is active
258 * \return VFW_E_TYPE_NOT_ACCEPT - type is not acceptable
259 * \return Apropriate error code otherwise.
260 *
261 */
COutputPin_Connect(IPin * This,IPin * pReceivePin,AM_MEDIA_TYPE * pmt)262 static HRESULT STDCALL COutputPin_Connect(IPin * This,
263 /* [in] */ IPin *pReceivePin,
264 /* [in] */ /* const */ AM_MEDIA_TYPE *pmt)
265 {
266 Debug printf("COutputPin_Connect(%p) called\n",This);
267 /*
268 *pmt=((COutputPin*)This)->type;
269 if(pmt->cbFormat>0)
270 {
271 pmt->pbFormat=malloc(pmt->cbFormat);
272 memcpy(pmt->pbFormat, ((COutputPin*)This)->type.pbFormat, pmt->cbFormat);
273 }
274 */
275 //return E_NOTIMPL;
276 return 0;// XXXXXXXXXXXXX CHECKME XXXXXXXXXXXXXXX
277 // if I put return 0; here, it crashes
278 }
279
280 /**
281 * \brief IPin::ReceiveConnection (accepts a connection from another pin)
282 *
283 * \param[in] This pointer to IPin interface
284 * \param[in] pConnector connecting pin's IPin interface
285 * \param[in] pmt suggested media type for connection
286 *
287 * \return S_OK - success
288 * \return E_POINTER - Null pointer
289 * \return VFW_E_ALREADY_CONNECTED - pin already connected
290 * \return VFW_E_NOT_STOPPED - filter is active
291 * \return VFW_E_TYPE_NOT_ACCEPT - type is not acceptable
292 *
293 * \note
294 * When returning S_OK method should also do the following:
295 * - store media type and return the same type in IPin::ConnectionMediaType
296 * - store pConnector and return it in IPin::ConnectedTo
297 *
298 */
COutputPin_ReceiveConnection(IPin * This,IPin * pConnector,const AM_MEDIA_TYPE * pmt)299 static HRESULT STDCALL COutputPin_ReceiveConnection(IPin * This,
300 /* [in] */ IPin *pConnector,
301 /* [in] */ const AM_MEDIA_TYPE *pmt)
302 {
303 Debug printf("COutputPin_ReceiveConnection(%p) called\n", This);
304 ((COutputPin*)This)->remote = pConnector;
305 return 0;
306 }
307
308 /**
309 * \brief IPin::Disconnect (accepts a connection from another pin)
310 *
311 * \param[in] This pointer to IPin interface
312 *
313 * \return S_OK - success
314 * \return S_FALSE - pin was not connected
315 * \return VFW_E_NOT_STOPPED - filter is active
316 *
317 * \note
318 * To break connection you have to also call Disconnect on other pin
319 */
COutputPin_Disconnect(IPin * This)320 static HRESULT STDCALL COutputPin_Disconnect(IPin * This)
321 {
322 Debug printf("COutputPin_Disconnect(%p) called\n", This);
323 return 1;
324 }
325
326 /**
327 * \brief IPin::ConnectedTo (retrieves pointer to the connected pin, if such exist)
328 *
329 * \param[in] This pointer to IPin interface
330 * \param[out] pPin pointer to remote pin's IPin interface
331 *
332 * \return S_OK - success
333 * \return E_POINTER - Null pointer
334 * \return VFW_E_NOT_CONNECTED - pin is not connected
335 *
336 * \note
337 * Caller must call Release on received IPin, when done
338 */
COutputPin_ConnectedTo(IPin * This,IPin ** pPin)339 static HRESULT STDCALL COutputPin_ConnectedTo(IPin * This,
340 /* [out] */ IPin **pPin)
341 {
342 Debug printf("COutputPin_ConnectedTo(%p) called\n", This);
343 if (!pPin)
344 return E_INVALIDARG;
345 *pPin = ((COutputPin*)This)->remote;
346 return 0;
347 }
348
349 /**
350 * \brief IPin::ConnectionMediaType (retrieves media type for connection, if such exist)
351 *
352 * \param[in] This pointer to IPin interface
353 * \param[out] pmt pointer to AM_MEDIA_TYPE, that receives connection media type
354 *
355 * \return S_OK - success
356 * \return E_POINTER - Null pointer
357 * \return VFW_E_NOT_CONNECTED - pin is not connected
358 *
359 */
COutputPin_ConnectionMediaType(IPin * This,AM_MEDIA_TYPE * pmt)360 static HRESULT STDCALL COutputPin_ConnectionMediaType(IPin * This,
361 /* [out] */ AM_MEDIA_TYPE *pmt)
362 {
363 Debug printf("COutputPin_ConnectionMediaType(%p) called\n",This);
364 if (!pmt)
365 return E_INVALIDARG;
366 CopyMediaType(pmt,&(((COutputPin*)This)->type));
367 return 0;
368 }
369
370 /**
371 * \brief IPin::QueryPinInfo (retrieves information about the pin)
372 *
373 * \param[in] This pointer to IPin interface
374 * \param[out] pInfo pointer to PIN_INFO structure, that receives pin info
375 *
376 * \return S_OK - success
377 * \return E_POINTER - Null pointer
378 *
379 * \note
380 * If pInfo->pFilter is not NULL, then caller must call Release on pInfo->pFilter when done
381 *
382 */
COutputPin_QueryPinInfo(IPin * This,PIN_INFO * pInfo)383 static HRESULT STDCALL COutputPin_QueryPinInfo(IPin * This,
384 /* [out] */ PIN_INFO *pInfo)
385 {
386 return output_unimplemented("COutputPin_QueryPinInfo", This);
387 }
388
389 /**
390 * \brief IPin::QueryDirection (retrieves pin direction)
391 *
392 * \param[in] This pointer to IPin interface
393 * \param[out] pPinDir pointer to variable, that receives pin direction (PINDIR_INPUT,PINDIR_OUTPUT)
394 *
395 * \return S_OK - success
396 * \return E_POINTER - Null pointer
397 *
398 */
COutputPin_QueryDirection(IPin * This,PIN_DIRECTION * pPinDir)399 static HRESULT STDCALL COutputPin_QueryDirection(IPin * This,
400 /* [out] */ PIN_DIRECTION *pPinDir)
401 {
402 Debug printf("COutputPin_QueryDirection(%p) called\n", This);
403 if (!pPinDir)
404 return E_INVALIDARG;
405 *pPinDir = PINDIR_INPUT;
406 return 0;
407 }
408
409 /**
410 * \brief IPin::QueryId (retrieves pin identificator)
411 *
412 * \param[in] This pointer to IPin interface
413 * \param[out] Id adress of variable, that receives string with pin's Id.
414 *
415 * \return S_OK - success
416 * \return E_OUTOFMEMORY - Insufficient memory
417 * \return E_POINTER - Null pointer
418 *
419 * \note
420 * Pin's Id is not the same as pin's name
421 *
422 */
COutputPin_QueryId(IPin * This,LPWSTR * Id)423 static HRESULT STDCALL COutputPin_QueryId(IPin * This,
424 /* [out] */ LPWSTR *Id)
425 {
426 return output_unimplemented("COutputPin_QueryId", This);
427 }
428
429 /**
430 * \brief IPin::QueryAccept (determines can media type be accepted or not)
431 *
432 * \param[in] This pointer to IPin interface
433 * \param[in] pmt Media type to check
434 *
435 * \return S_OK - success
436 * \return S_FALSE - pin rejects media type
437 *
438 */
COutputPin_QueryAccept(IPin * This,const AM_MEDIA_TYPE * pmt)439 static HRESULT STDCALL COutputPin_QueryAccept(IPin * This,
440 /* [in] */ const AM_MEDIA_TYPE *pmt)
441 {
442 return output_unimplemented("COutputPin_QueryAccept", This);
443 }
444
445 /**
446 * \brief IPin::EnumMediaTypes (enumerates the pin's preferred media types)
447 *
448 * \param[in] This pointer to IPin interface
449 * \param[out] ppEnum adress of variable that receives pointer to IEnumMEdiaTypes interface
450 *
451 * \return S_OK - success
452 * \return E_OUTOFMEMORY - Insufficient memory
453 * \return E_POINTER - Null pointer
454 *
455 * \note
456 * Caller must call Release on received interface when done
457 *
458 */
COutputPin_EnumMediaTypes(IPin * This,IEnumMediaTypes ** ppEnum)459 static HRESULT STDCALL COutputPin_EnumMediaTypes(IPin * This,
460 /* [out] */ IEnumMediaTypes **ppEnum)
461 {
462 Debug printf("COutputPin_EnumMediaTypes(%p) called\n",This);
463 if (!ppEnum)
464 return E_INVALIDARG;
465 *ppEnum = (IEnumMediaTypes*) CEnumMediaTypesCreate(&((COutputPin*)This)->type);
466 return 0;
467 }
468
469 /**
470 * \brief IPin::QueryInternalConnections (retries pin's internal connections)
471 *
472 * \param[in] This pointer to IPin interface
473 * \param[out] apPin Array that receives pins, internally connected to this
474 * \param[in,out] nPint Size of an array
475 *
476 * \return S_OK - success
477 * \return S_FALSE - pin rejects media type
478 * \return E_NOTIMPL - not implemented
479 *
480 */
COutputPin_QueryInternalConnections(IPin * This,IPin ** apPin,ULONG * nPin)481 static HRESULT STDCALL COutputPin_QueryInternalConnections(IPin * This,
482 /* [out] */ IPin **apPin,
483 /* [out][in] */ ULONG *nPin)
484 {
485 return output_unimplemented("COutputPin_QueryInternalConnections", This);
486 }
487
488 /**
489 * \brief IPin::EndOfStream (notifies pin, that no data is expected, until new run command)
490 *
491 * \param[in] This pointer to IPin interface
492 *
493 * \return S_OK - success
494 * \return E_UNEXPECTED - The pin is output pin
495 *
496 * \note
497 * IMemoryInputPin::Receive,IMemoryInputPin::ReceiveMultiple, IMemoryInputPin::EndOfStream,
498 * IMemAllocator::GetBuffer runs in different (streaming) thread then other
499 * methods (application thread).
500 * IMemoryInputPin::NewSegment runs either in streaming or application thread.
501 * Developer must use critical sections for thread-safing work.
502 *
503 */
COutputPin_EndOfStream(IPin * This)504 static HRESULT STDCALL COutputPin_EndOfStream(IPin * This)
505 {
506 return output_unimplemented("COutputPin_EndOfStream", This);
507 }
508
509 /**
510 * \brief IPin::BeginFlush (begins a flush operation)
511 *
512 * \param[in] This pointer to IPin interface
513 *
514 * \return S_OK - success
515 * \return E_UNEXPECTED - The pin is output pin
516 *
517 */
COutputPin_BeginFlush(IPin * This)518 static HRESULT STDCALL COutputPin_BeginFlush(IPin * This)
519 {
520 return output_unimplemented("COutputPin_BeginFlush", This);
521 }
522
523 /**
524 * \brief IPin::EndFlush (ends a flush operation)
525 *
526 * \param[in] This pointer to IPin interface
527 *
528 * \return S_OK - success
529 * \return E_UNEXPECTED - The pin is output pin
530 *
531 */
COutputPin_EndFlush(IPin * This)532 static HRESULT STDCALL COutputPin_EndFlush(IPin * This)
533 {
534 return output_unimplemented("COutputPin_EndFlush", This);
535 }
536
537 /**
538 * \brief IPin::NewSegment (media sample received after this call grouped as segment with common
539 * start,stop time and rate)
540 *
541 * \param[in] This pointer to IPin interface
542 * \param[in] tStart start time of new segment
543 * \param[in] tStop end time of new segment
544 * \param[in] dRate rate at wich segment should be processed
545 *
546 * \return S_OK - success
547 * \return E_UNEXPECTED - The pin is output pin
548 *
549 */
COutputPin_NewSegment(IPin * This,REFERENCE_TIME tStart,REFERENCE_TIME tStop,double dRate)550 static HRESULT STDCALL COutputPin_NewSegment(IPin * This,
551 /* [in] */ REFERENCE_TIME tStart,
552 /* [in] */ REFERENCE_TIME tStop,
553 /* [in] */ double dRate)
554 {
555 Debug printf("COutputPin_NewSegment(%Ld,%Ld,%f) called\n",
556 tStart, tStop, dRate);
557 return 0;
558 }
559
560
561
562 // IMemInputPin->IUnknown methods
563
564 /**
565 * \brief IUnknown::QueryInterface (query object for interface)
566 *
567 * \param[in] This pointer to IUnknown interface
568 * \param[in] iid GUID of requested interface
569 * \param[out] ppv receives pointer to interface
570 *
571 * \return S_OK - success (and *ppv contains valid pointer)
572 * \return E_NOINTERFACE - interface not found (and *ppv was set NULL)
573 *
574 * \note
575 * Make sure to call Release on received interface when you are done
576 *
577 */
COutputMemPin_QueryInterface(IUnknown * This,const GUID * iid,void ** ppv)578 static HRESULT STDCALL COutputMemPin_QueryInterface(IUnknown* This, const GUID* iid, void** ppv)
579 {
580 COutputMemPin* p = (COutputMemPin*)This;
581
582 Debug printf("COutputMemPin_QueryInterface(%p) called\n", This);
583 if (!ppv)
584 return E_INVALIDARG;
585
586 if(!memcmp(iid, &IID_IUnknown, 16))
587 {
588 *ppv = p;
589 p->vt->AddRef(This);
590 return 0;
591 }
592 /*if(!memcmp(iid, &IID_IPin, 16))
593 {
594 COutputPin* ptr=(COutputPin*)(This-1);
595 *ppv=(void*)ptr;
596 AddRef((IUnknown*)ptr);
597 return 0;
598 }*/
599 if(!memcmp(iid, &IID_IMemInputPin, 16))
600 {
601 *ppv = p;
602 p->vt->AddRef(This);
603 return 0;
604 }
605 Debug printf("Unknown interface : %08x-%04x-%04x-%02x%02x-" \
606 "%02x%02x%02x%02x%02x%02x\n",
607 iid->f1, iid->f2, iid->f3,
608 (unsigned char)iid->f4[1], (unsigned char)iid->f4[0],
609 (unsigned char)iid->f4[2], (unsigned char)iid->f4[3],
610 (unsigned char)iid->f4[4], (unsigned char)iid->f4[5],
611 (unsigned char)iid->f4[6], (unsigned char)iid->f4[7]);
612 return E_NOINTERFACE;
613 }
614
615 // IMemInputPin methods
616
617 /**
618 * \brief IMemInputPin::GetAllocator (retrives memory allocator, proposed by pin)
619 *
620 * \param[in] This pointer to IMemInputPin interface
621 * \param[out] ppAllocator address of variable that receives allocator's IMemAllocator interface
622 *
623 * \return S_OK - success
624 * \return VFW_E_NO_ALLOCATOR - No allocator
625 *
626 * \note
627 * Make sure to call Release on received interface when you are done
628 *
629 */
COutputMemPin_GetAllocator(IMemInputPin * This,IMemAllocator ** ppAllocator)630 static HRESULT STDCALL COutputMemPin_GetAllocator(IMemInputPin* This,
631 /* [out] */ IMemAllocator** ppAllocator)
632 {
633 Debug printf("COutputMemPin_GetAllocator(%p, %p) called\n", This->vt, ppAllocator);
634 *ppAllocator = (IMemAllocator*) MemAllocatorCreate();
635 return 0;
636 }
637
638 /**
639 *
640 * \brief IMemInputPin::NotifyAllocator (specifies an allocator for the connection)
641 *
642 * \param[in] This pointer to IMemInputPin interface
643 * \param[in] pAllocator allocator's IMemAllocator interface
644 * \param[in] bReadOnly specifies whether samples from allocator are readonly
645 *
646 * \return S_OK - success
647 * \return Apropriate error code otherwise
648 *
649 */
COutputMemPin_NotifyAllocator(IMemInputPin * This,IMemAllocator * pAllocator,int bReadOnly)650 static HRESULT STDCALL COutputMemPin_NotifyAllocator(IMemInputPin* This,
651 /* [in] */ IMemAllocator* pAllocator,
652 /* [in] */ int bReadOnly)
653 {
654 Debug printf("COutputMemPin_NotifyAllocator(%p, %p) called\n", This, pAllocator);
655 ((COutputMemPin*)This)->pAllocator = (MemAllocator*) pAllocator;
656 return 0;
657 }
658
659 /**
660 * \brief IMemInputPin::GetAllocatorRequirements (retrieves allocator properties requested by
661 * input pin)
662 *
663 * \param[in] This pointer to IMemInputPin interface
664 * \param[out] pProps pointer to a structure that receives allocator properties
665 *
666 * \return S_OK - success
667 * \return E_NOTIMPL - Not implemented
668 * \return E_POINTER - Null pointer
669 *
670 */
COutputMemPin_GetAllocatorRequirements(IMemInputPin * This,ALLOCATOR_PROPERTIES * pProps)671 static HRESULT STDCALL COutputMemPin_GetAllocatorRequirements(IMemInputPin* This,
672 /* [out] */ ALLOCATOR_PROPERTIES* pProps)
673 {
674 return output_unimplemented("COutputMemPin_GetAllocatorRequirements", This);
675 }
676
677 /**
678 * \brief IMemInputPin::Receive (receives the next media sample int thre stream)
679 *
680 * \param[in] This pointer to IMemInputPin interface
681 * \param[in] pSample pointer to sample's IMediaSample interface
682 *
683 * \return S_OK - success
684 * \return S_FALSE - The sample was rejected
685 * \return E_POINTER - Null pointer
686 * \return VFW_E_INVALIDMEDIATYPE - invalid media type
687 * \return VFW_E_RUNTIME_ERROR - run-time error occured
688 * \return VFW_E_WRONG_STATE - pin is stopped
689 *
690 * \remarks
691 * Method san do on of the following:
692 * - reject sample
693 * - accept sample and process it in another thread
694 * - accept sample and process it before returning
695 *
696 * In second case method should increase reference count for sample (through AddRef)
697 * In the last case method might block indefinitely. If this might
698 * happen IMemInpuPin::ReceiveCAnBlock returns S_OK
699 *
700 * \note
701 * IMemoryInputPin::Receive,IMemoryInputPin::ReceiveMultiple, IMemoryInputPin::EndOfStream,
702 * IMemAllocator::GetBuffer runs in different (streaming) thread then other
703 * methods (application thread).
704 * IMemoryInputPin::NewSegment runs either in streaming or application thread.
705 * Developer must use critical sections for thread-safing work.
706 *
707 */
COutputMemPin_Receive(IMemInputPin * This,IMediaSample * pSample)708 static HRESULT STDCALL COutputMemPin_Receive(IMemInputPin* This,
709 /* [in] */ IMediaSample* pSample)
710 {
711 Debug printf("COutputMemPin_Receive(%p) called\n", This);
712 if (!pSample)
713 return E_INVALIDARG;
714
715 if(((COutputMemPin*)This)->parent->SampleProc)
716 return ((COutputMemPin*)This)->parent->SampleProc(((COutputMemPin*)This)->parent->pUserData,pSample);
717 //reject sample
718 return S_FALSE;
719 }
720
721 /**
722 * \brief IMemInputPin::ReceiveMultiple (receives multiple samples in the stream)
723 *
724 * \param[in] This pointer to IMemInputPin interface
725 * \param[in] pSamples pointer to array with samples
726 * \param[in] nSamples number of samples in array
727 * \param[out] nSamplesProcessed number of processed samples
728 *
729 * \return S_OK - success
730 * \return S_FALSE - The sample was rejected
731 * \return E_POINTER - Null pointer
732 * \return VFW_E_INVALIDMEDIATYPE - invalid media type
733 * \return VFW_E_RUNTIME_ERROR - run-time error occured
734 * \return VFW_E_WRONG_STATE - pin is stopped
735 *
736 * \remarks
737 * This method behaves like IMemInputPin::Receive but for array of samples
738 *
739 * \note
740 * IMemoryInputPin::Receive,IMemoryInputPin::ReceiveMultiple, IMemoryInputPin::EndOfStream,
741 * IMemAllocator::GetBuffer runs in different (streaming) thread then other
742 * methods (application thread).
743 * IMemoryInputPin::NewSegment runs either in streaming or application thread.
744 * Developer must use critical sections for thread-safing work.
745 *
746 */
COutputMemPin_ReceiveMultiple(IMemInputPin * This,IMediaSample ** pSamples,long nSamples,long * nSamplesProcessed)747 static HRESULT STDCALL COutputMemPin_ReceiveMultiple(IMemInputPin * This,
748 /* [size_is][in] */ IMediaSample **pSamples,
749 /* [in] */ long nSamples,
750 /* [out] */ long *nSamplesProcessed)
751 {
752 HRESULT hr;
753 Debug printf("COutputMemPin_ReceiveMultiple(%p) %ld\n", This,nSamples);
754 for(*nSamplesProcessed=0; *nSamplesProcessed < nSamples; *nSamplesProcessed++) {
755 hr = This->vt->Receive(This,pSamples[*nSamplesProcessed]);
756 if (hr != S_OK) break;
757 }
758 return hr;
759 }
760
761 /**
762 * \brief IMemInputPin::ReceiveCanBlock (determines whether IMemInputPin:::Receive might block)
763 *
764 * \param[in] This pointer to IMemInputPin interface
765 *
766 * \return S_OK - the pin might block
767 * \return S_FALSE - the pin will not block
768 *
769 */
COutputMemPin_ReceiveCanBlock(IMemInputPin * This)770 static HRESULT STDCALL COutputMemPin_ReceiveCanBlock(IMemInputPin * This)
771 {
772 return output_unimplemented("COutputMemPin_ReceiveCanBlock", This);
773 }
774
775 /**
776 * \brief COutputPin::SetNewFormat(sets new media format for the pin)
777 *
778 * \param[in] This pointer to COutputPin class
779 * \param[in] amt new media format
780 *
781 */
COutputPin_SetNewFormat(COutputPin * This,const AM_MEDIA_TYPE * amt)782 static void COutputPin_SetNewFormat(COutputPin* This, const AM_MEDIA_TYPE* amt)
783 {
784 CopyMediaType(&(This->type),amt);
785 }
786
787 /**
788 * \brief COutputPin destructor
789 *
790 * \param[in] This pointer to COutputPin class
791 *
792 */
COutputPin_Destroy(COutputPin * This)793 static void COutputPin_Destroy(COutputPin* This)
794 {
795 free(This->mempin->vt);
796 free(This->mempin);
797 free(This->vt);
798 FreeMediaType(&(This->type));
799 free(This);
800 }
801
802 /**
803 * \brief IUnknown::AddRef (increases reference counter for interface)
804 *
805 * \param[in] This pointer to IUnknown class
806 *
807 * \return new value of reference counter
808 *
809 * \remarks
810 * Return value should be used only for debug purposes
811 *
812 */
COutputPin_AddRef(IUnknown * This)813 static HRESULT STDCALL COutputPin_AddRef(IUnknown* This)
814 {
815 Debug printf("COutputPin_AddRef(%p) called (%d)\n", This, ((COutputPin*)This)->refcount);
816 ((COutputPin*)This)->refcount++;
817 return 0;
818 }
819
820 /**
821 * \brief IUnknown::Release (desreases reference counter for interface)
822 *
823 * \param[in] This pointer to IUnknown class
824 *
825 * \return new value of reference counter
826 *
827 * \remarks
828 * When reference counter reaches zero calls destructor
829 * Return value should be used only for debug purposes
830 *
831 */
COutputPin_Release(IUnknown * This)832 static HRESULT STDCALL COutputPin_Release(IUnknown* This)
833 {
834 Debug printf("COutputPin_Release(%p) called (%d)\n", This, ((COutputPin*)This)->refcount);
835 if (--((COutputPin*)This)->refcount <= 0)
836 COutputPin_Destroy((COutputPin*)This);
837
838 return 0;
839 }
840
841 /**
842 * \brief IUnknown::AddRef (increases reference counter for interface)
843 *
844 * \param[in] This pointer to IUnknown class
845 *
846 * \return new value of reference counter
847 *
848 * \remarks
849 * Return value should be used only for debug purposes
850 *
851 */
COutputMemPin_AddRef(IUnknown * This)852 static HRESULT STDCALL COutputMemPin_AddRef(IUnknown* This)
853 {
854 COutputMemPin* p = (COutputMemPin*) This;
855 Debug printf("COutputMemPin_AddRef(%p) called (%p, %d)\n", p, p->parent, p->parent->refcount);
856 p->parent->refcount++;
857 return 0;
858 }
859
860 /**
861 * \brief IUnknown::Release (desreases reference counter for interface)
862 *
863 * \param[in] This pointer to IUnknown class
864 *
865 * \return new value of reference counter
866 *
867 * \remarks
868 * When reference counter reaches zero calls destructor
869 * Return value should be used only for debug purposes
870 *
871 */
COutputMemPin_Release(IUnknown * This)872 static HRESULT STDCALL COutputMemPin_Release(IUnknown* This)
873 {
874 COutputMemPin* p = (COutputMemPin*) This;
875 Debug printf("COutputMemPin_Release(%p) called (%p, %d)\n",
876 p, p->parent, p->parent->refcount);
877 if (--p->parent->refcount <= 0)
878 COutputPin_Destroy(p->parent);
879 return 0;
880 }
881
882 /**
883 * \brief COutputPin constructor
884 *
885 * \param[in] amt media type for pin
886 *
887 * \return pointer to COutputPin if success
888 * \return NULL if error occured
889 *
890 */
COutputPinCreate(const AM_MEDIA_TYPE * amt,SAMPLEPROC SampleProc,void * pUserData)891 COutputPin* COutputPinCreate(const AM_MEDIA_TYPE* amt,SAMPLEPROC SampleProc,void* pUserData)
892 {
893 COutputPin* This = malloc(sizeof(COutputPin));
894 IMemInputPin_vt* ivt;
895
896 if (!This)
897 return NULL;
898
899 This->vt = malloc(sizeof(IPin_vt));
900 This->mempin = malloc(sizeof(COutputMemPin));
901 ivt = malloc(sizeof(IMemInputPin_vt));
902
903 if (!This->vt || !This->mempin || !ivt)
904 {
905 COutputPin_Destroy(This);
906 free(ivt);
907 return NULL;
908 }
909
910 This->SampleProc=SampleProc;
911 This->pUserData=pUserData;
912
913 This->mempin->vt = ivt;
914
915 This->refcount = 1;
916 This->remote = 0;
917 CopyMediaType(&(This->type),amt);
918
919 This->vt->QueryInterface = COutputPin_QueryInterface;
920 This->vt->AddRef = COutputPin_AddRef;
921 This->vt->Release = COutputPin_Release;
922 This->vt->Connect = COutputPin_Connect;
923 This->vt->ReceiveConnection = COutputPin_ReceiveConnection;
924 This->vt->Disconnect = COutputPin_Disconnect;
925 This->vt->ConnectedTo = COutputPin_ConnectedTo;
926 This->vt->ConnectionMediaType = COutputPin_ConnectionMediaType;
927 This->vt->QueryPinInfo = COutputPin_QueryPinInfo;
928 This->vt->QueryDirection = COutputPin_QueryDirection;
929 This->vt->QueryId = COutputPin_QueryId;
930 This->vt->QueryAccept = COutputPin_QueryAccept;
931 This->vt->EnumMediaTypes = COutputPin_EnumMediaTypes;
932 This->vt->QueryInternalConnections = COutputPin_QueryInternalConnections;
933 This->vt->EndOfStream = COutputPin_EndOfStream;
934 This->vt->BeginFlush = COutputPin_BeginFlush;
935 This->vt->EndFlush = COutputPin_EndFlush;
936 This->vt->NewSegment = COutputPin_NewSegment;
937
938 This->mempin->vt->QueryInterface = COutputMemPin_QueryInterface;
939 This->mempin->vt->AddRef = COutputMemPin_AddRef;
940 This->mempin->vt->Release = COutputMemPin_Release;
941 This->mempin->vt->GetAllocator = COutputMemPin_GetAllocator;
942 This->mempin->vt->NotifyAllocator = COutputMemPin_NotifyAllocator;
943 This->mempin->vt->GetAllocatorRequirements = COutputMemPin_GetAllocatorRequirements;
944 This->mempin->vt->Receive = COutputMemPin_Receive;
945 This->mempin->vt->ReceiveMultiple = COutputMemPin_ReceiveMultiple;
946 This->mempin->vt->ReceiveCanBlock = COutputMemPin_ReceiveCanBlock;
947
948 This->mempin->frame_size_pointer = 0;
949 This->mempin->frame_pointer = 0;
950 This->mempin->pAllocator = 0;
951 This->mempin->refcount = 1;
952 This->mempin->parent = This;
953
954 This->SetNewFormat = COutputPin_SetNewFormat;
955
956 return This;
957 }
958