Click here to Skip to main content
15,886,783 members
Articles / Desktop Programming / MFC

DirectShow Editing Services (DES) and combining AVI files

Rate me:
Please Sign up or sign in to vote.
4.64/5 (4 votes)
9 Sep 2011CPOL5 min read 35.8K   5.8K   12  
A sample C++ project that uses DES to combine two or more AVI files.
//------------------------------------------------------------------------------
// File: StrmCtl.h
//
// Desc: DirectShow base classes.
//
// Copyright (c) 1996-2001 Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------------------------


#ifndef __strmctl_h__
#define __strmctl_h__

class CBaseStreamControl : public IAMStreamControl
{
public:
    // Used by the implementation
    enum StreamControlState
    { STREAM_FLOWING = 0x1000,
      STREAM_DISCARDING
    };

private:
    enum StreamControlState	m_StreamState;		// Current stream state
    enum StreamControlState	m_StreamStateOnStop;	// State after next stop
						// (i.e.Blocking or Discarding)

    REFERENCE_TIME	m_tStartTime;	    // MAX_TIME implies none
    REFERENCE_TIME	m_tStopTime;	    // MAX_TIME implies none
    DWORD		m_dwStartCookie;    // Cookie for notification to app
    DWORD		m_dwStopCookie;	    // Cookie for notification to app
    volatile BOOL       m_bIsFlushing;        // No optimization pls!
    volatile BOOL	m_bStopSendExtra;   // bSendExtra was set
    volatile BOOL	m_bStopExtraSent;   // the extra one was sent

    CCritSec		m_CritSec;	    // CritSec to guard above attributes

    // Event to fire when we can come
    // out of blocking, or to come out of waiting
    // to discard if we change our minds.
    //
    CAMEvent			m_StreamEvent;

    // All of these methods execute immediately.  Helpers for others.
    //
    void ExecuteStop();
    void ExecuteStart();
    void CancelStop();
    void CancelStart();

    // Some things we need to be told by our owning filter
    // Your pin must also expose IAMStreamControl when QI'd for it!
    //
    IReferenceClock *	m_pRefClock;	    // Need it to set advises
					    // Filter must tell us via
					    // SetSyncSource
    IMediaEventSink *   m_pSink;            // Event sink
					    // Filter must tell us after it
					    // creates it in JoinFilterGraph()
    FILTER_STATE	m_FilterState;	    // Just need it!
					    // Filter must tell us via
					    // NotifyFilterState
    REFERENCE_TIME	m_tRunStart;	    // Per the Run call to the filter

    // This guy will return one of the three StreamControlState's.  Here's what
    // the caller should do for each one:
    //
    // STREAM_FLOWING:		Proceed as usual (render or pass the sample on)
    // STREAM_DISCARDING:	Calculate the time 'til *pSampleStop and wait
    //				that long for the event handle
    //				(GetStreamEventHandle()).  If the wait
    //				expires, throw the sample away.  If the event
    //				fires, call me back - I've changed my mind.
    //
    enum StreamControlState CheckSampleTimes( __in const REFERENCE_TIME * pSampleStart,
					      __in const REFERENCE_TIME * pSampleStop );

public:
    // You don't have to tell us much when we're created, but there are other
    // obligations that must be met.  See SetSyncSource & NotifyFilterState
    // below.
    //
    CBaseStreamControl(__inout_opt HRESULT *phr = NULL);
    ~CBaseStreamControl();

    // If you want this class to work properly, there are thing you need to
    // (keep) telling it.  Filters with pins that use this class
    // should ensure that they pass through to this method any calls they
    // receive on their SetSyncSource.

    // We need a clock to see what time it is.  This is for the
    // "discard in a timely fashion" logic.  If we discard everything as
    // quick as possible, a whole 60 minute file could get discarded in the
    // first 10 seconds, and if somebody wants to turn streaming on at 30 
    // minutes into the file, and they make the call more than a few seconds
    // after the graph is run, it may be too late!
    // So we hold every sample until it's time has gone, then we discard it.
    // The filter should call this when it gets a SetSyncSource
    //
    void SetSyncSource( IReferenceClock * pRefClock )
    {
	CAutoLock lck(&m_CritSec);
	if (m_pRefClock) m_pRefClock->Release();
	m_pRefClock = pRefClock;
	if (m_pRefClock) m_pRefClock->AddRef();
    }

    // Set event sink for notifications
    // The filter should call this in its JoinFilterGraph after it creates the
    // IMediaEventSink
    //
    void SetFilterGraph( IMediaEventSink *pSink ) {
        m_pSink = pSink;
    }

    // Since we schedule in stream time, we need the tStart and must track the
    // state of our owning filter.
    // The app should call this ever state change
    //
    void NotifyFilterState( FILTER_STATE new_state, REFERENCE_TIME tStart = 0 );

    // Filter should call Flushing(TRUE) in BeginFlush,
    // and Flushing(FALSE) in EndFlush.
    //
    void Flushing( BOOL bInProgress );


    // The two main methods of IAMStreamControl

    // Class adds default values suitable for immediate
    // muting and unmuting of the stream.

    STDMETHODIMP StopAt( const REFERENCE_TIME * ptStop = NULL,
			 BOOL bSendExtra = FALSE,
			 DWORD dwCookie = 0 );
    STDMETHODIMP StartAt( const REFERENCE_TIME * ptStart = NULL,
		    	  DWORD dwCookie = 0 );
    STDMETHODIMP GetInfo( __out AM_STREAM_INFO *pInfo);

    // Helper function for pin's receive method.  Call this with
    // the sample and we'll tell you what to do with it.  We'll do a
    // WaitForSingleObject within this call if one is required.  This is
    // a "What should I do with this sample?" kind of call. We'll tell the
    // caller to either flow it or discard it.
    // If pSample is NULL we evaluate based on the current state
    // settings
    enum StreamControlState CheckStreamState( IMediaSample * pSample );

private:
    // These don't require locking, but we are relying on the fact that
    // m_StreamState can be retrieved with integrity, and is a snap shot that
    // may have just been, or may be just about to be, changed.
    HANDLE GetStreamEventHandle() const { return m_StreamEvent; }
    enum StreamControlState GetStreamState() const { return m_StreamState; }
    BOOL IsStreaming() const { return m_StreamState == STREAM_FLOWING; }
};

#endif

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Retired
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions