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