]> git.vomp.tv Git - vompclient.git/blob - dssourcepin.cc
*** empty log message ***
[vompclient.git] / dssourcepin.cc
1 /*\r
2     Copyright 2004-2005 Chris Tallon\r
3 \r
4     This file is part of VOMP.\r
5 \r
6     VOMP is free software; you can redistribute it and/or modify\r
7     it under the terms of the GNU General Public License as published by\r
8     the Free Software Foundation; either version 2 of the License, or\r
9     (at your option) any later version.\r
10 \r
11     VOMP is distributed in the hope that it will be useful,\r
12     but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14     GNU General Public License for more details.\r
15 \r
16     You should have received a copy of the GNU General Public License\r
17     along with VOMP; if not, write to the Free Software\r
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19 */\r
20 #include "dssourcepin.h"\r
21 #include "dssourcefilter.h"\r
22 #include <Dvdmedia.h>\r
23 #include <mmreg.h>\r
24 \r
25 \r
26 class DsSFEnumMediaTypes: public IEnumMediaTypes {\r
27 public:\r
28   DsSFEnumMediaTypes(DsSourcePin* papa,ULONG pos=0);\r
29   virtual ~DsSFEnumMediaTypes();\r
30   virtual HRESULT STDMETHODCALLTYPE Next(ULONG nummedia,  AM_MEDIA_TYPE **pins,ULONG *fetched);\r
31   virtual HRESULT STDMETHODCALLTYPE Skip(ULONG numpin);\r
32   virtual HRESULT STDMETHODCALLTYPE Reset();\r
33   virtual HRESULT STDMETHODCALLTYPE Clone(IEnumMediaTypes **enuma);\r
34   virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id,void ** object);\r
35   virtual ULONG STDMETHODCALLTYPE AddRef();\r
36     virtual ULONG STDMETHODCALLTYPE Release();\r
37 protected:\r
38   DsSourcePin* parent;\r
39   ULONG curpos;\r
40   volatile long refs;\r
41 };\r
42 \r
43 DsSFEnumMediaTypes::DsSFEnumMediaTypes(DsSourcePin* papa,ULONG pos){\r
44   parent=papa;\r
45   curpos=pos;\r
46   parent->AddRef();\r
47   refs=0;\r
48 }\r
49 \r
50 DsSFEnumMediaTypes::~DsSFEnumMediaTypes(){\r
51   parent->Release();\r
52 }\r
53 \r
54 HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Next(ULONG numpin, AM_MEDIA_TYPE **pins,ULONG *fetched) {\r
55   int i;\r
56 \r
57   if (pins==NULL) return E_POINTER;\r
58   if (numpin!=1 && fetched==NULL) return E_INVALIDARG;\r
59   *fetched=0;\r
60 \r
61   for (i=0;(i<numpin);i++) {\r
62     pins[i]=(AM_MEDIA_TYPE*)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));\r
63     if (parent->GetMediaType(curpos+i,pins[i])!=S_OK) return S_FALSE;\r
64     curpos++;\r
65     if (fetched!=NULL)  (*fetched)++;\r
66   }\r
67   return S_OK;\r
68 }\r
69 \r
70 HRESULT STDMETHODCALLTYPE   DsSFEnumMediaTypes::Skip(ULONG numpin){\r
71   curpos+=numpin;\r
72   if (curpos>1) return S_FALSE;\r
73   return S_OK;\r
74 }\r
75 HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Reset(){\r
76   curpos=0;\r
77   return S_OK;\r
78 }\r
79 HRESULT STDMETHODCALLTYPE DsSFEnumMediaTypes::Clone(IEnumMediaTypes **enuma){\r
80   if (enuma==NULL) return E_POINTER;\r
81   *enuma=new DsSFEnumMediaTypes(parent,curpos);\r
82   (*enuma)->AddRef();\r
83   return S_OK;\r
84 }\r
85 \r
86 HRESULT STDMETHODCALLTYPE  DsSFEnumMediaTypes::QueryInterface(REFIID id,void ** object){\r
87   if (object==NULL) return E_POINTER;\r
88   if (id==IID_IUnknown ||id == IID_IEnumMediaTypes) {\r
89     *object=(IUnknown*)this;\r
90     ((IUnknown*)object)->AddRef();\r
91     return NOERROR;\r
92   } else {\r
93     *object=NULL;\r
94     return E_NOINTERFACE;\r
95   }\r
96 }\r
97 \r
98 \r
99 \r
100 ULONG STDMETHODCALLTYPE DsSFEnumMediaTypes::AddRef(){\r
101   InterlockedIncrement(&refs);\r
102   long tempref=refs;\r
103   if (tempref>1) return tempref;\r
104   else return 1;\r
105 }\r
106 \r
107 ULONG STDMETHODCALLTYPE DsSFEnumMediaTypes::Release(){\r
108   long tempref=InterlockedDecrement(&refs);\r
109 \r
110   if (tempref==0) {\r
111     refs++;\r
112     delete this;\r
113     return NULL;\r
114   } else {\r
115     if (tempref>1) return tempref;\r
116     else return 1;\r
117   }\r
118 }\r
119 \r
120 \r
121 void CopyMType(AM_MEDIA_TYPE* dest,const AM_MEDIA_TYPE*source) {\r
122   memcpy(dest,source,sizeof(AM_MEDIA_TYPE));\r
123   if (source->pbFormat!=NULL) {\r
124     dest->pbFormat=(BYTE*)CoTaskMemAlloc(dest->cbFormat);\r
125     memcpy(dest->pbFormat,source->pbFormat,dest->cbFormat);\r
126   }\r
127 }\r
128 void ReleaseMType(AM_MEDIA_TYPE* free) {\r
129   if (free->cbFormat!=NULL) CoTaskMemFree(free->pbFormat);\r
130   free->pbFormat=NULL;\r
131 }\r
132 \r
133 DsSourcePin::DsSourcePin(DsSourceFilter *pFilter,\r
134              HRESULT *phr,LPCWSTR pName,bool audio)\r
135 {\r
136   isaudiopin=audio;\r
137   m_pFilter=pFilter;\r
138   connected=NULL;\r
139   connectedinput=NULL;\r
140   allocator=NULL;\r
141 \r
142 \r
143 \r
144 }\r
145 \r
146 DsSourcePin::~DsSourcePin()\r
147 {\r
148 \r
149 \r
150 \r
151 }\r
152 \r
153 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryInterface(REFIID id,void ** object){\r
154   if (object==NULL) return E_POINTER;\r
155   if (id==IID_IUnknown) {\r
156     *object=(IUnknown*)this;\r
157     ((IUnknown*)object)->AddRef();\r
158     return NOERROR;\r
159   } else if (id==IID_IPin) {\r
160     *object=(IPin*)this;\r
161     ((IPin*)object)->AddRef();\r
162     return NOERROR;\r
163   } else {\r
164     *object=NULL;\r
165     return E_NOINTERFACE;\r
166   }\r
167 }\r
168 \r
169 ULONG STDMETHODCALLTYPE DsSourcePin::AddRef(){\r
170   return m_pFilter->AddRef();\r
171 \r
172 }\r
173 ULONG STDMETHODCALLTYPE DsSourcePin::Release(){\r
174   return m_pFilter->Release();\r
175 }\r
176 \r
177 \r
178 /*IPin*/\r
179 HRESULT STDMETHODCALLTYPE DsSourcePin::Connect(IPin *pinempf,const AM_MEDIA_TYPE *mtype) {\r
180   if (pinempf==NULL) return E_POINTER;\r
181   EnterCriticalSection(&m_pFilter->filterlock);\r
182 \r
183   if (connected!=NULL) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_ALREADY_CONNECTED;}\r
184   if (m_pFilter->mystate!=State_Stopped) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_NOT_STOPPED;}\r
185 \r
186 \r
187   bool gotmt=false;\r
188 \r
189   if (mtype!=NULL) {\r
190     if (CheckMediaType(mtype)==S_OK){\r
191       pinempf->AddRef();\r
192       if (pinempf->ReceiveConnection((IPin*)this,mtype)==S_OK) {\r
193         CopyMType(&medtype,mtype);\r
194         LeaveCriticalSection(&m_pFilter->filterlock);\r
195       } else {\r
196         LeaveCriticalSection(&m_pFilter->filterlock);\r
197         CoTaskMemFree(mtype->pbFormat);\r
198         pinempf->Release();\r
199         return VFW_E_TYPE_NOT_ACCEPTED;\r
200       }\r
201 \r
202     } else {\r
203       LeaveCriticalSection(&m_pFilter->filterlock);\r
204       CoTaskMemFree(mtype->pbFormat);\r
205       return VFW_E_TYPE_NOT_ACCEPTED;\r
206     }\r
207     CoTaskMemFree(mtype->pbFormat);\r
208   }else {\r
209     IEnumMediaTypes * emt;\r
210     EnumMediaTypes(&emt);\r
211     AM_MEDIA_TYPE  * emtype;\r
212     ULONG fetched=0;\r
213     pinempf->AddRef();\r
214     while (emt->Next(1,&emtype,&fetched)==S_OK) {\r
215       if (CheckMediaType(emtype)==S_OK){\r
216         if (pinempf->ReceiveConnection((IPin*)this,emtype)==S_OK) {\r
217           connected=pinempf;\r
218           CopyMType(&medtype,emtype);\r
219           CoTaskMemFree(emtype->pbFormat);\r
220                   CoTaskMemFree(emtype);\r
221           gotmt=true;\r
222           break;\r
223         }\r
224 \r
225       }\r
226       CoTaskMemFree(emtype->pbFormat);\r
227           CoTaskMemFree(emtype);\r
228     }\r
229     emt->Release();\r
230     if (gotmt==false) {\r
231       pinempf->EnumMediaTypes(&emt);\r
232       while (emt->Next(1,&emtype,&fetched)==S_OK) {\r
233         if (CheckMediaType(emtype)==S_OK){\r
234           if (pinempf->ReceiveConnection((IPin*)this,emtype)==S_OK) {\r
235             connected=pinempf;\r
236             CopyMType(&medtype,emtype);\r
237             CoTaskMemFree(emtype->pbFormat);\r
238                                                 CoTaskMemFree(emtype);\r
239             gotmt=true;\r
240             break;\r
241           }\r
242 \r
243         }\r
244         CoTaskMemFree(emtype->pbFormat);\r
245                 CoTaskMemFree(emtype);\r
246       }\r
247       emt->Release();\r
248       if (gotmt==false) {\r
249         pinempf->Release();\r
250         LeaveCriticalSection(&m_pFilter->filterlock);\r
251         return VFW_E_NO_ACCEPTABLE_TYPES;\r
252       }\r
253     }\r
254   }\r
255 \r
256   if (pinempf->QueryInterface(IID_IMemInputPin,(void**)&connectedinput)!=S_OK) {\r
257     LeaveCriticalSection(&m_pFilter->filterlock);\r
258     connected->Release();\r
259     connected=NULL;\r
260   /*  connectedinput->Release();\r
261     connectedinput=NULL;*/\r
262     return VFW_E_NO_TRANSPORT;\r
263   }\r
264   ALLOCATOR_PROPERTIES eigenall;\r
265   ZeroMemory(&eigenall,sizeof(eigenall));\r
266   connectedinput->GetAllocatorRequirements(&eigenall);\r
267   if (eigenall.cbAlign==0) eigenall.cbAlign=1;\r
268   connectedinput->GetAllocator(&allocator);\r
269   if (DecideBufferSize(allocator,&eigenall)==S_OK) {\r
270     if (connectedinput->NotifyAllocator(allocator,FALSE)==S_OK){\r
271       connected=pinempf;\r
272       LeaveCriticalSection(&m_pFilter->filterlock);\r
273       return S_OK;\r
274     }\r
275   }\r
276   if (allocator!=NULL) allocator->Release();\r
277   allocator=NULL;\r
278 \r
279   if (CoCreateInstance(CLSID_MemoryAllocator,0,CLSCTX_INPROC_SERVER,\r
280     IID_IMemAllocator,(void **)allocator)==S_OK) {\r
281       if (DecideBufferSize(allocator,&eigenall)==S_OK) {\r
282         if (connectedinput->NotifyAllocator(allocator,FALSE)==S_OK){\r
283           connected=pinempf;\r
284           LeaveCriticalSection(&m_pFilter->filterlock);\r
285         return S_OK;\r
286       }\r
287     }\r
288   }\r
289   if (allocator!=NULL) allocator->Release();\r
290   allocator=NULL;\r
291   connected->Release();\r
292   connected=NULL;\r
293   connectedinput->Release();\r
294   connectedinput=NULL;\r
295   LeaveCriticalSection(&m_pFilter->filterlock);\r
296   return VFW_E_NO_TRANSPORT;\r
297 \r
298 \r
299 \r
300 \r
301 }\r
302 HRESULT STDMETHODCALLTYPE DsSourcePin::ReceiveConnection(IPin *connect,\r
303                              const AM_MEDIA_TYPE *mtype){\r
304      return VFW_E_TYPE_NOT_ACCEPTED; //We have only output pins\r
305 }\r
306  HRESULT STDMETHODCALLTYPE DsSourcePin::Disconnect() {\r
307    EnterCriticalSection(&m_pFilter->filterlock);\r
308    if (connected!=NULL) {\r
309      if (m_pFilter->mystate!=State_Stopped) {LeaveCriticalSection(&m_pFilter->filterlock);return VFW_E_NOT_STOPPED;}\r
310      /*TODO: Decommit allocator*/\r
311      allocator->Decommit();\r
312      allocator->Release();\r
313      allocator=NULL;\r
314      ReleaseMType(&medtype);\r
315      connectedinput->Release();\r
316      connectedinput=NULL;\r
317      connected->Release();\r
318      connected=NULL;\r
319      LeaveCriticalSection(&m_pFilter->filterlock);\r
320      return S_OK;\r
321    }\r
322    LeaveCriticalSection(&m_pFilter->filterlock);\r
323    return S_FALSE;\r
324  }\r
325 \r
326  HRESULT STDMETHODCALLTYPE DsSourcePin::ConnectedTo(IPin **pin){\r
327    if (pin==NULL) return E_POINTER;\r
328    IPin* pinn=connected;\r
329    *pin=pinn;\r
330    if (pinn!=NULL) {\r
331      pinn->AddRef();\r
332      return S_OK;\r
333    } else {\r
334      return VFW_E_NOT_CONNECTED;\r
335    }\r
336  }\r
337  HRESULT STDMETHODCALLTYPE  DsSourcePin::ConnectionMediaType(AM_MEDIA_TYPE *mtype){\r
338    if (mtype==NULL) return E_POINTER;\r
339    if (connected!=NULL){\r
340     CopyMType(mtype,&medtype);\r
341     return S_OK;\r
342    } else {\r
343      ZeroMemory(mtype,sizeof(mtype));\r
344      return VFW_E_NOT_CONNECTED;\r
345    }\r
346  }\r
347  HRESULT STDMETHODCALLTYPE DsSourcePin::QueryPinInfo(PIN_INFO *info){\r
348    if (info==NULL) return E_POINTER;\r
349    info->dir=PINDIR_OUTPUT;\r
350    info->pFilter=(IBaseFilter*)m_pFilter;\r
351    if (m_pFilter) m_pFilter->AddRef();\r
352    if (isaudiopin) wcscpy(info->achName,L"Audio");\r
353    else wcscpy(info->achName,L"Video");\r
354    return S_OK;\r
355  }\r
356 \r
357  HRESULT STDMETHODCALLTYPE  DsSourcePin::QueryDirection(PIN_DIRECTION *dir){\r
358    if (dir==NULL) return E_POINTER;\r
359    *dir=PINDIR_OUTPUT;\r
360    return S_OK;\r
361  }\r
362  HRESULT STDMETHODCALLTYPE DsSourcePin::QueryId(LPWSTR *id){\r
363    if (id==NULL) return E_POINTER;\r
364    *id=(LPWSTR)CoTaskMemAlloc(12);\r
365    if (*id==NULL) return E_OUTOFMEMORY;\r
366 \r
367 \r
368    if (isaudiopin) wcscpy(*id,L"Audio");\r
369     else  wcscpy(*id, L"Video");\r
370     return S_OK;\r
371  }\r
372  HRESULT STDMETHODCALLTYPE  DsSourcePin::QueryAccept(const AM_MEDIA_TYPE *mtype) {\r
373    if (mtype==NULL) return S_FALSE;\r
374    if (CheckMediaType(mtype)==S_OK) return S_OK;\r
375    else return S_FALSE;\r
376  }\r
377  HRESULT STDMETHODCALLTYPE DsSourcePin::EnumMediaTypes(IEnumMediaTypes **enuma){\r
378 if (enuma==NULL) return E_POINTER;\r
379   *enuma=new DsSFEnumMediaTypes( this);\r
380   (*enuma)->AddRef();\r
381   return S_OK;\r
382 }\r
383 \r
384 HRESULT STDMETHODCALLTYPE DsSourcePin::QueryInternalConnections(IPin **pin,ULONG *numpin){\r
385   return E_NOTIMPL;\r
386 }\r
387 HRESULT STDMETHODCALLTYPE DsSourcePin::EndOfStream(){\r
388   return E_UNEXPECTED; //we are a output pin!\r
389 }\r
390 \r
391 HRESULT STDMETHODCALLTYPE DsSourcePin::NewSegment(REFERENCE_TIME start,REFERENCE_TIME stop,double rate){\r
392   return E_UNEXPECTED;//we are a output pin!\r
393 }\r
394 \r
395 HRESULT DsSourcePin::getCurrentMediaSample(IMediaSample**ms){\r
396   if (allocator!=NULL) return allocator->GetBuffer(ms,NULL,NULL,0);\r
397   else return E_NOINTERFACE;\r
398 }\r
399 \r
400 HRESULT DsSourcePin::deliver(IMediaSample * ms){\r
401   //EnterCriticalSection(&m_pFilter->filterlock);\r
402   HRESULT hres;\r
403   if (connectedinput!=NULL)hres= connectedinput->Receive(ms);\r
404   else hres= VFW_E_NOT_CONNECTED;\r
405   //LeaveCriticalSection(&m_pFilter->filterlock);\r
406   return hres;\r
407 \r
408 }\r
409 \r
410 HRESULT DsSourcePin::GetMediaType(int iPosition, AM_MEDIA_TYPE *pmt)\r
411 {\r
412   HRESULT hr;\r
413 \r
414   if (isaudiopin){\r
415     if (iPosition==0) {\r
416       ZeroMemory(pmt,sizeof(*pmt));\r
417       pmt->lSampleSize = 1;\r
418       pmt->bFixedSizeSamples = TRUE;\r
419       pmt->majortype=MEDIATYPE_Audio;\r
420       MPEG1WAVEFORMAT wfe;\r
421       ZeroMemory(&wfe,sizeof(wfe));\r
422       wfe.wfx.cbSize=22;\r
423       wfe.wfx.nSamplesPerSec=48000;\r
424       wfe.wfx.nChannels=2;\r
425       wfe.wfx.nAvgBytesPerSec=32000;\r
426       wfe.wfx.nBlockAlign=768;\r
427       wfe.wfx.wFormatTag=WAVE_FORMAT_MPEG;\r
428       wfe.fwHeadLayer=2;\r
429       wfe.dwHeadBitrate=256000;\r
430       wfe.fwHeadMode=ACM_MPEG_STEREO;\r
431       wfe.fwHeadModeExt=1;\r
432       wfe.wHeadEmphasis=1;\r
433       wfe.fwHeadFlags=ACM_MPEG_ID_MPEG1 |ACM_MPEG_ORIGINALHOME | ACM_MPEG_PROTECTIONBIT;\r
434       pmt->subtype=MEDIASUBTYPE_MPEG2_AUDIO;\r
435       pmt->formattype=FORMAT_WaveFormatEx;\r
436       pmt->cbFormat=sizeof(wfe);\r
437       pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(wfe));\r
438       memcpy(pmt->pbFormat,&wfe,sizeof(wfe));\r
439       pmt->lSampleSize=0;\r
440       hr=S_OK;\r
441 \r
442 \r
443         } else  {\r
444       hr=VFW_S_NO_MORE_ITEMS ;\r
445     }\r
446   } else {\r
447     if (iPosition == 0) {\r
448       ZeroMemory(pmt,sizeof(*pmt));\r
449       pmt->lSampleSize = 1;\r
450       pmt->bFixedSizeSamples = TRUE;\r
451       pmt->majortype=MEDIATYPE_Video;\r
452       hr=S_OK;\r
453       pmt->subtype=MEDIASUBTYPE_MPEG2_VIDEO;\r
454             pmt->formattype=FORMAT_MPEG2Video;\r
455 \r
456             MPEG2VIDEOINFO hdr;\r
457             ZeroMemory(&hdr,sizeof(hdr));\r
458             hdr.dwProfile=AM_MPEG2Profile_Main;\r
459             hdr.dwLevel=AM_MPEG2Level_Main;\r
460             hdr.hdr.bmiHeader.biSize = sizeof(hdr.hdr.bmiHeader);\r
461             hdr.hdr.bmiHeader.biWidth = 720;\r
462             hdr.hdr.bmiHeader.biHeight = 568;\r
463       pmt->cbFormat=sizeof(hdr);\r
464       pmt->pbFormat=(BYTE*)CoTaskMemAlloc(sizeof(hdr));\r
465       memcpy(pmt->pbFormat,&hdr,sizeof(hdr));\r
466 \r
467     } else {\r
468       hr=VFW_S_NO_MORE_ITEMS;\r
469     }\r
470   }\r
471   return hr ;\r
472 }\r
473 \r
474 HRESULT DsSourcePin::Inactive() {\r
475   if (allocator!=NULL) return allocator->Decommit();\r
476   return VFW_E_NO_ALLOCATOR;\r
477 }\r
478 \r
479 HRESULT DsSourcePin::Active() {\r
480   if (allocator!=NULL) return allocator->Commit();\r
481   return VFW_E_NO_ALLOCATOR;\r
482 }\r
483 \r
484 \r
485 HRESULT DsSourcePin::Run(REFERENCE_TIME reftime){\r
486   return NOERROR;\r
487 }\r
488 \r
489 // No description\r
490 HRESULT DsSourcePin::CheckMediaType(const AM_MEDIA_TYPE *pmt)\r
491 {\r
492     HRESULT res;\r
493 \r
494     if (isaudiopin) {\r
495         bool subtype=false;\r
496 #if 0 /* For future demands ac3 */\r
497     subtype=pmt->subtype==(MEDIASUBTYPE_DOLBY_AC3);\r
498 #endif\r
499     subtype=(pmt->subtype==(MEDIASUBTYPE_MPEG2_AUDIO));\r
500         if (pmt->majortype==MEDIATYPE_Audio && subtype) {\r
501       res = S_OK ;\r
502         } else {\r
503             res = S_FALSE ;\r
504         }\r
505     } else {\r
506         if (pmt->majortype==MEDIATYPE_Video &&\r
507                   pmt-> subtype==MEDIASUBTYPE_MPEG2_VIDEO) {\r
508       res = S_OK ;\r
509         } else {\r
510             res = S_FALSE ;\r
511         }\r
512     }\r
513     return res;\r
514 }\r
515 \r
516 HRESULT DsSourcePin::DecideBufferSize(IMemAllocator *pa,ALLOCATOR_PROPERTIES *all_pp){\r
517   HRESULT hr;\r
518 \r
519     if (pa==NULL)return E_POINTER;\r
520     if (all_pp==NULL) return E_POINTER;\r
521   if (isaudiopin) {\r
522     if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024)\r
523     {\r
524       //all_pp->cBuffers = 300;//old\r
525       all_pp->cBuffers = 10;\r
526       all_pp->cbBuffer = 64*1024;\r
527     }\r
528   } else {\r
529     if (all_pp->cBuffers*all_pp->cbBuffer < 300*64*1024)\r
530     {\r
531       //all_pp->cBuffers = 300;//old\r
532       all_pp->cBuffers = 30;\r
533       all_pp->cbBuffer = 64*1024;\r
534     }\r
535   }\r
536 \r
537     ALLOCATOR_PROPERTIES all_pp_cur;\r
538     hr =pa->SetProperties(all_pp,&all_pp_cur);\r
539     if (FAILED(hr))\r
540     {\r
541         return hr;\r
542     }\r
543     if (all_pp_cur.cbBuffer*all_pp_cur.cBuffers < all_pp->cBuffers*all_pp->cbBuffer)\r
544     {\r
545         return E_FAIL;\r
546     }\r
547 \r
548     return S_OK;\r
549 }\r
550 \r
551 \r