OSDN Git Service

54e428f66dbfc0f7643c27156968d5cbdc82e6b2
[qtheora/main.git] / Lib / QDecoder / QFilter.h
1 // QFilter.h
2 // 2009/05/29
3
4 #pragma once
5
6 /* */
7
8 // {AD5A1E4E-8050-467E-AEEC-5C99A23076B6}
9 DEFINE_GUID(CLSID_QDecoder,
10         0xad5a1e4e, 0x8050, 0x467e, 0xae, 0xec, 0x5c, 0x99, 0xa2, 0x30, 0x76, 0xb6);
11
12 // QFilter
13 [ uuid("AD5A1E4E-8050-467E-AEEC-5C99A23076B6") ]
14 class ATL_NO_VTABLE QFilter :
15         public ATL::CComObjectRootEx<ATL::CComMultiThreadModel>,
16         public ATL::CComCoClass<QFilter, &CLSID_QDecoder>,
17
18         public IBaseFilter,
19         public IMediaSeeking,
20         public IAMFilterMiscFlags,
21
22         public QPinHost {
23
24         ATL::CComCriticalSection m_cs;
25
26         QReader m_Reader;
27
28         QStreamer* m_pStreamer;
29
30         ATL::CComPtr<IReferenceClock> m_Clock;
31
32         IFilterGraph* m_pFGraph; /* weak */
33
34         ATL::CStringW m_Name;
35
36         enum {
37                 PID_Video = 0,
38                 PID_Audio,
39                 PINS
40         };
41
42         IPin* m_Pins[PINS];
43
44         QPinVideo* m_pPinVideo;
45         QPinAudio* m_pPinAudio;
46
47         FILTER_STATE m_state;
48
49         INT64 m_StartPos;
50
51 public:
52
53         DECLARE_NOT_AGGREGATABLE(QFilter)
54
55         DECLARE_PROTECT_FINAL_CONSTRUCT()
56
57         BEGIN_COM_MAP(QFilter)
58                 COM_INTERFACE_ENTRY(IPersist)
59                 COM_INTERFACE_ENTRY(IMediaFilter)
60                 COM_INTERFACE_ENTRY(IBaseFilter)
61                 COM_INTERFACE_ENTRY(IMediaSeeking)
62                 COM_INTERFACE_ENTRY(IAMFilterMiscFlags)
63         END_COM_MAP()
64
65 public:
66
67         QFilter() : m_pStreamer(0), m_pFGraph(0), m_pPinVideo(0),
68                 m_state(State_Stopped),
69                 m_StartPos(-1)
70         {
71                 memset(m_Pins, 0, sizeof(m_Pins));
72         }
73
74         ~QFilter()
75         {
76                 delete m_pStreamer;
77         }
78
79         HRESULT FinalConstruct()
80         {
81                 ATLTRACE("QFilter::FinalConstruct()\n");
82
83                 HRESULT hRslt = m_cs.Init();
84                 if (FAILED(hRslt)) {
85                         return hRslt;
86                 }
87
88                 {
89                         ATL::CComObject<QPinVideo>* pin = 0;
90                         HRESULT hRslt = ATL::CComObject<QPinVideo>::CreateInstance(&pin);
91                         if (FAILED(hRslt)) {
92                                 return hRslt;
93                         }
94
95                         hRslt = pin->Init(this, this);
96                         if (FAILED(hRslt)) {
97                                 delete pin;
98                                 return hRslt;
99                         }
100
101                         hRslt = pin->QueryInterface(m_Pins + PID_Video);
102                         if (FAILED(hRslt)) {
103                                 delete pin;
104                                 return hRslt;
105                         }
106
107                         m_pPinVideo = pin;
108                 }
109
110                 {
111                         ATL::CComObject<QPinAudio>* pin = 0;
112                         HRESULT hRslt = ATL::CComObject<QPinAudio>::CreateInstance(&pin);
113                         if (FAILED(hRslt)) {
114                                 return hRslt;
115                         }
116
117                         hRslt = pin->Init(this, this);
118                         if (FAILED(hRslt)) {
119                                 delete pin;
120                                 return hRslt;
121                         }
122
123                         hRslt = pin->QueryInterface(m_Pins + PID_Audio);
124                         if (FAILED(hRslt)) {
125                                 delete pin;
126                                 return hRslt;
127                         }
128
129                         m_pPinAudio = pin;
130                 }
131
132                 return S_OK;
133         }
134
135         void FinalRelease()
136         {
137                 ATLTRACE("QFilter::FinalRelease()\n");
138
139                 for (INT32 i = 0; i < PINS; i++) {
140                         if (m_Pins[i] != 0) {
141                                 m_Pins[i]->Release();
142                         }
143                 }
144
145                 m_cs.Term();
146         }
147
148         /* */
149
150         HRESULT Open(LPCWSTR path)
151         {
152                 if (!m_Reader.Open(path)) {
153                         return VFW_E_NOT_FOUND;
154                 }
155
156                 if (!m_Reader.Setup()) {
157                         return VFW_E_INVALID_FILE_FORMAT;
158                 }
159
160                 const QM_Track_t* vtrack = m_Reader.GetVideoTrack();
161                 if (vtrack != 0) {
162                         const QM_TrackVideo_t* v = vtrack->Video;
163
164                         m_pPinVideo->SetupVideoFormat(
165                                 v->PixelWidth,
166                                 v->PixelHeight,
167                                 vtrack->TrackDuration);
168                 }
169
170                 const QM_Track_t* atrack = m_Reader.GetAudioTrack();
171                 if (atrack != 0) {
172                         const QM_TrackAudio_t* a = atrack->Audio;
173
174                         m_pPinAudio->SetupAudioFormat(
175                                 a->Channels,
176                                 (INT32)(a->SamplingFrequency));
177                 }
178
179                 return S_OK;
180         }
181
182         /* */
183
184 public:
185
186         /* QPinHost */
187
188         virtual ATL::CComCriticalSection& FilterCSec()
189         {
190                 return m_cs;
191         }
192
193         virtual bool IsRunning()
194         {
195                 return (m_state != State_Stopped);
196         }
197
198         /* IPersist */
199
200         STDMETHOD(GetClassID)(
201                 LPCLSID pClassID)
202         {
203                 ATLTRACE("QFilter::GetClassID()\n");
204
205                 if (pClassID == 0) {
206                         return E_INVALIDARG;
207                 }
208
209                 *pClassID = __uuidof(QFilter);
210
211                 return S_OK;
212         }
213
214         /* IMediaFilter */
215
216         STDMETHOD(Stop)(void)
217         {
218                 ATLTRACE("QFilter::Stop()\n");
219
220                 ATL::CComCritSecLock<ATL::CComCriticalSection> lock(m_cs);
221
222                 HRESULT hRslt = StopStreaming();
223                 if (FAILED(hRslt)) {
224                         return hRslt;
225                 }
226
227                 m_state = State_Stopped;
228
229                 return S_OK;
230         }
231
232         STDMETHOD(Pause)(void)
233         {
234                 ATLTRACE("QFilter::Pause()\n");
235
236                 ATL::CComCritSecLock<ATL::CComCriticalSection> lock(m_cs);
237
238                 HRESULT hRslt = StartStreaming();
239                 if (FAILED(hRslt)) {
240                         return hRslt;
241                 }
242
243                 m_state = State_Paused;
244
245                 return S_OK;
246         }
247
248         STDMETHOD(Run)(REFERENCE_TIME tStart)
249         {
250                 ATLTRACE("QFilter::Run()\n");
251
252                 ATL::CComCritSecLock<ATL::CComCriticalSection> lock(m_cs);
253
254                 HRESULT hRslt = StartStreaming();
255                 if (FAILED(hRslt)) {
256                         return hRslt;
257                 }
258
259                 m_state = State_Running;
260
261                 return S_OK;
262         }
263
264         STDMETHOD(GetState)(
265                 DWORD         /* dwMilliSecsTimeout */,
266                 FILTER_STATE* State)
267         {
268                 ATLTRACE("QFilter::GetState()\n");
269
270                 ATL::CComCritSecLock<ATL::CComCriticalSection> lock(m_cs);
271
272                 if (State == 0) {
273                         return E_INVALIDARG;
274                 }
275
276                 *State = m_state;
277
278                 return S_OK;
279         }
280
281         STDMETHOD(SetSyncSource)(IReferenceClock* pClock)
282         {
283                 ATLTRACE("QFilter::SetSyncSource()\n");
284
285                 ATL::CComCritSecLock<ATL::CComCriticalSection> lock(m_cs);
286
287                 m_Clock = pClock;
288
289                 return S_OK;
290         }
291
292         STDMETHOD(GetSyncSource)(IReferenceClock** pClock)
293         {
294                 ATLTRACE("QFilter::GetSyncSource()\n");
295
296                 ATL::CComCritSecLock<ATL::CComCriticalSection> lock(m_cs);
297
298                 if (pClock == 0) {
299                         return E_INVALIDARG;
300                 }
301
302                 HRESULT hRslt = m_Clock.CopyTo(pClock);
303                 if (FAILED(hRslt)) {
304                         return hRslt;
305                 }
306
307                 return S_OK;
308         }
309
310         /* IBaseFilter */
311
312         STDMETHOD(EnumPins)(IEnumPins** ppEnum)
313         {
314                 ATLTRACE("QFilter::EnumPins()\n");
315
316                 if (ppEnum == 0) {
317                         return E_INVALIDARG;
318                 }
319
320                 HRESULT hRslt = QEnumPins::Create(m_Pins, m_Pins + PINS, static_cast<IBaseFilter*>(this), ppEnum);
321                 if (FAILED(hRslt)) {
322                         return hRslt;
323                 }
324
325                 return S_OK;
326         }
327
328         STDMETHOD(FindPin)(
329                 LPCWSTR Id,
330                 IPin**  ppPin)
331         {
332                 ATLTRACE("QFilter::FindPin()\n");
333
334                 if (Id == 0 || ppPin == 0) {
335                         return E_INVALIDARG;
336                 }
337
338                 IPin* pin = 0;
339
340                 if (wcscmp(Id, L"Video") == 0) {
341                         pin = m_Pins[PID_Video];
342
343                 } else if (wcscmp(Id, L"Audio") == 0) {
344                         pin = m_Pins[PID_Audio];
345                 }
346
347                 *ppPin = pin;
348
349                 if (pin == 0) {
350                         return VFW_E_NOT_FOUND;
351                 }
352
353                 pin->AddRef();
354
355                 return S_OK;
356         }
357
358         STDMETHOD(QueryFilterInfo)(
359                 FILTER_INFO* pInfo)
360         {
361                 ATLTRACE("QFilter::QueryFilterInfo()\n");
362
363                 ATL::CComCritSecLock<ATL::CComCriticalSection> lock(m_cs);
364
365                 if (pInfo == 0) {
366                         return E_INVALIDARG;
367                 }
368
369                 SIZE_T len = m_Name.GetLength();
370                 if (len > MAX_FILTER_NAME - 1) {
371                         len = MAX_FILTER_NAME - 1;
372                 }
373                 wcsncpy_s(pInfo->achName, MAX_FILTER_NAME, m_Name, len);
374
375                 pInfo->pGraph = m_pFGraph;
376                 if (m_pFGraph != 0) {
377                         m_pFGraph->AddRef();
378                 }
379
380                 return S_OK;
381         }
382
383         STDMETHOD(JoinFilterGraph)(
384                 IFilterGraph* pGraph,
385                 LPCWSTR       pName)
386         {
387                 ATLTRACE("QFilter::JoinFilterGraph()\n");
388
389                 ATL::CComCritSecLock<ATL::CComCriticalSection> lock(m_cs);
390
391                 m_pFGraph = pGraph; /* weak */
392
393                 if (pGraph != 0) {
394                         if (pName != 0) {
395                                 m_Name = pName;
396                         } else {
397                                 m_Name = L"QDecoder";
398                         }
399
400                 } else {
401                         m_Name.Empty();
402                 }
403
404                 return S_OK;
405         }
406
407         STDMETHOD(QueryVendorInfo)(
408                 LPWSTR* pVendorInfo)
409         {
410                 ATLTRACE("QFilter::QueryVendorInfo()\n");
411
412                 if (pVendorInfo == 0) {
413                         return E_INVALIDARG;
414                 }
415
416                 LPCWSTR NAME = L"Project Quilla";
417
418                 *pVendorInfo = static_cast<LPWSTR>(CoTaskMemAlloc((wcslen(NAME) + 1) * sizeof(WCHAR)));
419                 if (*pVendorInfo == 0) {
420                         return E_OUTOFMEMORY;
421                 }
422
423                 memcpy(*pVendorInfo, NAME, (wcslen(NAME) + 1) * sizeof(WCHAR));
424
425                 return S_OK;
426         }
427
428         /* IMediaSeeking */
429
430         STDMETHOD(GetCapabilities)(
431                 DWORD* pCapabilities)
432         {
433                 if (pCapabilities == 0) {
434                         return E_INVALIDARG;
435                 }
436
437                 *pCapabilities =
438                         AM_SEEKING_CanSeekAbsolute  |
439                         AM_SEEKING_CanSeekForwards  |
440                         AM_SEEKING_CanSeekBackwards |
441                         AM_SEEKING_CanGetDuration;
442
443                 return S_OK;
444         }
445
446         STDMETHOD(CheckCapabilities)(
447                 DWORD* pCapabilities)
448         {
449                 if (pCapabilities == 0) {
450                         return E_INVALIDARG;
451                 }
452
453                 DWORD c0 = *pCapabilities;
454
455                 DWORD cap = 0;
456                 GetCapabilities(&cap);
457
458                 *pCapabilities &= cap;
459
460                 if ((cap & c0) != cap) {
461                         return S_FALSE;
462                 }
463
464                 return S_OK;
465         }
466
467         STDMETHOD(IsFormatSupported)(
468                 const GUID* pFormat)
469         {
470                 if (pFormat == 0) {
471                         return E_INVALIDARG;
472                 }
473
474                 if (*pFormat != TIME_FORMAT_MEDIA_TIME) {
475                         return S_FALSE;
476                 }
477
478                 return S_OK;
479         }
480
481         STDMETHOD(QueryPreferredFormat)(
482                 GUID* pFormat)
483         {
484                 if (pFormat == 0) {
485                         return E_INVALIDARG;
486                 }
487
488                 *pFormat = TIME_FORMAT_MEDIA_TIME;
489
490                 return S_OK;
491         }
492
493         STDMETHOD(GetTimeFormat)(
494                 GUID* pFormat)
495         {
496                 if (pFormat == 0) {
497                         return E_INVALIDARG;
498                 }
499
500                 *pFormat = TIME_FORMAT_MEDIA_TIME;
501
502                 return S_OK;
503         }
504
505         STDMETHOD(IsUsingTimeFormat)(
506                 const GUID* pFormat)
507         {
508                 if (pFormat == 0) {
509                         return E_INVALIDARG;
510                 }
511
512                 if (*pFormat != TIME_FORMAT_MEDIA_TIME) {
513                         return S_FALSE;
514                 }
515
516                 return S_OK;
517         }
518
519         STDMETHOD(SetTimeFormat)(
520                 const GUID* pFormat)
521         {
522                 if (pFormat == 0) {
523                         return E_INVALIDARG;
524                 }
525
526                 if (*pFormat != TIME_FORMAT_MEDIA_TIME) {
527                         return E_INVALIDARG;
528                 }
529
530                 return S_OK;
531         }
532
533         STDMETHOD(GetDuration)(
534                 LONGLONG* pDuration)
535         {
536                 if (pDuration == 0) {
537                         return E_INVALIDARG;
538                 }
539
540                 *pDuration = m_Reader.GetDuration();
541
542                 return S_OK;
543         }
544
545         STDMETHOD(GetStopPosition)(
546                 LONGLONG* /* pStop */)
547         {
548                 return E_NOTIMPL;
549         }
550
551         STDMETHOD(GetCurrentPosition)(
552                 LONGLONG* /* pCurrent */)
553         {
554                 return E_NOTIMPL;
555         }
556
557         STDMETHOD(ConvertTimeFormat)(
558                 LONGLONG*   /* pTarget*/,
559                 const GUID* /* pTargetFormat */,
560                 LONGLONG    /* Source */,
561                 const GUID* /* pSourceFormat */)
562         {
563                 return E_NOTIMPL;
564         }
565
566         STDMETHOD(SetPositions)(
567                 LONGLONG* pCurrent,
568                 DWORD     dwCurrentFlags,
569                 LONGLONG* pStop,
570                 DWORD     dwStopFlags)
571         {
572                 ATL::CComCritSecLock<ATL::CComCriticalSection> lock(m_cs);
573
574                 switch (dwCurrentFlags & AM_SEEKING_PositioningBitsMask) {
575                 case AM_SEEKING_NoPositioning:
576                         break;
577
578                 case AM_SEEKING_AbsolutePositioning:
579                 {
580                         if (pCurrent == 0) {
581                                 return E_INVALIDARG;
582                         }
583
584                         INT64 pos = *pCurrent;
585
586                         if (m_pStreamer != 0) {
587                                 m_pStreamer->BeginFlush();
588                                 m_pStreamer->RequestSeek(pos);
589                                 m_pStreamer->RequestStart();
590
591                         } else {
592                                 m_StartPos = pos;
593                         }
594
595                         break;
596                 }
597
598                 default:
599                         return E_INVALIDARG;
600                 }
601
602                 switch (dwStopFlags & AM_SEEKING_PositioningBitsMask) {
603                 case AM_SEEKING_NoPositioning:
604                         break;
605
606                 default:
607                         return E_INVALIDARG;
608                 }
609
610                 return S_OK;
611         }
612
613         STDMETHOD(GetPositions)(
614                 LONGLONG* /* pCurrent */,
615                 LONGLONG* /* pStop */)
616         {
617                 return E_NOTIMPL;
618         }
619
620         STDMETHOD(GetAvailable)(
621                 LONGLONG* /* pEarliest */,
622                 LONGLONG* /* pLatest */)
623         {
624                 return E_NOTIMPL;
625         }
626
627         STDMETHOD(SetRate)(
628                 double /* dRate */)
629         {
630                 return E_NOTIMPL;
631         }
632
633         STDMETHOD(GetRate)(
634                 double* /* pdRate */)
635         {
636                 return E_NOTIMPL;
637         }
638
639         STDMETHOD(GetPreroll)(
640                 LONGLONG* /* pllPreroll */)
641         {
642                 return E_NOTIMPL;
643         }
644
645         /* IAMFilterMiscFlags */
646
647         STDMETHOD_(ULONG, GetMiscFlags)()
648         {
649                 ATLTRACE("QFilter::GetMiscFlags()\n");
650
651                 return AM_FILTER_MISC_FLAGS_IS_SOURCE;
652         }
653
654         /* */
655
656 private:
657
658         /* */
659
660         HRESULT StartStreaming()
661         {
662                 if (m_pStreamer == 0) {
663                         m_pStreamer = new QStreamer(&m_Reader);
664
665                         HRESULT hRslt = m_pStreamer->Initialize();
666                         if (FAILED(hRslt)) {
667                                 return hRslt;
668                         }
669
670                         hRslt = m_pStreamer->SetupVideo(
671                                 m_pPinVideo->GetMemInputPin(),
672                                 m_pPinVideo->GetMemAllocator(),
673                                 m_pPinVideo->GetVideoHeader());
674                         if (FAILED(hRslt)) {
675                                 return hRslt;
676                         }
677
678                         hRslt = m_pStreamer->SetupAudio(
679                                 m_pPinAudio->GetMemInputPin(),
680                                 m_pPinAudio->GetMemAllocator(),
681                                 m_pPinAudio->GetWaveHeader());
682                         if (FAILED(hRslt)) {
683                                 return hRslt;
684                         }
685
686                         hRslt = m_pStreamer->Commit();
687                         if (FAILED(hRslt)) {
688                                 return hRslt;
689                         }
690
691                         hRslt = m_pStreamer->Create();
692                         if (FAILED(hRslt)) {
693                                 return hRslt;
694                         }
695
696                         if (m_StartPos != -1) {
697                                 m_pStreamer->RequestSeek(m_StartPos);
698                                 m_StartPos = -1;
699                         }
700                 }
701
702                 m_pStreamer->RequestStart();
703
704                 return S_OK;
705         }
706
707         HRESULT StopStreaming()
708         {
709                 if (m_pStreamer != 0) {
710                         HRESULT hRslt = m_pStreamer->Decommit();
711                         if (FAILED(hRslt)) {
712                                 return hRslt;
713                         }
714
715                         m_pStreamer->RequestQuit();
716
717                         m_pStreamer->Uninitialize();
718
719                         delete m_pStreamer;
720                         m_pStreamer = 0;
721                 }
722
723                 return S_OK;
724         }
725
726         /* */
727
728 }; // QFilter
729