Tristan Matthews | 0a329cc | 2013-07-17 13:20:14 -0400 | [diff] [blame] | 1 | //------------------------------------------------------------------------------
|
| 2 | // File: AMFilter.h
|
| 3 | //
|
| 4 | // Desc: DirectShow base classes - efines class hierarchy for streams
|
| 5 | // architecture.
|
| 6 | //
|
| 7 | // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
| 8 | //------------------------------------------------------------------------------
|
| 9 |
|
| 10 |
|
| 11 | #ifndef __FILTER__
|
| 12 | #define __FILTER__
|
| 13 |
|
| 14 | /* The following classes are declared in this header: */
|
| 15 |
|
| 16 | class CBaseMediaFilter; // IMediaFilter support
|
| 17 | class CBaseFilter; // IBaseFilter,IMediaFilter support
|
| 18 | class CBasePin; // Abstract base class for IPin interface
|
| 19 | class CEnumPins; // Enumerate input and output pins
|
| 20 | class CEnumMediaTypes; // Enumerate the pin's preferred formats
|
| 21 | class CBaseOutputPin; // Adds data provider member functions
|
| 22 | class CBaseInputPin; // Implements IMemInputPin interface
|
| 23 | class CMediaSample; // Basic transport unit for IMemInputPin
|
| 24 | class CBaseAllocator; // General list guff for most allocators
|
| 25 | class CMemAllocator; // Implements memory buffer allocation
|
| 26 |
|
| 27 |
|
| 28 | //=====================================================================
|
| 29 | //=====================================================================
|
| 30 | //
|
| 31 | // QueryFilterInfo and QueryPinInfo AddRef the interface pointers
|
| 32 | // they return. You can use the macro below to release the interface.
|
| 33 | //
|
| 34 | //=====================================================================
|
| 35 | //=====================================================================
|
| 36 |
|
| 37 | #define QueryFilterInfoReleaseGraph(fi) if ((fi).pGraph) (fi).pGraph->Release();
|
| 38 |
|
| 39 | #define QueryPinInfoReleaseFilter(pi) if ((pi).pFilter) (pi).pFilter->Release();
|
| 40 |
|
| 41 | //=====================================================================
|
| 42 | //=====================================================================
|
| 43 | // Defines CBaseMediaFilter
|
| 44 | //
|
| 45 | // Abstract base class implementing IMediaFilter.
|
| 46 | //
|
| 47 | // Typically you will derive your filter from CBaseFilter rather than
|
| 48 | // this, unless you are implementing an object such as a plug-in
|
| 49 | // distributor that needs to support IMediaFilter but not IBaseFilter.
|
| 50 | //
|
| 51 | // Note that IMediaFilter is derived from IPersist to allow query of
|
| 52 | // class id.
|
| 53 | //=====================================================================
|
| 54 | //=====================================================================
|
| 55 |
|
| 56 | class AM_NOVTABLE CBaseMediaFilter : public CUnknown,
|
| 57 | public IMediaFilter
|
| 58 | {
|
| 59 |
|
| 60 | protected:
|
| 61 |
|
| 62 | FILTER_STATE m_State; // current state: running, paused
|
| 63 | IReferenceClock *m_pClock; // this filter's reference clock
|
| 64 | // note: all filters in a filter graph use the same clock
|
| 65 |
|
| 66 | // offset from stream time to reference time
|
| 67 | CRefTime m_tStart;
|
| 68 |
|
| 69 | CLSID m_clsid; // This filters clsid
|
| 70 | // used for serialization
|
| 71 | CCritSec *m_pLock; // Object we use for locking
|
| 72 |
|
| 73 | public:
|
| 74 |
|
| 75 | CBaseMediaFilter(
|
| 76 | __in_opt LPCTSTR pName,
|
| 77 | __inout_opt LPUNKNOWN pUnk,
|
| 78 | __in CCritSec *pLock,
|
| 79 | REFCLSID clsid);
|
| 80 |
|
| 81 | virtual ~CBaseMediaFilter();
|
| 82 |
|
| 83 | DECLARE_IUNKNOWN
|
| 84 |
|
| 85 | // override this to say what interfaces we support where
|
| 86 | STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
|
| 87 |
|
| 88 | //
|
| 89 | // --- IPersist method ---
|
| 90 | //
|
| 91 |
|
| 92 | STDMETHODIMP GetClassID(__out CLSID *pClsID);
|
| 93 |
|
| 94 | // --- IMediaFilter methods ---
|
| 95 |
|
| 96 | STDMETHODIMP GetState(DWORD dwMSecs, __out FILTER_STATE *State);
|
| 97 |
|
| 98 | STDMETHODIMP SetSyncSource(__inout_opt IReferenceClock *pClock);
|
| 99 |
|
| 100 | STDMETHODIMP GetSyncSource(__deref_out_opt IReferenceClock **pClock);
|
| 101 |
|
| 102 | // default implementation of Stop and Pause just record the
|
| 103 | // state. Override to activate or de-activate your filter.
|
| 104 | // Note that Run when called from Stopped state will call Pause
|
| 105 | // to ensure activation, so if you are a source or transform
|
| 106 | // you will probably not need to override Run.
|
| 107 | STDMETHODIMP Stop();
|
| 108 | STDMETHODIMP Pause();
|
| 109 |
|
| 110 |
|
| 111 | // the start parameter is the difference to be added to the
|
| 112 | // sample's stream time to get the reference time for
|
| 113 | // its presentation
|
| 114 | STDMETHODIMP Run(REFERENCE_TIME tStart);
|
| 115 |
|
| 116 | // --- helper methods ---
|
| 117 |
|
| 118 | // return the current stream time - ie find out what
|
| 119 | // stream time should be appearing now
|
| 120 | virtual HRESULT StreamTime(CRefTime& rtStream);
|
| 121 |
|
| 122 | // Is the filter currently active? (running or paused)
|
| 123 | BOOL IsActive() {
|
| 124 | CAutoLock cObjectLock(m_pLock);
|
| 125 | return ((m_State == State_Paused) || (m_State == State_Running));
|
| 126 | };
|
| 127 | };
|
| 128 |
|
| 129 | //=====================================================================
|
| 130 | //=====================================================================
|
| 131 | // Defines CBaseFilter
|
| 132 | //
|
| 133 | // An abstract class providing basic IBaseFilter support for pin
|
| 134 | // enumeration and filter information reading.
|
| 135 | //
|
| 136 | // We cannot derive from CBaseMediaFilter since methods in IMediaFilter
|
| 137 | // are also in IBaseFilter and would be ambiguous. Since much of the code
|
| 138 | // assumes that they derive from a class that has m_State and other state
|
| 139 | // directly available, we duplicate code from CBaseMediaFilter rather than
|
| 140 | // having a member variable.
|
| 141 | //
|
| 142 | // Derive your filter from this, or from a derived object such as
|
| 143 | // CTransformFilter.
|
| 144 | //=====================================================================
|
| 145 | //=====================================================================
|
| 146 |
|
| 147 |
|
| 148 | class AM_NOVTABLE CBaseFilter : public CUnknown, // Handles an IUnknown
|
| 149 | public IBaseFilter, // The Filter Interface
|
| 150 | public IAMovieSetup // For un/registration
|
| 151 | {
|
| 152 |
|
| 153 | friend class CBasePin;
|
| 154 |
|
| 155 | protected:
|
| 156 | FILTER_STATE m_State; // current state: running, paused
|
| 157 | IReferenceClock *m_pClock; // this graph's ref clock
|
| 158 | CRefTime m_tStart; // offset from stream time to reference time
|
| 159 | CLSID m_clsid; // This filters clsid
|
| 160 | // used for serialization
|
| 161 | CCritSec *m_pLock; // Object we use for locking
|
| 162 |
|
| 163 | WCHAR *m_pName; // Full filter name
|
| 164 | IFilterGraph *m_pGraph; // Graph we belong to
|
| 165 | IMediaEventSink *m_pSink; // Called with notify events
|
| 166 | LONG m_PinVersion; // Current pin version
|
| 167 |
|
| 168 | public:
|
| 169 |
|
| 170 | CBaseFilter(
|
| 171 | __in_opt LPCTSTR pName, // Object description
|
| 172 | __inout_opt LPUNKNOWN pUnk, // IUnknown of delegating object
|
| 173 | __in CCritSec *pLock, // Object who maintains lock
|
| 174 | REFCLSID clsid); // The clsid to be used to serialize this filter
|
| 175 |
|
| 176 | CBaseFilter(
|
| 177 | __in_opt LPCTSTR pName, // Object description
|
| 178 | __in_opt LPUNKNOWN pUnk, // IUnknown of delegating object
|
| 179 | __in CCritSec *pLock, // Object who maintains lock
|
| 180 | REFCLSID clsid, // The clsid to be used to serialize this filter
|
| 181 | __inout HRESULT *phr); // General OLE return code
|
| 182 | #ifdef UNICODE
|
| 183 | CBaseFilter(
|
| 184 | __in_opt LPCSTR pName, // Object description
|
| 185 | __in_opt LPUNKNOWN pUnk, // IUnknown of delegating object
|
| 186 | __in CCritSec *pLock, // Object who maintains lock
|
| 187 | REFCLSID clsid); // The clsid to be used to serialize this filter
|
| 188 |
|
| 189 | CBaseFilter(
|
| 190 | __in_opt LPCSTR pName, // Object description
|
| 191 | __in_opt LPUNKNOWN pUnk, // IUnknown of delegating object
|
| 192 | __in CCritSec *pLock, // Object who maintains lock
|
| 193 | REFCLSID clsid, // The clsid to be used to serialize this filter
|
| 194 | __inout HRESULT *phr); // General OLE return code
|
| 195 | #endif
|
| 196 | ~CBaseFilter();
|
| 197 |
|
| 198 | DECLARE_IUNKNOWN
|
| 199 |
|
| 200 | // override this to say what interfaces we support where
|
| 201 | STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
|
| 202 | #ifdef DEBUG
|
| 203 | STDMETHODIMP_(ULONG) NonDelegatingRelease();
|
| 204 | #endif
|
| 205 |
|
| 206 | //
|
| 207 | // --- IPersist method ---
|
| 208 | //
|
| 209 |
|
| 210 | STDMETHODIMP GetClassID(__out CLSID *pClsID);
|
| 211 |
|
| 212 | // --- IMediaFilter methods ---
|
| 213 |
|
| 214 | STDMETHODIMP GetState(DWORD dwMSecs, __out FILTER_STATE *State);
|
| 215 |
|
| 216 | STDMETHODIMP SetSyncSource(__in_opt IReferenceClock *pClock);
|
| 217 |
|
| 218 | STDMETHODIMP GetSyncSource(__deref_out_opt IReferenceClock **pClock);
|
| 219 |
|
| 220 |
|
| 221 | // override Stop and Pause so we can activate the pins.
|
| 222 | // Note that Run will call Pause first if activation needed.
|
| 223 | // Override these if you want to activate your filter rather than
|
| 224 | // your pins.
|
| 225 | STDMETHODIMP Stop();
|
| 226 | STDMETHODIMP Pause();
|
| 227 |
|
| 228 | // the start parameter is the difference to be added to the
|
| 229 | // sample's stream time to get the reference time for
|
| 230 | // its presentation
|
| 231 | STDMETHODIMP Run(REFERENCE_TIME tStart);
|
| 232 |
|
| 233 | // --- helper methods ---
|
| 234 |
|
| 235 | // return the current stream time - ie find out what
|
| 236 | // stream time should be appearing now
|
| 237 | virtual HRESULT StreamTime(CRefTime& rtStream);
|
| 238 |
|
| 239 | // Is the filter currently active?
|
| 240 | BOOL IsActive() {
|
| 241 | CAutoLock cObjectLock(m_pLock);
|
| 242 | return ((m_State == State_Paused) || (m_State == State_Running));
|
| 243 | };
|
| 244 |
|
| 245 | // Is this filter stopped (without locking)
|
| 246 | BOOL IsStopped() {
|
| 247 | return (m_State == State_Stopped);
|
| 248 | };
|
| 249 |
|
| 250 | //
|
| 251 | // --- IBaseFilter methods ---
|
| 252 | //
|
| 253 |
|
| 254 | // pin enumerator
|
| 255 | STDMETHODIMP EnumPins(
|
| 256 | __deref_out IEnumPins ** ppEnum);
|
| 257 |
|
| 258 |
|
| 259 | // default behaviour of FindPin assumes pin ids are their names
|
| 260 | STDMETHODIMP FindPin(
|
| 261 | LPCWSTR Id,
|
| 262 | __deref_out IPin ** ppPin
|
| 263 | );
|
| 264 |
|
| 265 | STDMETHODIMP QueryFilterInfo(
|
| 266 | __out FILTER_INFO * pInfo);
|
| 267 |
|
| 268 | STDMETHODIMP JoinFilterGraph(
|
| 269 | __inout_opt IFilterGraph * pGraph,
|
| 270 | __in_opt LPCWSTR pName);
|
| 271 |
|
| 272 | // return a Vendor information string. Optional - may return E_NOTIMPL.
|
| 273 | // memory returned should be freed using CoTaskMemFree
|
| 274 | // default implementation returns E_NOTIMPL
|
| 275 | STDMETHODIMP QueryVendorInfo(
|
| 276 | __deref_out LPWSTR* pVendorInfo
|
| 277 | );
|
| 278 |
|
| 279 | // --- helper methods ---
|
| 280 |
|
| 281 | // send an event notification to the filter graph if we know about it.
|
| 282 | // returns S_OK if delivered, S_FALSE if the filter graph does not sink
|
| 283 | // events, or an error otherwise.
|
| 284 | HRESULT NotifyEvent(
|
| 285 | long EventCode,
|
| 286 | LONG_PTR EventParam1,
|
| 287 | LONG_PTR EventParam2);
|
| 288 |
|
| 289 | // return the filter graph we belong to
|
| 290 | __out_opt IFilterGraph *GetFilterGraph() {
|
| 291 | return m_pGraph;
|
| 292 | }
|
| 293 |
|
| 294 | // Request reconnect
|
| 295 | // pPin is the pin to reconnect
|
| 296 | // pmt is the type to reconnect with - can be NULL
|
| 297 | // Calls ReconnectEx on the filter graph
|
| 298 | HRESULT ReconnectPin(IPin *pPin, __in_opt AM_MEDIA_TYPE const *pmt);
|
| 299 |
|
| 300 | // find out the current pin version (used by enumerators)
|
| 301 | virtual LONG GetPinVersion();
|
| 302 | void IncrementPinVersion();
|
| 303 |
|
| 304 | // you need to supply these to access the pins from the enumerator
|
| 305 | // and for default Stop and Pause/Run activation.
|
| 306 | virtual int GetPinCount() PURE;
|
| 307 | virtual CBasePin *GetPin(int n) PURE;
|
| 308 |
|
| 309 | // --- IAMovieSetup methods ---
|
| 310 |
|
| 311 | STDMETHODIMP Register(); // ask filter to register itself
|
| 312 | STDMETHODIMP Unregister(); // and unregister itself
|
| 313 |
|
| 314 | // --- setup helper methods ---
|
| 315 | // (override to return filters setup data)
|
| 316 |
|
| 317 | virtual __out_opt LPAMOVIESETUP_FILTER GetSetupData(){ return NULL; }
|
| 318 |
|
| 319 | };
|
| 320 |
|
| 321 |
|
| 322 | //=====================================================================
|
| 323 | //=====================================================================
|
| 324 | // Defines CBasePin
|
| 325 | //
|
| 326 | // Abstract class that supports the basics of IPin
|
| 327 | //=====================================================================
|
| 328 | //=====================================================================
|
| 329 |
|
| 330 | class AM_NOVTABLE CBasePin : public CUnknown, public IPin, public IQualityControl
|
| 331 | {
|
| 332 |
|
| 333 | protected:
|
| 334 |
|
| 335 | WCHAR * m_pName; // This pin's name
|
| 336 | IPin *m_Connected; // Pin we have connected to
|
| 337 | PIN_DIRECTION m_dir; // Direction of this pin
|
| 338 | CCritSec *m_pLock; // Object we use for locking
|
| 339 | bool m_bRunTimeError; // Run time error generated
|
| 340 | bool m_bCanReconnectWhenActive; // OK to reconnect when active
|
| 341 | bool m_bTryMyTypesFirst; // When connecting enumerate
|
| 342 | // this pin's types first
|
| 343 | CBaseFilter *m_pFilter; // Filter we were created by
|
| 344 | IQualityControl *m_pQSink; // Target for Quality messages
|
| 345 | LONG m_TypeVersion; // Holds current type version
|
| 346 | CMediaType m_mt; // Media type of connection
|
| 347 |
|
| 348 | CRefTime m_tStart; // time from NewSegment call
|
| 349 | CRefTime m_tStop; // time from NewSegment
|
| 350 | double m_dRate; // rate from NewSegment
|
| 351 |
|
| 352 | #ifdef DEBUG
|
| 353 | LONG m_cRef; // Ref count tracing
|
| 354 | #endif
|
| 355 |
|
| 356 | // displays pin connection information
|
| 357 |
|
| 358 | #ifdef DEBUG
|
| 359 | void DisplayPinInfo(IPin *pReceivePin);
|
| 360 | void DisplayTypeInfo(IPin *pPin, const CMediaType *pmt);
|
| 361 | #else
|
| 362 | void DisplayPinInfo(IPin *pReceivePin) {};
|
| 363 | void DisplayTypeInfo(IPin *pPin, const CMediaType *pmt) {};
|
| 364 | #endif
|
| 365 |
|
| 366 | // used to agree a media type for a pin connection
|
| 367 |
|
| 368 | // given a specific media type, attempt a connection (includes
|
| 369 | // checking that the type is acceptable to this pin)
|
| 370 | HRESULT
|
| 371 | AttemptConnection(
|
| 372 | IPin* pReceivePin, // connect to this pin
|
| 373 | const CMediaType* pmt // using this type
|
| 374 | );
|
| 375 |
|
| 376 | // try all the media types in this enumerator - for each that
|
| 377 | // we accept, try to connect using ReceiveConnection.
|
| 378 | HRESULT TryMediaTypes(
|
| 379 | IPin *pReceivePin, // connect to this pin
|
| 380 | __in_opt const CMediaType *pmt, // proposed type from Connect
|
| 381 | IEnumMediaTypes *pEnum); // try this enumerator
|
| 382 |
|
| 383 | // establish a connection with a suitable mediatype. Needs to
|
| 384 | // propose a media type if the pmt pointer is null or partially
|
| 385 | // specified - use TryMediaTypes on both our and then the other pin's
|
| 386 | // enumerator until we find one that works.
|
| 387 | HRESULT AgreeMediaType(
|
| 388 | IPin *pReceivePin, // connect to this pin
|
| 389 | const CMediaType *pmt); // proposed type from Connect
|
| 390 |
|
| 391 | public:
|
| 392 |
|
| 393 | CBasePin(
|
| 394 | __in_opt LPCTSTR pObjectName, // Object description
|
| 395 | __in CBaseFilter *pFilter, // Owning filter who knows about pins
|
| 396 | __in CCritSec *pLock, // Object who implements the lock
|
| 397 | __inout HRESULT *phr, // General OLE return code
|
| 398 | __in_opt LPCWSTR pName, // Pin name for us
|
| 399 | PIN_DIRECTION dir); // Either PINDIR_INPUT or PINDIR_OUTPUT
|
| 400 | #ifdef UNICODE
|
| 401 | CBasePin(
|
| 402 | __in_opt LPCSTR pObjectName, // Object description
|
| 403 | __in CBaseFilter *pFilter, // Owning filter who knows about pins
|
| 404 | __in CCritSec *pLock, // Object who implements the lock
|
| 405 | __inout HRESULT *phr, // General OLE return code
|
| 406 | __in_opt LPCWSTR pName, // Pin name for us
|
| 407 | PIN_DIRECTION dir); // Either PINDIR_INPUT or PINDIR_OUTPUT
|
| 408 | #endif
|
| 409 | virtual ~CBasePin();
|
| 410 |
|
| 411 | DECLARE_IUNKNOWN
|
| 412 |
|
| 413 | STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
|
| 414 | STDMETHODIMP_(ULONG) NonDelegatingRelease();
|
| 415 | STDMETHODIMP_(ULONG) NonDelegatingAddRef();
|
| 416 |
|
| 417 | // --- IPin methods ---
|
| 418 |
|
| 419 | // take lead role in establishing a connection. Media type pointer
|
| 420 | // may be null, or may point to partially-specified mediatype
|
| 421 | // (subtype or format type may be GUID_NULL).
|
| 422 | STDMETHODIMP Connect(
|
| 423 | IPin * pReceivePin,
|
| 424 | __in_opt const AM_MEDIA_TYPE *pmt // optional media type
|
| 425 | );
|
| 426 |
|
| 427 | // (passive) accept a connection from another pin
|
| 428 | STDMETHODIMP ReceiveConnection(
|
| 429 | IPin * pConnector, // this is the initiating connecting pin
|
| 430 | const AM_MEDIA_TYPE *pmt // this is the media type we will exchange
|
| 431 | );
|
| 432 |
|
| 433 | STDMETHODIMP Disconnect();
|
| 434 |
|
| 435 | STDMETHODIMP ConnectedTo(__deref_out IPin **pPin);
|
| 436 |
|
| 437 | STDMETHODIMP ConnectionMediaType(__out AM_MEDIA_TYPE *pmt);
|
| 438 |
|
| 439 | STDMETHODIMP QueryPinInfo(
|
| 440 | __out PIN_INFO * pInfo
|
| 441 | );
|
| 442 |
|
| 443 | STDMETHODIMP QueryDirection(
|
| 444 | __out PIN_DIRECTION * pPinDir
|
| 445 | );
|
| 446 |
|
| 447 | STDMETHODIMP QueryId(
|
| 448 | __deref_out LPWSTR * Id
|
| 449 | );
|
| 450 |
|
| 451 | // does the pin support this media type
|
| 452 | STDMETHODIMP QueryAccept(
|
| 453 | const AM_MEDIA_TYPE *pmt
|
| 454 | );
|
| 455 |
|
| 456 | // return an enumerator for this pins preferred media types
|
| 457 | STDMETHODIMP EnumMediaTypes(
|
| 458 | __deref_out IEnumMediaTypes **ppEnum
|
| 459 | );
|
| 460 |
|
| 461 | // return an array of IPin* - the pins that this pin internally connects to
|
| 462 | // All pins put in the array must be AddReffed (but no others)
|
| 463 | // Errors: "Can't say" - FAIL, not enough slots - return S_FALSE
|
| 464 | // Default: return E_NOTIMPL
|
| 465 | // The filter graph will interpret NOT_IMPL as any input pin connects to
|
| 466 | // all visible output pins and vice versa.
|
| 467 | // apPin can be NULL if nPin==0 (not otherwise).
|
| 468 | STDMETHODIMP QueryInternalConnections(
|
| 469 | __out_ecount_part(*nPin,*nPin) IPin* *apPin, // array of IPin*
|
| 470 | __inout ULONG *nPin // on input, the number of slots
|
| 471 | // on output the number of pins
|
| 472 | ) { return E_NOTIMPL; }
|
| 473 |
|
| 474 | // Called when no more data will be sent
|
| 475 | STDMETHODIMP EndOfStream(void);
|
| 476 |
|
| 477 | // Begin/EndFlush still PURE
|
| 478 |
|
| 479 | // NewSegment notifies of the start/stop/rate applying to the data
|
| 480 | // about to be received. Default implementation records data and
|
| 481 | // returns S_OK.
|
| 482 | // Override this to pass downstream.
|
| 483 | STDMETHODIMP NewSegment(
|
| 484 | REFERENCE_TIME tStart,
|
| 485 | REFERENCE_TIME tStop,
|
| 486 | double dRate);
|
| 487 |
|
| 488 | //================================================================================
|
| 489 | // IQualityControl methods
|
| 490 | //================================================================================
|
| 491 |
|
| 492 | STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
|
| 493 |
|
| 494 | STDMETHODIMP SetSink(IQualityControl * piqc);
|
| 495 |
|
| 496 | // --- helper methods ---
|
| 497 |
|
| 498 | // Returns true if the pin is connected. false otherwise.
|
| 499 | BOOL IsConnected(void) {return (m_Connected != NULL); };
|
| 500 | // Return the pin this is connected to (if any)
|
| 501 | IPin * GetConnected() { return m_Connected; };
|
| 502 |
|
| 503 | // Check if our filter is currently stopped
|
| 504 | BOOL IsStopped() {
|
| 505 | return (m_pFilter->m_State == State_Stopped);
|
| 506 | };
|
| 507 |
|
| 508 | // find out the current type version (used by enumerators)
|
| 509 | virtual LONG GetMediaTypeVersion();
|
| 510 | void IncrementTypeVersion();
|
| 511 |
|
| 512 | // switch the pin to active (paused or running) mode
|
| 513 | // not an error to call this if already active
|
| 514 | virtual HRESULT Active(void);
|
| 515 |
|
| 516 | // switch the pin to inactive state - may already be inactive
|
| 517 | virtual HRESULT Inactive(void);
|
| 518 |
|
| 519 | // Notify of Run() from filter
|
| 520 | virtual HRESULT Run(REFERENCE_TIME tStart);
|
| 521 |
|
| 522 | // check if the pin can support this specific proposed type and format
|
| 523 | virtual HRESULT CheckMediaType(const CMediaType *) PURE;
|
| 524 |
|
| 525 | // set the connection to use this format (previously agreed)
|
| 526 | virtual HRESULT SetMediaType(const CMediaType *);
|
| 527 |
|
| 528 | // check that the connection is ok before verifying it
|
| 529 | // can be overridden eg to check what interfaces will be supported.
|
| 530 | virtual HRESULT CheckConnect(IPin *);
|
| 531 |
|
| 532 | // Set and release resources required for a connection
|
| 533 | virtual HRESULT BreakConnect();
|
| 534 | virtual HRESULT CompleteConnect(IPin *pReceivePin);
|
| 535 |
|
| 536 | // returns the preferred formats for a pin
|
| 537 | virtual HRESULT GetMediaType(int iPosition, __inout CMediaType *pMediaType);
|
| 538 |
|
| 539 | // access to NewSegment values
|
| 540 | REFERENCE_TIME CurrentStopTime() {
|
| 541 | return m_tStop;
|
| 542 | }
|
| 543 | REFERENCE_TIME CurrentStartTime() {
|
| 544 | return m_tStart;
|
| 545 | }
|
| 546 | double CurrentRate() {
|
| 547 | return m_dRate;
|
| 548 | }
|
| 549 |
|
| 550 | // Access name
|
| 551 | LPWSTR Name() { return m_pName; };
|
| 552 |
|
| 553 | // Can reconnectwhen active?
|
| 554 | void SetReconnectWhenActive(bool bCanReconnect)
|
| 555 | {
|
| 556 | m_bCanReconnectWhenActive = bCanReconnect;
|
| 557 | }
|
| 558 |
|
| 559 | bool CanReconnectWhenActive()
|
| 560 | {
|
| 561 | return m_bCanReconnectWhenActive;
|
| 562 | }
|
| 563 |
|
| 564 | protected:
|
| 565 | STDMETHODIMP DisconnectInternal();
|
| 566 | };
|
| 567 |
|
| 568 |
|
| 569 | //=====================================================================
|
| 570 | //=====================================================================
|
| 571 | // Defines CEnumPins
|
| 572 | //
|
| 573 | // Pin enumerator class that works by calling CBaseFilter. This interface
|
| 574 | // is provided by CBaseFilter::EnumPins and calls GetPinCount() and
|
| 575 | // GetPin() to enumerate existing pins. Needs to be a separate object so
|
| 576 | // that it can be cloned (creating an existing object at the same
|
| 577 | // position in the enumeration)
|
| 578 | //
|
| 579 | //=====================================================================
|
| 580 | //=====================================================================
|
| 581 |
|
| 582 | class CEnumPins : public IEnumPins // The interface we support
|
| 583 | {
|
| 584 | int m_Position; // Current ordinal position
|
| 585 | int m_PinCount; // Number of pins available
|
| 586 | CBaseFilter *m_pFilter; // The filter who owns us
|
| 587 | LONG m_Version; // Pin version information
|
| 588 | LONG m_cRef;
|
| 589 |
|
| 590 | typedef CGenericList<CBasePin> CPinList;
|
| 591 |
|
| 592 | CPinList m_PinCache; // These pointers have not been AddRef'ed and
|
| 593 | // so they should not be dereferenced. They are
|
| 594 | // merely kept to ID which pins have been enumerated.
|
| 595 |
|
| 596 | #ifdef DEBUG
|
| 597 | DWORD m_dwCookie;
|
| 598 | #endif
|
| 599 |
|
| 600 | /* If while we are retrieving a pin for example from the filter an error
|
| 601 | occurs we assume that our internal state is stale with respect to the
|
| 602 | filter (someone may have deleted all the pins). We can check before
|
| 603 | starting whether or not the operation is likely to fail by asking the
|
| 604 | filter what it's current version number is. If the filter has not
|
| 605 | overriden the GetPinVersion method then this will always match */
|
| 606 |
|
| 607 | BOOL AreWeOutOfSync() {
|
| 608 | return (m_pFilter->GetPinVersion() == m_Version ? FALSE : TRUE);
|
| 609 | };
|
| 610 |
|
| 611 | /* This method performs the same operations as Reset, except is does not clear
|
| 612 | the cache of pins already enumerated. */
|
| 613 |
|
| 614 | STDMETHODIMP Refresh();
|
| 615 |
|
| 616 | public:
|
| 617 |
|
| 618 | CEnumPins(
|
| 619 | __in CBaseFilter *pFilter,
|
| 620 | __in_opt CEnumPins *pEnumPins);
|
| 621 |
|
| 622 | virtual ~CEnumPins();
|
| 623 |
|
| 624 | // IUnknown
|
| 625 | STDMETHODIMP QueryInterface(REFIID riid, __deref_out void **ppv);
|
| 626 | STDMETHODIMP_(ULONG) AddRef();
|
| 627 | STDMETHODIMP_(ULONG) Release();
|
| 628 |
|
| 629 | // IEnumPins
|
| 630 | STDMETHODIMP Next(
|
| 631 | ULONG cPins, // place this many pins...
|
| 632 | __out_ecount(cPins) IPin ** ppPins, // ...in this array of IPin*
|
| 633 | __out_opt ULONG * pcFetched // actual count passed returned here
|
| 634 | );
|
| 635 |
|
| 636 | STDMETHODIMP Skip(ULONG cPins);
|
| 637 | STDMETHODIMP Reset();
|
| 638 | STDMETHODIMP Clone(__deref_out IEnumPins **ppEnum);
|
| 639 |
|
| 640 |
|
| 641 | };
|
| 642 |
|
| 643 |
|
| 644 | //=====================================================================
|
| 645 | //=====================================================================
|
| 646 | // Defines CEnumMediaTypes
|
| 647 | //
|
| 648 | // Enumerates the preferred formats for input and output pins
|
| 649 | //=====================================================================
|
| 650 | //=====================================================================
|
| 651 |
|
| 652 | class CEnumMediaTypes : public IEnumMediaTypes // The interface we support
|
| 653 | {
|
| 654 | int m_Position; // Current ordinal position
|
| 655 | CBasePin *m_pPin; // The pin who owns us
|
| 656 | LONG m_Version; // Media type version value
|
| 657 | LONG m_cRef;
|
| 658 | #ifdef DEBUG
|
| 659 | DWORD m_dwCookie;
|
| 660 | #endif
|
| 661 |
|
| 662 | /* The media types a filter supports can be quite dynamic so we add to
|
| 663 | the general IEnumXXXX interface the ability to be signaled when they
|
| 664 | change via an event handle the connected filter supplies. Until the
|
| 665 | Reset method is called after the state changes all further calls to
|
| 666 | the enumerator (except Reset) will return E_UNEXPECTED error code */
|
| 667 |
|
| 668 | BOOL AreWeOutOfSync() {
|
| 669 | return (m_pPin->GetMediaTypeVersion() == m_Version ? FALSE : TRUE);
|
| 670 | };
|
| 671 |
|
| 672 | public:
|
| 673 |
|
| 674 | CEnumMediaTypes(
|
| 675 | __in CBasePin *pPin,
|
| 676 | __in_opt CEnumMediaTypes *pEnumMediaTypes);
|
| 677 |
|
| 678 | virtual ~CEnumMediaTypes();
|
| 679 |
|
| 680 | // IUnknown
|
| 681 | STDMETHODIMP QueryInterface(REFIID riid, __deref_out void **ppv);
|
| 682 | STDMETHODIMP_(ULONG) AddRef();
|
| 683 | STDMETHODIMP_(ULONG) Release();
|
| 684 |
|
| 685 | // IEnumMediaTypes
|
| 686 | STDMETHODIMP Next(
|
| 687 | ULONG cMediaTypes, // place this many pins...
|
| 688 | __out_ecount(cMediaTypes) AM_MEDIA_TYPE ** ppMediaTypes, // ...in this array
|
| 689 | __out_opt ULONG * pcFetched // actual count passed
|
| 690 | );
|
| 691 |
|
| 692 | STDMETHODIMP Skip(ULONG cMediaTypes);
|
| 693 | STDMETHODIMP Reset();
|
| 694 | STDMETHODIMP Clone(__deref_out IEnumMediaTypes **ppEnum);
|
| 695 | };
|
| 696 |
|
| 697 |
|
| 698 |
|
| 699 |
|
| 700 | //=====================================================================
|
| 701 | //=====================================================================
|
| 702 | // Defines CBaseOutputPin
|
| 703 | //
|
| 704 | // class derived from CBasePin that can pass buffers to a connected pin
|
| 705 | // that supports IMemInputPin. Supports IPin.
|
| 706 | //
|
| 707 | // Derive your output pin from this.
|
| 708 | //
|
| 709 | //=====================================================================
|
| 710 | //=====================================================================
|
| 711 |
|
| 712 | class AM_NOVTABLE CBaseOutputPin : public CBasePin
|
| 713 | {
|
| 714 |
|
| 715 | protected:
|
| 716 |
|
| 717 | IMemAllocator *m_pAllocator;
|
| 718 | IMemInputPin *m_pInputPin; // interface on the downstreaminput pin
|
| 719 | // set up in CheckConnect when we connect.
|
| 720 |
|
| 721 | public:
|
| 722 |
|
| 723 | CBaseOutputPin(
|
| 724 | __in_opt LPCTSTR pObjectName,
|
| 725 | __in CBaseFilter *pFilter,
|
| 726 | __in CCritSec *pLock,
|
| 727 | __inout HRESULT *phr,
|
| 728 | __in_opt LPCWSTR pName);
|
| 729 | #ifdef UNICODE
|
| 730 | CBaseOutputPin(
|
| 731 | __in_opt LPCSTR pObjectName,
|
| 732 | __in CBaseFilter *pFilter,
|
| 733 | __in CCritSec *pLock,
|
| 734 | __inout HRESULT *phr,
|
| 735 | __in_opt LPCWSTR pName);
|
| 736 | #endif
|
| 737 | // override CompleteConnect() so we can negotiate an allocator
|
| 738 | virtual HRESULT CompleteConnect(IPin *pReceivePin);
|
| 739 |
|
| 740 | // negotiate the allocator and its buffer size/count and other properties
|
| 741 | // Calls DecideBufferSize to set properties
|
| 742 | virtual HRESULT DecideAllocator(IMemInputPin * pPin, __deref_out IMemAllocator ** pAlloc);
|
| 743 |
|
| 744 | // override this to set the buffer size and count. Return an error
|
| 745 | // if the size/count is not to your liking.
|
| 746 | // The allocator properties passed in are those requested by the
|
| 747 | // input pin - use eg the alignment and prefix members if you have
|
| 748 | // no preference on these.
|
| 749 | virtual HRESULT DecideBufferSize(
|
| 750 | IMemAllocator * pAlloc,
|
| 751 | __inout ALLOCATOR_PROPERTIES * ppropInputRequest
|
| 752 | ) PURE;
|
| 753 |
|
| 754 | // returns an empty sample buffer from the allocator
|
| 755 | virtual HRESULT GetDeliveryBuffer(__deref_out IMediaSample ** ppSample,
|
| 756 | __in_opt REFERENCE_TIME * pStartTime,
|
| 757 | __in_opt REFERENCE_TIME * pEndTime,
|
| 758 | DWORD dwFlags);
|
| 759 |
|
| 760 | // deliver a filled-in sample to the connected input pin
|
| 761 | // note - you need to release it after calling this. The receiving
|
| 762 | // pin will addref the sample if it needs to hold it beyond the
|
| 763 | // call.
|
| 764 | virtual HRESULT Deliver(IMediaSample *);
|
| 765 |
|
| 766 | // override this to control the connection
|
| 767 | virtual HRESULT InitAllocator(__deref_out IMemAllocator **ppAlloc);
|
| 768 | HRESULT CheckConnect(IPin *pPin);
|
| 769 | HRESULT BreakConnect();
|
| 770 |
|
| 771 | // override to call Commit and Decommit
|
| 772 | HRESULT Active(void);
|
| 773 | HRESULT Inactive(void);
|
| 774 |
|
| 775 | // we have a default handling of EndOfStream which is to return
|
| 776 | // an error, since this should be called on input pins only
|
| 777 | STDMETHODIMP EndOfStream(void);
|
| 778 |
|
| 779 | // called from elsewhere in our filter to pass EOS downstream to
|
| 780 | // our connected input pin
|
| 781 | virtual HRESULT DeliverEndOfStream(void);
|
| 782 |
|
| 783 | // same for Begin/EndFlush - we handle Begin/EndFlush since it
|
| 784 | // is an error on an output pin, and we have Deliver methods to
|
| 785 | // call the methods on the connected pin
|
| 786 | STDMETHODIMP BeginFlush(void);
|
| 787 | STDMETHODIMP EndFlush(void);
|
| 788 | virtual HRESULT DeliverBeginFlush(void);
|
| 789 | virtual HRESULT DeliverEndFlush(void);
|
| 790 |
|
| 791 | // deliver NewSegment to connected pin - you will need to
|
| 792 | // override this if you queue any data in your output pin.
|
| 793 | virtual HRESULT DeliverNewSegment(
|
| 794 | REFERENCE_TIME tStart,
|
| 795 | REFERENCE_TIME tStop,
|
| 796 | double dRate);
|
| 797 |
|
| 798 | //================================================================================
|
| 799 | // IQualityControl methods
|
| 800 | //================================================================================
|
| 801 |
|
| 802 | // All inherited from CBasePin and not overridden here.
|
| 803 | // STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
|
| 804 | // STDMETHODIMP SetSink(IQualityControl * piqc);
|
| 805 | };
|
| 806 |
|
| 807 |
|
| 808 | //=====================================================================
|
| 809 | //=====================================================================
|
| 810 | // Defines CBaseInputPin
|
| 811 | //
|
| 812 | // derive your standard input pin from this.
|
| 813 | // you need to supply GetMediaType and CheckConnect etc (see CBasePin),
|
| 814 | // and you need to supply Receive to do something more useful.
|
| 815 | //
|
| 816 | //=====================================================================
|
| 817 | //=====================================================================
|
| 818 |
|
| 819 | class AM_NOVTABLE CBaseInputPin : public CBasePin,
|
| 820 | public IMemInputPin
|
| 821 | {
|
| 822 |
|
| 823 | protected:
|
| 824 |
|
| 825 | IMemAllocator *m_pAllocator; // Default memory allocator
|
| 826 |
|
| 827 | // allocator is read-only, so received samples
|
| 828 | // cannot be modified (probably only relevant to in-place
|
| 829 | // transforms
|
| 830 | BYTE m_bReadOnly;
|
| 831 |
|
| 832 | // in flushing state (between BeginFlush and EndFlush)
|
| 833 | // if TRUE, all Receives are returned with S_FALSE
|
| 834 | BYTE m_bFlushing;
|
| 835 |
|
| 836 | // Sample properties - initalized in Receive
|
| 837 | AM_SAMPLE2_PROPERTIES m_SampleProps;
|
| 838 |
|
| 839 | public:
|
| 840 |
|
| 841 | CBaseInputPin(
|
| 842 | __in_opt LPCTSTR pObjectName,
|
| 843 | __in CBaseFilter *pFilter,
|
| 844 | __in CCritSec *pLock,
|
| 845 | __inout HRESULT *phr,
|
| 846 | __in_opt LPCWSTR pName);
|
| 847 | #ifdef UNICODE
|
| 848 | CBaseInputPin(
|
| 849 | __in_opt LPCSTR pObjectName,
|
| 850 | __in CBaseFilter *pFilter,
|
| 851 | __in CCritSec *pLock,
|
| 852 | __inout HRESULT *phr,
|
| 853 | __in_opt LPCWSTR pName);
|
| 854 | #endif
|
| 855 | virtual ~CBaseInputPin();
|
| 856 |
|
| 857 | DECLARE_IUNKNOWN
|
| 858 |
|
| 859 | // override this to publicise our interfaces
|
| 860 | STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
|
| 861 |
|
| 862 | // return the allocator interface that this input pin
|
| 863 | // would like the output pin to use
|
| 864 | STDMETHODIMP GetAllocator(__deref_out IMemAllocator ** ppAllocator);
|
| 865 |
|
| 866 | // tell the input pin which allocator the output pin is actually
|
| 867 | // going to use.
|
| 868 | STDMETHODIMP NotifyAllocator(
|
| 869 | IMemAllocator * pAllocator,
|
| 870 | BOOL bReadOnly);
|
| 871 |
|
| 872 | // do something with this media sample
|
| 873 | STDMETHODIMP Receive(IMediaSample *pSample);
|
| 874 |
|
| 875 | // do something with these media samples
|
| 876 | STDMETHODIMP ReceiveMultiple (
|
| 877 | __in_ecount(nSamples) IMediaSample **pSamples,
|
| 878 | long nSamples,
|
| 879 | __out long *nSamplesProcessed);
|
| 880 |
|
| 881 | // See if Receive() blocks
|
| 882 | STDMETHODIMP ReceiveCanBlock();
|
| 883 |
|
| 884 | // Default handling for BeginFlush - call at the beginning
|
| 885 | // of your implementation (makes sure that all Receive calls
|
| 886 | // fail). After calling this, you need to free any queued data
|
| 887 | // and then call downstream.
|
| 888 | STDMETHODIMP BeginFlush(void);
|
| 889 |
|
| 890 | // default handling for EndFlush - call at end of your implementation
|
| 891 | // - before calling this, ensure that there is no queued data and no thread
|
| 892 | // pushing any more without a further receive, then call downstream,
|
| 893 | // then call this method to clear the m_bFlushing flag and re-enable
|
| 894 | // receives
|
| 895 | STDMETHODIMP EndFlush(void);
|
| 896 |
|
| 897 | // this method is optional (can return E_NOTIMPL).
|
| 898 | // default implementation returns E_NOTIMPL. Override if you have
|
| 899 | // specific alignment or prefix needs, but could use an upstream
|
| 900 | // allocator
|
| 901 | STDMETHODIMP GetAllocatorRequirements(__out ALLOCATOR_PROPERTIES*pProps);
|
| 902 |
|
| 903 | // Release the pin's allocator.
|
| 904 | HRESULT BreakConnect();
|
| 905 |
|
| 906 | // helper method to check the read-only flag
|
| 907 | BOOL IsReadOnly() {
|
| 908 | return m_bReadOnly;
|
| 909 | };
|
| 910 |
|
| 911 | // helper method to see if we are flushing
|
| 912 | BOOL IsFlushing() {
|
| 913 | return m_bFlushing;
|
| 914 | };
|
| 915 |
|
| 916 | // Override this for checking whether it's OK to process samples
|
| 917 | // Also call this from EndOfStream.
|
| 918 | virtual HRESULT CheckStreaming();
|
| 919 |
|
| 920 | // Pass a Quality notification on to the appropriate sink
|
| 921 | HRESULT PassNotify(Quality& q);
|
| 922 |
|
| 923 |
|
| 924 | //================================================================================
|
| 925 | // IQualityControl methods (from CBasePin)
|
| 926 | //================================================================================
|
| 927 |
|
| 928 | STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
|
| 929 |
|
| 930 | // no need to override:
|
| 931 | // STDMETHODIMP SetSink(IQualityControl * piqc);
|
| 932 |
|
| 933 |
|
| 934 | // switch the pin to inactive state - may already be inactive
|
| 935 | virtual HRESULT Inactive(void);
|
| 936 |
|
| 937 | // Return sample properties pointer
|
| 938 | AM_SAMPLE2_PROPERTIES * SampleProps() {
|
| 939 | ASSERT(m_SampleProps.cbData != 0);
|
| 940 | return &m_SampleProps;
|
| 941 | }
|
| 942 |
|
| 943 | };
|
| 944 |
|
| 945 | ///////////////////////////////////////////////////////////////////////////
|
| 946 | // CDynamicOutputPin
|
| 947 | //
|
| 948 |
|
| 949 | class CDynamicOutputPin : public CBaseOutputPin,
|
| 950 | public IPinFlowControl
|
| 951 | {
|
| 952 | public:
|
| 953 | #ifdef UNICODE
|
| 954 | CDynamicOutputPin(
|
| 955 | __in_opt LPCSTR pObjectName,
|
| 956 | __in CBaseFilter *pFilter,
|
| 957 | __in CCritSec *pLock,
|
| 958 | __inout HRESULT *phr,
|
| 959 | __in_opt LPCWSTR pName);
|
| 960 | #endif
|
| 961 |
|
| 962 | CDynamicOutputPin(
|
| 963 | __in_opt LPCTSTR pObjectName,
|
| 964 | __in CBaseFilter *pFilter,
|
| 965 | __in CCritSec *pLock,
|
| 966 | __inout HRESULT *phr,
|
| 967 | __in_opt LPCWSTR pName);
|
| 968 |
|
| 969 | ~CDynamicOutputPin();
|
| 970 |
|
| 971 | // IUnknown Methods
|
| 972 | DECLARE_IUNKNOWN
|
| 973 | STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
|
| 974 |
|
| 975 | // IPin Methods
|
| 976 | STDMETHODIMP Disconnect(void);
|
| 977 |
|
| 978 | // IPinFlowControl Methods
|
| 979 | STDMETHODIMP Block(DWORD dwBlockFlags, HANDLE hEvent);
|
| 980 |
|
| 981 | // Set graph config info
|
| 982 | void SetConfigInfo(IGraphConfig *pGraphConfig, HANDLE hStopEvent);
|
| 983 |
|
| 984 | #ifdef DEBUG
|
| 985 | virtual HRESULT Deliver(IMediaSample *pSample);
|
| 986 | virtual HRESULT DeliverEndOfStream(void);
|
| 987 | virtual HRESULT DeliverNewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
|
| 988 | #endif // DEBUG
|
| 989 |
|
| 990 | HRESULT DeliverBeginFlush(void);
|
| 991 | HRESULT DeliverEndFlush(void);
|
| 992 |
|
| 993 | HRESULT Inactive(void);
|
| 994 | HRESULT Active(void);
|
| 995 | virtual HRESULT CompleteConnect(IPin *pReceivePin);
|
| 996 |
|
| 997 | virtual HRESULT StartUsingOutputPin(void);
|
| 998 | virtual void StopUsingOutputPin(void);
|
| 999 | virtual bool StreamingThreadUsingOutputPin(void);
|
| 1000 |
|
| 1001 | HRESULT ChangeOutputFormat
|
| 1002 | (
|
| 1003 | const AM_MEDIA_TYPE *pmt,
|
| 1004 | REFERENCE_TIME tSegmentStart,
|
| 1005 | REFERENCE_TIME tSegmentStop,
|
| 1006 | double dSegmentRate
|
| 1007 | );
|
| 1008 | HRESULT ChangeMediaType(const CMediaType *pmt);
|
| 1009 | HRESULT DynamicReconnect(const CMediaType *pmt);
|
| 1010 |
|
| 1011 | protected:
|
| 1012 | HRESULT SynchronousBlockOutputPin(void);
|
| 1013 | HRESULT AsynchronousBlockOutputPin(HANDLE hNotifyCallerPinBlockedEvent);
|
| 1014 | HRESULT UnblockOutputPin(void);
|
| 1015 |
|
| 1016 | void BlockOutputPin(void);
|
| 1017 | void ResetBlockState(void);
|
| 1018 |
|
| 1019 | static HRESULT WaitEvent(HANDLE hEvent);
|
| 1020 |
|
| 1021 | enum BLOCK_STATE
|
| 1022 | {
|
| 1023 | NOT_BLOCKED,
|
| 1024 | PENDING,
|
| 1025 | BLOCKED
|
| 1026 | };
|
| 1027 |
|
| 1028 | // This lock should be held when the following class members are
|
| 1029 | // being used: m_hNotifyCallerPinBlockedEvent, m_BlockState,
|
| 1030 | // m_dwBlockCallerThreadID and m_dwNumOutstandingOutputPinUsers.
|
| 1031 | CCritSec m_BlockStateLock;
|
| 1032 |
|
| 1033 | // This event should be signaled when the output pin is
|
| 1034 | // not blocked. This is a manual reset event. For more
|
| 1035 | // information on events, see the documentation for
|
| 1036 | // CreateEvent() in the Windows SDK.
|
| 1037 | HANDLE m_hUnblockOutputPinEvent;
|
| 1038 |
|
| 1039 | // This event will be signaled when block operation succeedes or
|
| 1040 | // when the user cancels the block operation. The block operation
|
| 1041 | // can be canceled by calling IPinFlowControl2::Block( 0, NULL )
|
| 1042 | // while the block operation is pending.
|
| 1043 | HANDLE m_hNotifyCallerPinBlockedEvent;
|
| 1044 |
|
| 1045 | // The state of the current block operation.
|
| 1046 | BLOCK_STATE m_BlockState;
|
| 1047 |
|
| 1048 | // The ID of the thread which last called IPinFlowControl::Block().
|
| 1049 | // For more information on thread IDs, see the documentation for
|
| 1050 | // GetCurrentThreadID() in the Windows SDK.
|
| 1051 | DWORD m_dwBlockCallerThreadID;
|
| 1052 |
|
| 1053 | // The number of times StartUsingOutputPin() has been sucessfully
|
| 1054 | // called and a corresponding call to StopUsingOutputPin() has not
|
| 1055 | // been made. When this variable is greater than 0, the streaming
|
| 1056 | // thread is calling IPin::NewSegment(), IPin::EndOfStream(),
|
| 1057 | // IMemInputPin::Receive() or IMemInputPin::ReceiveMultiple(). The
|
| 1058 | // streaming thread could also be calling: DynamicReconnect(),
|
| 1059 | // ChangeMediaType() or ChangeOutputFormat(). The output pin cannot
|
| 1060 | // be blocked while the output pin is being used.
|
| 1061 | DWORD m_dwNumOutstandingOutputPinUsers;
|
| 1062 |
|
| 1063 | // This event should be set when the IMediaFilter::Stop() is called.
|
| 1064 | // This is a manual reset event. It is also set when the output pin
|
| 1065 | // delivers a flush to the connected input pin.
|
| 1066 | HANDLE m_hStopEvent;
|
| 1067 | IGraphConfig* m_pGraphConfig;
|
| 1068 |
|
| 1069 | // TRUE if the output pin's allocator's samples are read only.
|
| 1070 | // Otherwise FALSE. For more information, see the documentation
|
| 1071 | // for IMemInputPin::NotifyAllocator().
|
| 1072 | BOOL m_bPinUsesReadOnlyAllocator;
|
| 1073 |
|
| 1074 | private:
|
| 1075 | HRESULT Initialize(void);
|
| 1076 | HRESULT ChangeMediaTypeHelper(const CMediaType *pmt);
|
| 1077 |
|
| 1078 | #ifdef DEBUG
|
| 1079 | void AssertValid(void);
|
| 1080 | #endif // DEBUG
|
| 1081 | };
|
| 1082 |
|
| 1083 | class CAutoUsingOutputPin
|
| 1084 | {
|
| 1085 | public:
|
| 1086 | CAutoUsingOutputPin( __in CDynamicOutputPin* pOutputPin, __inout HRESULT* phr );
|
| 1087 | ~CAutoUsingOutputPin();
|
| 1088 |
|
| 1089 | private:
|
| 1090 | CDynamicOutputPin* m_pOutputPin;
|
| 1091 | };
|
| 1092 |
|
| 1093 | inline CAutoUsingOutputPin::CAutoUsingOutputPin( __in CDynamicOutputPin* pOutputPin, __inout HRESULT* phr ) :
|
| 1094 | m_pOutputPin(NULL)
|
| 1095 | {
|
| 1096 | // The caller should always pass in valid pointers.
|
| 1097 | ASSERT( NULL != pOutputPin );
|
| 1098 | ASSERT( NULL != phr );
|
| 1099 |
|
| 1100 | // Make sure the user initialized phr.
|
| 1101 | ASSERT( S_OK == *phr );
|
| 1102 |
|
| 1103 | HRESULT hr = pOutputPin->StartUsingOutputPin();
|
| 1104 | if( FAILED( hr ) )
|
| 1105 | {
|
| 1106 | *phr = hr;
|
| 1107 | return;
|
| 1108 | }
|
| 1109 |
|
| 1110 | m_pOutputPin = pOutputPin;
|
| 1111 | }
|
| 1112 |
|
| 1113 | inline CAutoUsingOutputPin::~CAutoUsingOutputPin()
|
| 1114 | {
|
| 1115 | if( NULL != m_pOutputPin )
|
| 1116 | {
|
| 1117 | m_pOutputPin->StopUsingOutputPin();
|
| 1118 | }
|
| 1119 | }
|
| 1120 |
|
| 1121 | #ifdef DEBUG
|
| 1122 |
|
| 1123 | inline HRESULT CDynamicOutputPin::Deliver(IMediaSample *pSample)
|
| 1124 | {
|
| 1125 | // The caller should call StartUsingOutputPin() before calling this
|
| 1126 | // method.
|
| 1127 | ASSERT(StreamingThreadUsingOutputPin());
|
| 1128 |
|
| 1129 | return CBaseOutputPin::Deliver(pSample);
|
| 1130 | }
|
| 1131 |
|
| 1132 | inline HRESULT CDynamicOutputPin::DeliverEndOfStream(void)
|
| 1133 | {
|
| 1134 | // The caller should call StartUsingOutputPin() before calling this
|
| 1135 | // method.
|
| 1136 | ASSERT( StreamingThreadUsingOutputPin() );
|
| 1137 |
|
| 1138 | return CBaseOutputPin::DeliverEndOfStream();
|
| 1139 | }
|
| 1140 |
|
| 1141 | inline HRESULT CDynamicOutputPin::DeliverNewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
|
| 1142 | {
|
| 1143 | // The caller should call StartUsingOutputPin() before calling this
|
| 1144 | // method.
|
| 1145 | ASSERT(StreamingThreadUsingOutputPin());
|
| 1146 |
|
| 1147 | return CBaseOutputPin::DeliverNewSegment(tStart, tStop, dRate);
|
| 1148 | }
|
| 1149 |
|
| 1150 | #endif // DEBUG
|
| 1151 |
|
| 1152 | //=====================================================================
|
| 1153 | //=====================================================================
|
| 1154 | // Memory allocators
|
| 1155 | //
|
| 1156 | // the shared memory transport between pins requires the input pin
|
| 1157 | // to provide a memory allocator that can provide sample objects. A
|
| 1158 | // sample object supports the IMediaSample interface.
|
| 1159 | //
|
| 1160 | // CBaseAllocator handles the management of free and busy samples. It
|
| 1161 | // allocates CMediaSample objects. CBaseAllocator is an abstract class:
|
| 1162 | // in particular it has no method of initializing the list of free
|
| 1163 | // samples. CMemAllocator is derived from CBaseAllocator and initializes
|
| 1164 | // the list of samples using memory from the standard IMalloc interface.
|
| 1165 | //
|
| 1166 | // If you want your buffers to live in some special area of memory,
|
| 1167 | // derive your allocator object from CBaseAllocator. If you derive your
|
| 1168 | // IMemInputPin interface object from CBaseMemInputPin, you will get
|
| 1169 | // CMemAllocator-based allocation etc for free and will just need to
|
| 1170 | // supply the Receive handling, and media type / format negotiation.
|
| 1171 | //=====================================================================
|
| 1172 | //=====================================================================
|
| 1173 |
|
| 1174 |
|
| 1175 | //=====================================================================
|
| 1176 | //=====================================================================
|
| 1177 | // Defines CMediaSample
|
| 1178 | //
|
| 1179 | // an object of this class supports IMediaSample and represents a buffer
|
| 1180 | // for media data with some associated properties. Releasing it returns
|
| 1181 | // it to a freelist managed by a CBaseAllocator derived object.
|
| 1182 | //=====================================================================
|
| 1183 | //=====================================================================
|
| 1184 |
|
| 1185 | class CMediaSample : public IMediaSample2 // The interface we support
|
| 1186 | {
|
| 1187 |
|
| 1188 | protected:
|
| 1189 |
|
| 1190 | friend class CBaseAllocator;
|
| 1191 |
|
| 1192 | /* Values for dwFlags - these are used for backward compatiblity
|
| 1193 | only now - use AM_SAMPLE_xxx
|
| 1194 | */
|
| 1195 | enum { Sample_SyncPoint = 0x01, /* Is this a sync point */
|
| 1196 | Sample_Preroll = 0x02, /* Is this a preroll sample */
|
| 1197 | Sample_Discontinuity = 0x04, /* Set if start of new segment */
|
| 1198 | Sample_TypeChanged = 0x08, /* Has the type changed */
|
| 1199 | Sample_TimeValid = 0x10, /* Set if time is valid */
|
| 1200 | Sample_MediaTimeValid = 0x20, /* Is the media time valid */
|
| 1201 | Sample_TimeDiscontinuity = 0x40, /* Time discontinuity */
|
| 1202 | Sample_StopValid = 0x100, /* Stop time valid */
|
| 1203 | Sample_ValidFlags = 0x1FF
|
| 1204 | };
|
| 1205 |
|
| 1206 | /* Properties, the media sample class can be a container for a format
|
| 1207 | change in which case we take a copy of a type through the SetMediaType
|
| 1208 | interface function and then return it when GetMediaType is called. As
|
| 1209 | we do no internal processing on it we leave it as a pointer */
|
| 1210 |
|
| 1211 | DWORD m_dwFlags; /* Flags for this sample */
|
| 1212 | /* Type specific flags are packed
|
| 1213 | into the top word
|
| 1214 | */
|
| 1215 | DWORD m_dwTypeSpecificFlags; /* Media type specific flags */
|
| 1216 | __field_ecount_opt(m_cbBuffer) LPBYTE m_pBuffer; /* Pointer to the complete buffer */
|
| 1217 | LONG m_lActual; /* Length of data in this sample */
|
| 1218 | LONG m_cbBuffer; /* Size of the buffer */
|
| 1219 | CBaseAllocator *m_pAllocator; /* The allocator who owns us */
|
| 1220 | CMediaSample *m_pNext; /* Chaining in free list */
|
| 1221 | REFERENCE_TIME m_Start; /* Start sample time */
|
| 1222 | REFERENCE_TIME m_End; /* End sample time */
|
| 1223 | LONGLONG m_MediaStart; /* Real media start position */
|
| 1224 | LONG m_MediaEnd; /* A difference to get the end */
|
| 1225 | AM_MEDIA_TYPE *m_pMediaType; /* Media type change data */
|
| 1226 | DWORD m_dwStreamId; /* Stream id */
|
| 1227 | public:
|
| 1228 | LONG m_cRef; /* Reference count */
|
| 1229 |
|
| 1230 |
|
| 1231 | public:
|
| 1232 |
|
| 1233 | CMediaSample(
|
| 1234 | __in_opt LPCTSTR pName,
|
| 1235 | __in_opt CBaseAllocator *pAllocator,
|
| 1236 | __inout_opt HRESULT *phr,
|
| 1237 | __in_bcount_opt(length) LPBYTE pBuffer = NULL,
|
| 1238 | LONG length = 0);
|
| 1239 | #ifdef UNICODE
|
| 1240 | CMediaSample(
|
| 1241 | __in_opt LPCSTR pName,
|
| 1242 | __in_opt CBaseAllocator *pAllocator,
|
| 1243 | __inout_opt HRESULT *phr,
|
| 1244 | __in_bcount_opt(length) LPBYTE pBuffer = NULL,
|
| 1245 | LONG length = 0);
|
| 1246 | #endif
|
| 1247 |
|
| 1248 | virtual ~CMediaSample();
|
| 1249 |
|
| 1250 | /* Note the media sample does not delegate to its owner */
|
| 1251 |
|
| 1252 | STDMETHODIMP QueryInterface(REFIID riid, __deref_out void **ppv);
|
| 1253 | STDMETHODIMP_(ULONG) AddRef();
|
| 1254 | STDMETHODIMP_(ULONG) Release();
|
| 1255 |
|
| 1256 | // set the buffer pointer and length. Used by allocators that
|
| 1257 | // want variable sized pointers or pointers into already-read data.
|
| 1258 | // This is only available through a CMediaSample* not an IMediaSample*
|
| 1259 | // and so cannot be changed by clients.
|
| 1260 | HRESULT SetPointer(__in_bcount(cBytes) BYTE * ptr, LONG cBytes);
|
| 1261 |
|
| 1262 | // Get me a read/write pointer to this buffer's memory.
|
| 1263 | STDMETHODIMP GetPointer(__deref_out BYTE ** ppBuffer);
|
| 1264 |
|
| 1265 | STDMETHODIMP_(LONG) GetSize(void);
|
| 1266 |
|
| 1267 | // get the stream time at which this sample should start and finish.
|
| 1268 | STDMETHODIMP GetTime(
|
| 1269 | __out REFERENCE_TIME * pTimeStart, // put time here
|
| 1270 | __out REFERENCE_TIME * pTimeEnd
|
| 1271 | );
|
| 1272 |
|
| 1273 | // Set the stream time at which this sample should start and finish.
|
| 1274 | STDMETHODIMP SetTime(
|
| 1275 | __in_opt REFERENCE_TIME * pTimeStart, // put time here
|
| 1276 | __in_opt REFERENCE_TIME * pTimeEnd
|
| 1277 | );
|
| 1278 | STDMETHODIMP IsSyncPoint(void);
|
| 1279 | STDMETHODIMP SetSyncPoint(BOOL bIsSyncPoint);
|
| 1280 | STDMETHODIMP IsPreroll(void);
|
| 1281 | STDMETHODIMP SetPreroll(BOOL bIsPreroll);
|
| 1282 |
|
| 1283 | STDMETHODIMP_(LONG) GetActualDataLength(void);
|
| 1284 | STDMETHODIMP SetActualDataLength(LONG lActual);
|
| 1285 |
|
| 1286 | // these allow for limited format changes in band
|
| 1287 |
|
| 1288 | STDMETHODIMP GetMediaType(__deref_out AM_MEDIA_TYPE **ppMediaType);
|
| 1289 | STDMETHODIMP SetMediaType(__in_opt AM_MEDIA_TYPE *pMediaType);
|
| 1290 |
|
| 1291 | // returns S_OK if there is a discontinuity in the data (this same is
|
| 1292 | // not a continuation of the previous stream of data
|
| 1293 | // - there has been a seek).
|
| 1294 | STDMETHODIMP IsDiscontinuity(void);
|
| 1295 | // set the discontinuity property - TRUE if this sample is not a
|
| 1296 | // continuation, but a new sample after a seek.
|
| 1297 | STDMETHODIMP SetDiscontinuity(BOOL bDiscontinuity);
|
| 1298 |
|
| 1299 | // get the media times for this sample
|
| 1300 | STDMETHODIMP GetMediaTime(
|
| 1301 | __out LONGLONG * pTimeStart,
|
| 1302 | __out LONGLONG * pTimeEnd
|
| 1303 | );
|
| 1304 |
|
| 1305 | // Set the media times for this sample
|
| 1306 | STDMETHODIMP SetMediaTime(
|
| 1307 | __in_opt LONGLONG * pTimeStart,
|
| 1308 | __in_opt LONGLONG * pTimeEnd
|
| 1309 | );
|
| 1310 |
|
| 1311 | // Set and get properties (IMediaSample2)
|
| 1312 | STDMETHODIMP GetProperties(
|
| 1313 | DWORD cbProperties,
|
| 1314 | __out_bcount(cbProperties) BYTE * pbProperties
|
| 1315 | );
|
| 1316 |
|
| 1317 | STDMETHODIMP SetProperties(
|
| 1318 | DWORD cbProperties,
|
| 1319 | __in_bcount(cbProperties) const BYTE * pbProperties
|
| 1320 | );
|
| 1321 | };
|
| 1322 |
|
| 1323 |
|
| 1324 | //=====================================================================
|
| 1325 | //=====================================================================
|
| 1326 | // Defines CBaseAllocator
|
| 1327 | //
|
| 1328 | // Abstract base class that manages a list of media samples
|
| 1329 | //
|
| 1330 | // This class provides support for getting buffers from the free list,
|
| 1331 | // including handling of commit and (asynchronous) decommit.
|
| 1332 | //
|
| 1333 | // Derive from this class and override the Alloc and Free functions to
|
| 1334 | // allocate your CMediaSample (or derived) objects and add them to the
|
| 1335 | // free list, preparing them as necessary.
|
| 1336 | //=====================================================================
|
| 1337 | //=====================================================================
|
| 1338 |
|
| 1339 | class AM_NOVTABLE CBaseAllocator : public CUnknown,// A non delegating IUnknown
|
| 1340 | public IMemAllocatorCallbackTemp, // The interface we support
|
| 1341 | public CCritSec // Provides object locking
|
| 1342 | {
|
| 1343 | class CSampleList;
|
| 1344 | friend class CSampleList;
|
| 1345 |
|
| 1346 | /* Trick to get at protected member in CMediaSample */
|
| 1347 | static CMediaSample * &NextSample(__in CMediaSample *pSample)
|
| 1348 | {
|
| 1349 | return pSample->m_pNext;
|
| 1350 | };
|
| 1351 |
|
| 1352 | /* Mini list class for the free list */
|
| 1353 | class CSampleList
|
| 1354 | {
|
| 1355 | public:
|
| 1356 | CSampleList() : m_List(NULL), m_nOnList(0) {};
|
| 1357 | #ifdef DEBUG
|
| 1358 | ~CSampleList()
|
| 1359 | {
|
| 1360 | ASSERT(m_nOnList == 0);
|
| 1361 | };
|
| 1362 | #endif
|
| 1363 | CMediaSample *Head() const { return m_List; };
|
| 1364 | CMediaSample *Next(__in CMediaSample *pSample) const { return CBaseAllocator::NextSample(pSample); };
|
| 1365 | int GetCount() const { return m_nOnList; };
|
| 1366 | void Add(__inout CMediaSample *pSample)
|
| 1367 | {
|
| 1368 | ASSERT(pSample != NULL);
|
| 1369 | CBaseAllocator::NextSample(pSample) = m_List;
|
| 1370 | m_List = pSample;
|
| 1371 | m_nOnList++;
|
| 1372 | };
|
| 1373 | CMediaSample *RemoveHead()
|
| 1374 | {
|
| 1375 | CMediaSample *pSample = m_List;
|
| 1376 | if (pSample != NULL) {
|
| 1377 | m_List = CBaseAllocator::NextSample(m_List);
|
| 1378 | m_nOnList--;
|
| 1379 | }
|
| 1380 | return pSample;
|
| 1381 | };
|
| 1382 | void Remove(__inout CMediaSample *pSample);
|
| 1383 |
|
| 1384 | public:
|
| 1385 | CMediaSample *m_List;
|
| 1386 | int m_nOnList;
|
| 1387 | };
|
| 1388 | protected:
|
| 1389 |
|
| 1390 | CSampleList m_lFree; // Free list
|
| 1391 |
|
| 1392 | /* Note to overriders of CBaseAllocator.
|
| 1393 |
|
| 1394 | We use a lazy signalling mechanism for waiting for samples.
|
| 1395 | This means we don't call the OS if no waits occur.
|
| 1396 |
|
| 1397 | In order to implement this:
|
| 1398 |
|
| 1399 | 1. When a new sample is added to m_lFree call NotifySample() which
|
| 1400 | calls ReleaseSemaphore on m_hSem with a count of m_lWaiting and
|
| 1401 | sets m_lWaiting to 0.
|
| 1402 | This must all be done holding the allocator's critical section.
|
| 1403 |
|
| 1404 | 2. When waiting for a sample call SetWaiting() which increments
|
| 1405 | m_lWaiting BEFORE leaving the allocator's critical section.
|
| 1406 |
|
| 1407 | 3. Actually wait by calling WaitForSingleObject(m_hSem, INFINITE)
|
| 1408 | having left the allocator's critical section. The effect of
|
| 1409 | this is to remove 1 from the semaphore's count. You MUST call
|
| 1410 | this once having incremented m_lWaiting.
|
| 1411 |
|
| 1412 | The following are then true when the critical section is not held :
|
| 1413 | (let nWaiting = number about to wait or waiting)
|
| 1414 |
|
| 1415 | (1) if (m_lFree.GetCount() != 0) then (m_lWaiting == 0)
|
| 1416 | (2) m_lWaiting + Semaphore count == nWaiting
|
| 1417 |
|
| 1418 | We would deadlock if
|
| 1419 | nWaiting != 0 &&
|
| 1420 | m_lFree.GetCount() != 0 &&
|
| 1421 | Semaphore count == 0
|
| 1422 |
|
| 1423 | But from (1) if m_lFree.GetCount() != 0 then m_lWaiting == 0 so
|
| 1424 | from (2) Semaphore count == nWaiting (which is non-0) so the
|
| 1425 | deadlock can't happen.
|
| 1426 | */
|
| 1427 |
|
| 1428 | HANDLE m_hSem; // For signalling
|
| 1429 | long m_lWaiting; // Waiting for a free element
|
| 1430 | long m_lCount; // how many buffers we have agreed to provide
|
| 1431 | long m_lAllocated; // how many buffers are currently allocated
|
| 1432 | long m_lSize; // agreed size of each buffer
|
| 1433 | long m_lAlignment; // agreed alignment
|
| 1434 | long m_lPrefix; // agreed prefix (preceeds GetPointer() value)
|
| 1435 | BOOL m_bChanged; // Have the buffer requirements changed
|
| 1436 |
|
| 1437 | // if true, we are decommitted and can't allocate memory
|
| 1438 | BOOL m_bCommitted;
|
| 1439 | // if true, the decommit has happened, but we haven't called Free yet
|
| 1440 | // as there are still outstanding buffers
|
| 1441 | BOOL m_bDecommitInProgress;
|
| 1442 |
|
| 1443 | // Notification interface
|
| 1444 | IMemAllocatorNotifyCallbackTemp *m_pNotify;
|
| 1445 |
|
| 1446 | BOOL m_fEnableReleaseCallback;
|
| 1447 |
|
| 1448 | // called to decommit the memory when the last buffer is freed
|
| 1449 | // pure virtual - need to override this
|
| 1450 | virtual void Free(void) PURE;
|
| 1451 |
|
| 1452 | // override to allocate the memory when commit called
|
| 1453 | virtual HRESULT Alloc(void);
|
| 1454 |
|
| 1455 | public:
|
| 1456 |
|
| 1457 | CBaseAllocator(
|
| 1458 | __in_opt LPCTSTR , __inout_opt LPUNKNOWN, __inout HRESULT *,
|
| 1459 | BOOL bEvent = TRUE, BOOL fEnableReleaseCallback = FALSE);
|
| 1460 | #ifdef UNICODE
|
| 1461 | CBaseAllocator(
|
| 1462 | __in_opt LPCSTR , __inout_opt LPUNKNOWN, __inout HRESULT *,
|
| 1463 | BOOL bEvent = TRUE, BOOL fEnableReleaseCallback = FALSE);
|
| 1464 | #endif
|
| 1465 | virtual ~CBaseAllocator();
|
| 1466 |
|
| 1467 | DECLARE_IUNKNOWN
|
| 1468 |
|
| 1469 | // override this to publicise our interfaces
|
| 1470 | STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
|
| 1471 |
|
| 1472 | STDMETHODIMP SetProperties(
|
| 1473 | __in ALLOCATOR_PROPERTIES* pRequest,
|
| 1474 | __out ALLOCATOR_PROPERTIES* pActual);
|
| 1475 |
|
| 1476 | // return the properties actually being used on this allocator
|
| 1477 | STDMETHODIMP GetProperties(
|
| 1478 | __out ALLOCATOR_PROPERTIES* pProps);
|
| 1479 |
|
| 1480 | // override Commit to allocate memory. We handle the GetBuffer
|
| 1481 | //state changes
|
| 1482 | STDMETHODIMP Commit();
|
| 1483 |
|
| 1484 | // override this to handle the memory freeing. We handle any outstanding
|
| 1485 | // GetBuffer calls
|
| 1486 | STDMETHODIMP Decommit();
|
| 1487 |
|
| 1488 | // get container for a sample. Blocking, synchronous call to get the
|
| 1489 | // next free buffer (as represented by an IMediaSample interface).
|
| 1490 | // on return, the time etc properties will be invalid, but the buffer
|
| 1491 | // pointer and size will be correct. The two time parameters are
|
| 1492 | // optional and either may be NULL, they may alternatively be set to
|
| 1493 | // the start and end times the sample will have attached to it
|
| 1494 | // bPrevFramesSkipped is not used (used only by the video renderer's
|
| 1495 | // allocator where it affects quality management in direct draw).
|
| 1496 |
|
| 1497 | STDMETHODIMP GetBuffer(__deref_out IMediaSample **ppBuffer,
|
| 1498 | __in_opt REFERENCE_TIME * pStartTime,
|
| 1499 | __in_opt REFERENCE_TIME * pEndTime,
|
| 1500 | DWORD dwFlags);
|
| 1501 |
|
| 1502 | // final release of a CMediaSample will call this
|
| 1503 | STDMETHODIMP ReleaseBuffer(IMediaSample *pBuffer);
|
| 1504 | // obsolete:: virtual void PutOnFreeList(CMediaSample * pSample);
|
| 1505 |
|
| 1506 | STDMETHODIMP SetNotify(IMemAllocatorNotifyCallbackTemp *pNotify);
|
| 1507 |
|
| 1508 | STDMETHODIMP GetFreeCount(__out LONG *plBuffersFree);
|
| 1509 |
|
| 1510 | // Notify that a sample is available
|
| 1511 | void NotifySample();
|
| 1512 |
|
| 1513 | // Notify that we're waiting for a sample
|
| 1514 | void SetWaiting() { m_lWaiting++; };
|
| 1515 | };
|
| 1516 |
|
| 1517 |
|
| 1518 | //=====================================================================
|
| 1519 | //=====================================================================
|
| 1520 | // Defines CMemAllocator
|
| 1521 | //
|
| 1522 | // this is an allocator based on CBaseAllocator that allocates sample
|
| 1523 | // buffers in main memory (from 'new'). You must call SetProperties
|
| 1524 | // before calling Commit.
|
| 1525 | //
|
| 1526 | // we don't free the memory when going into Decommit state. The simplest
|
| 1527 | // way to implement this without complicating CBaseAllocator is to
|
| 1528 | // have a Free() function, called to go into decommit state, that does
|
| 1529 | // nothing and a ReallyFree function called from our destructor that
|
| 1530 | // actually frees the memory.
|
| 1531 | //=====================================================================
|
| 1532 | //=====================================================================
|
| 1533 |
|
| 1534 | // Make me one from quartz.dll
|
| 1535 | STDAPI CreateMemoryAllocator(__deref_out IMemAllocator **ppAllocator);
|
| 1536 |
|
| 1537 | class CMemAllocator : public CBaseAllocator
|
| 1538 | {
|
| 1539 |
|
| 1540 | protected:
|
| 1541 |
|
| 1542 | LPBYTE m_pBuffer; // combined memory for all buffers
|
| 1543 |
|
| 1544 | // override to free the memory when decommit completes
|
| 1545 | // - we actually do nothing, and save the memory until deletion.
|
| 1546 | void Free(void);
|
| 1547 |
|
| 1548 | // called from the destructor (and from Alloc if changing size/count) to
|
| 1549 | // actually free up the memory
|
| 1550 | void ReallyFree(void);
|
| 1551 |
|
| 1552 | // overriden to allocate the memory when commit called
|
| 1553 | HRESULT Alloc(void);
|
| 1554 |
|
| 1555 | public:
|
| 1556 | /* This goes in the factory template table to create new instances */
|
| 1557 | static CUnknown *CreateInstance(__inout_opt LPUNKNOWN, __inout HRESULT *);
|
| 1558 |
|
| 1559 | STDMETHODIMP SetProperties(
|
| 1560 | __in ALLOCATOR_PROPERTIES* pRequest,
|
| 1561 | __out ALLOCATOR_PROPERTIES* pActual);
|
| 1562 |
|
| 1563 | CMemAllocator(__in_opt LPCTSTR , __inout_opt LPUNKNOWN, __inout HRESULT *);
|
| 1564 | #ifdef UNICODE
|
| 1565 | CMemAllocator(__in_opt LPCSTR , __inout_opt LPUNKNOWN, __inout HRESULT *);
|
| 1566 | #endif
|
| 1567 | ~CMemAllocator();
|
| 1568 | };
|
| 1569 |
|
| 1570 | // helper used by IAMovieSetup implementation
|
| 1571 | STDAPI
|
| 1572 | AMovieSetupRegisterFilter( const AMOVIESETUP_FILTER * const psetupdata
|
| 1573 | , IFilterMapper * pIFM
|
| 1574 | , BOOL bRegister );
|
| 1575 |
|
| 1576 |
|
| 1577 | ///////////////////////////////////////////////////////////////////////////
|
| 1578 | // ------------------------------------------------------------------------
|
| 1579 | // ------------------------------------------------------------------------
|
| 1580 | // ------------------------------------------------------------------------
|
| 1581 | // ------------------------------------------------------------------------
|
| 1582 | ///////////////////////////////////////////////////////////////////////////
|
| 1583 |
|
| 1584 | #endif /* __FILTER__ */
|
| 1585 |
|
| 1586 |
|
| 1587 |
|