Click here to Skip to main content
15,890,336 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Descritpion:
In order to grab s specified frame from video,i wrote a sample grabber filter and null renderer on winmobile and registered dll.In main program
, two self-written filters are created rightly using cocreateinstance method. but transform method isn't called.
implementation
C#
typedef HRESULT (*SAMPLECALLBACK) (IMediaSample * pSample);

MIDL_INTERFACE("6B652FFF-11FE-4FCE-92AD-0266B5D7C78F")
IGrabberSample : public IUnknown
{
public:
	virtual HRESULT STDMETHODCALLTYPE SetAcceptedMediaType( 
		const AM_MEDIA_TYPE *pType) = 0;
	virtual HRESULT STDMETHODCALLTYPE GetConnectedMediaType( 
		AM_MEDIA_TYPE *pType) = 0;
	virtual HRESULT STDMETHODCALLTYPE SetCallback( 
		SAMPLECALLBACK Callback) = 0;
};


class CSampleGrabber : public CTransInPlaceFilter,
	public IGrabberSample
{
private:
	BOOL m_bModifiesData;   
protected:
	CMediaType m_mtAccept;
	SAMPLECALLBACK m_callback;
	CCritSec m_Lock; // serialize access to our data
	//BOOL IsReadOnly( ) { return !m_bModifiesData; }
	// PURE, override this to ensure we get 
	// connected with the right media type
	HRESULT CheckInputType( const CMediaType * pmt );
        //call callback function in this method
	HRESULT Transform( IMediaSample * pms );
public:
	
   CSampleGrabber( IUnknown * pOuter, HRESULT * phr, BOOL ModifiesData);
   static CUnknown *WINAPI CreateInstance(LPUNKNOWN punk, HRESULT *phr);
	// Expose ISampleGrabber
	STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);
	DECLARE_IUNKNOWN;
	
	// IGrabberSample
	STDMETHODIMP SetAcceptedMediaType( const AM_MEDIA_TYPE * pmt );
	STDMETHODIMP GetConnectedMediaType( AM_MEDIA_TYPE * pmt );
	STDMETHODIMP SetCallback( SAMPLECALLBACK Callback );
};

Question:
After building filter graph and then running the graph - transform method isn't called.I want to deal with sample data in transform function, but i have no ideal about the problem. does anybody know the reasons. Your advice will be much appreciated.
thank you for your attention!
Posted
Updated 16-May-10 16:17pm
v3

1 solution

I had also problems with the sample grabber towards a null renderer , to be used for direct3d surfaces , this is how i solved the samplegrabber part in c# ( i use directshow.net and c#):

my sample grabber :
    /// <summary>
    /// a callback handler for samples
    /// The ISampleGrabberCB interface provides callback methods for the ISampleGrabber::SetCallback method. 
    /// If your application calls that method, it must implement this interface. For more information, see ISampleGrabber.
    /// http://msdn.microsoft.com/en-us/library/dd376985(VS.85).aspx
    /// </summary>
    public class JMakerAviSampleDetector : ISampleGrabberCB
    {
        #region declare events
        /// <summary>
        /// Occurs when [event sample cb].
        /// </summary>
        public event JDelegates.JSampleISample EventSampleCb;

        /// <summary>
        /// Occurs when [event buffer cb].
        /// </summary>
        public event JDelegates.JSampleBuffer EventBufferCb;

        private bool pFirstTime;
        #endregion

        #region initialize
        public JMakerAviSampleDetector()
        {
            pFirstTime = true;
        }
        #endregion

        #region declare callback
        /// <summary>
        /// Get the callback using a imediasample
        /// http://msdn.microsoft.com/en-us/library/dd376987(v=VS.85).aspx
        /// </summary>
        /// 
        /// <param name="sampleTime">
        /// >Starting time of the sample, in seconds. 
        /// </param>
        /// 
        /// <param name="sample">
        /// Pointer to the IMediaSample interface of the sample. 
        /// The IMediaSample interface sets and retrieves properties on media samples. 
        /// A media sample is a COM object that contains a block of media data. 
        /// Media samples support the use of shared memory buffers among filters.
        /// http://msdn.microsoft.com/en-us/library/dd407001(VS.85).aspx
        /// </param>
        /// 
        /// <returns>
        /// Returns S_OK if successful, or an HRESULT error code otherwise. 
        /// </returns>
        public int SampleCB(double sampleTime, IMediaSample sample)
        {
            if (pFirstTime)
            {
                 ScanSampe(sample);
            }
            else if (0 == sample.IsDiscontinuity())
            {
                ScanSampe(sample);
            }

            pFirstTime = false;
            EventSampleCb(this, sampleTime, sample);
            return 0;
        }

        /// <summary>
        /// Get the callback using a buffer . 
        /// The BufferCB method is a callback method that receives a pointer to the sample buffer
        /// http://msdn.microsoft.com/en-us/library/dd376986(v=VS.85).aspx
        /// </summary>
        /// 
        /// <param name="sampleTime">
        /// Starting time of the sample, in seconds.
        ///  </param>
        /// 
        /// <param name="buffer">
        /// The buffer.Pointer to a buffer that contains the sample data. 
        /// The format of the data depends on the media type of the Sample Grabber's input pin. 
        /// To get the media type, call ISampleGrabber::GetConnectedMediaType.
        /// </param>
        /// 
        /// <param name="bufferLen">
        /// Length of the buffer pointed to by pBuffer, in bytes. 
        /// </param>
        /// 
        /// <returns>
        /// Returns S_OK if successful, or an HRESULT error code otherwise. 
        /// </returns>
        /// 
        /// <remarks>
        /// This method receives a pointer to the original sample data, not a copy
        /// </remarks>
        public int BufferCB(double sampleTime, IntPtr buffer, int bufferLen)
        {
            EventBufferCb(this, sampleTime, buffer, bufferLen);
            return 0;            
        }
        #endregion

        private void ScanSampe(IMediaSample sample)
        {
            // Determine if this sample represents a break in the data stream.
            // A discontinuity occurs when a filter seeks to a different place in the stream, or when a filter drops samples for quality control.
            // A perfect way to checkup everyhting
            // Returns S_OK (=0) if the sample is a break in the data stream. Otherwise, returns S_FALSE (=1).
            var hr = sample.IsDiscontinuity();
            var isDicontinuity = (hr == 0);
            Trace.WriteLine("Is discontinuity => " + isDicontinuity);
            

            // Check if the sample is a preroll sample.
            // Preroll samples are processed but not displayed. They are located in the media stream before the displayable samples.
            // Returns S_OK (=0) if the sample is a preroll sample. Otherwise, returns S_FALSE (=1).
            hr = sample.IsPreroll();
            var isPreroll = (hr == 0);
            Trace.WriteLine("Is preroll => " + isPreroll);
            
            // Determine if the beginning of this sample is a synchronization point.
            // A filter can begin a stream at any synchronization point. 
            // With some compression types, streaming can begin only at certain points in the stream; for example, on key frames. 
            // If the bTemporalCompression member of the AM_MEDIA_TYPE structure is FALSE, all samples are synchronization points.
            // Returns S_OK (=0) if the sample is a synchronization point. Otherwise, returns S_FALSE (=1).
            hr = sample.IsSyncPoint();
            var isSyncPoint = (hr == 0);
            Trace.WriteLine("Is syncpoint => " + isSyncPoint);
            
            // Get the pointer to the media sample's buffer.
            // The buffer memory is owned by the media sample object, and is automatically released when the media sample is destroyed. 
            // The caller should not free or reallocate the buffer.
            // Returns S_OK if successful, or an HRESULT value indicating the cause of the error.
            IntPtr bufferPointer;
            hr = sample.GetPointer(out bufferPointer);
            Trace.WriteLine(String.Format("Buffer-pointer => " + DsError.GetErrorText(hr) + " bufferpointer is at " + bufferPointer.ToInt32()));

            // Retrieve the size of the buffer, in bytes. 
            // The size does not include the prefix bytes, if any. 
            var bufferSize = sample.GetSize();
            Trace.WriteLine(string.Format("Buffer size is {0}", bufferSize));

            // The GetActualDataLength method retrieves the length of the valid data in the buffer.
            var actualDataSize = sample.GetActualDataLength();
            Trace.WriteLine(string.Format("Actual data lenth is {0}", actualDataSize));

            if (isDicontinuity || isPreroll)
            {
                Trace.WriteLine(
                    "dropped sample , or a seek , or a preroll , we will not check mediatype or media-start/-end  ");
                return;
                
            }
            // Get media start and end time
            long timeStart;
            long timeEnd;
            hr = sample.GetMediaTime(out timeStart, out timeEnd);
            Trace.WriteLine(string.Format("GetMediaStart => {0} media start is {1} , media end is {2}", DsError.GetErrorText(hr) , timeStart , timeEnd));

            // Get the mediatype for the sample
            AMMediaType mediaType;
            hr = sample.GetMediaType(out mediaType);
            Trace.WriteLine(string.Format("GetMediaType => {0}",DsError.GetErrorText(hr) ));


        }
    }


and my on event :
private void OnEventBufferCb(object sender,double sampleTime, IntPtr buffer, int bufferLength)
{
    RaiseSampleBufferChanged(sampleTime, buffer, bufferLength);
}


any my init :
// voeg de null renderer toe
// **********************
Tracer.Write(this, "filtergraph connect pins");

// connect source-filter met samplegrabber filter
var loutPin = DsFindPin.ByDirection(pGraphFilterSource, PinDirection.Output, 0);
var lInPin = DsFindPin.ByDirection(pGraphFilterSampleGrabber, PinDirection.Input, 0);
pHr = pGraphManager.Connect(loutPin, lInPin);
DsError.ThrowExceptionForHR(pHr);

// connect samplegrabber-filter met null-filter
loutPin = DsFindPin.ByDirection(pGraphFilterSampleGrabber, PinDirection.Output, 0);
lInPin = DsFindPin.ByDirection(pGraphFilterNullRenderer, PinDirection.Input, 0);
pHr = pGraphManager.Connect(loutPin, lInPin);
DsError.ThrowExceptionForHR(pHr);

// **********************
Tracer.Write(this, "filtegraph configure filtergraph");
if (pGraphSampleGrabber.GetConnectedMediaType(pMediaType) == 0)
{
    pGraphAviSampleDetector = new JMakerAviSampleDetector();
    pHr = pGraphSampleGrabber.SetBufferSamples(true);
    DsError.ThrowExceptionForHR(pHr);
    pHr = pGraphSampleGrabber.SetOneShot(false);
    DsError.ThrowExceptionForHR(pHr);

    // when set to 0 , call SampleCB
    // when set to 1 , call BufferCB
    pHr = pGraphSampleGrabber.SetCallback(pGraphAviSampleDetector, 0);
    pGraphAviSampleDetector.EventBufferCb += OnEventBufferCb;
    pGraphAviSampleDetector.EventSampleCb += OnEventSampleCb;
}
 
Share this answer
 

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



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900