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