locked
Why memory usage increase when release video (IMFSinkWriter) RRS feed

  • Question

  • In the loop of my program, There are the creation and release of video. i noticed that memory usage will increase slightly when the release of video occured in each loop.

    Remark: In addition, from my testing of MFCaptureToFile sample (Microsoft SDKs\Windows\v7.1\Samples\multimedia\mediafoundation) by running the video's loop with pressing "start" and "stop", the memory usage will increase as well.

    Help me!

    my code.

    /* Include files to use the OpenCV API. */
    #include <cv.h>
    #include <cxcore.h>
    #include <highgui.h>
    
    /* Include files to use the MFPLAYER API. */
    #include <mfapi.h>
    #include <mfidl.h>
    #include <Mfreadwrite.h>
    #include <mferror.h>
    
    /* Include files to use IFileOpenDialog. */
    #include <shobjidl.h>   
    #include <shlwapi.h>
    
    #pragma comment(lib, "mfreadwrite")
    #pragma comment(lib, "mfplat")
    #pragma comment(lib, "mfuuid")
    
    #define GRAY_CHANNELS	 ( 1 )
    #define RGB24_CHANNELS	 ( 3 )
    #define RGB32_CHANNELS	 ( 4 )
    
    #define IF_FAIL_GOTO(hr) if (FAILED(hr)) { goto done; }
    
    class WriteAVI 
    {
    /***********************************************************************/
    /***********************************************************************/
    private:
    	/*********** Variable **********/
    	UINT64		rtStart;
        UINT64		rtDuration;
    	DWORD		stream;
    
    	/************ Object ***********/
    	IMFSinkWriter	*pSinkWriter;
    	GUID			VideoInputFormat;
    
    	/*********** Function **********/
    	template <class T> void SafeRelease ( T **ppT );
    	HRESULT		InitializeSinkWriter	( IMFSinkWriter **ppSinkWriter, 
    										  DWORD *pStream,
    										  LPCWSTR FileName,
    										  GUID FormatVideo,
    										  UINT32 BitRate,
    										  UINT32 Width,
    										  UINT32 Height,
    										  UINT32 Fps,
    										  INT Channels );
    	HRESULT		WriteFrame				( BYTE *pData, 
    										  const LONGLONG& artStart, 
    										  const LONGLONG& artDuration );	
    
    /***********************************************************************/
    /***********************************************************************/
    public:
    	/*********** Variable **********/
    	LONG		widthStep;
    	DWORD		imageSize;
    	INT			channels;
    	UINT32		fps;
    	UINT32		bitRate;
    	UINT32		videoWidth;
    	UINT32		videoHeight;
    
    	/************ Object ***********/
    
    	/*********** Function **********/
    	void		WriteImage				( BYTE *pData );
    	bool		CreateVideo				( LPCWSTR FileName,					/* Video file names.		*/
    										  GUID FormatVideo,					/* Video format.			*/
    										  UINT32 BitRate,					/* Bit rate.				*/
    										  UINT32 Width,						/* Width of video.			*/
    										  UINT32 Height,					/* Height of video.			*/
    										  UINT32 Fps,						/* Frame per second.		*/
    										  INT Channels );					/* Channels of video.		*/
    	void		ReleaseVideo			( void );
    
    	WriteAVI( void )
    	{
    		/* Set default */
    		pSinkWriter		= NULL;
    	}
    	~WriteAVI( void )
    	{
    	}
    };
    
    bool WriteAVI::CreateVideo ( LPCWSTR FileName,  
    							 GUID FormatVideo,
    							 UINT32 BitRate,
    							 UINT32 Width,
    							 UINT32 Height,
    							 UINT32 Fps, 
    							 INT Channels )
    {
    	//HRESULT hr;
    	HRESULT hr = CoInitializeEx(0, COINIT_APARTMENTTHREADED);
    
    	/* Initialize the Media Foundation platform. */
    	IF_FAIL_GOTO( hr = MFStartup( MF_VERSION ) );
    
    	/* Initialize sink writer */
        IF_FAIL_GOTO( hr = InitializeSinkWriter ( &pSinkWriter, 
    									  		  &stream,
    											  FileName,
    											  FormatVideo,
    											  BitRate,
    											  Width,
    											  Height,
    											  Fps,
    											  Channels) );
        if( SUCCEEDED(hr) )
        {
    		/* Set start point of the video frame. */
    		rtStart	= 0;
    
    		/* Get the video attribute. */
    		fps			= Fps;
    		bitRate		= BitRate;
    		channels	= Channels;
    		videoWidth	= Width;
    		videoHeight	= Height;
    		widthStep	= Width * Channels;
    		imageSize	= Height * widthStep;
    
    		/* Converts a video frame rate into a frame duration. */
    		MFFrameRateToAverageTimePerFrame( Fps, 1, &rtDuration );
    		
    		/* Return true for success connecting. */
    		return TRUE;
    	}
    	else
    	{	
    		/* Shut down Media Foundation. */
    		MFShutdown();
    	}
    done:
    	/* Return false for fail connecting. */
        return FALSE;
    }
    
    HRESULT WriteAVI::InitializeSinkWriter ( IMFSinkWriter **ppSinkWriter, 
    										 DWORD *pStream,
    										 LPCWSTR FileName,
    										 GUID FormatVideo,
    										 UINT32 BitRate,
    										 UINT32 Width,
    										 UINT32 Height,
    										 UINT32 Fps,
    										 INT Channels )
    {
    	/* Initial variable */
    	HRESULT hr;
        IMFSinkWriter   *pbufSinkWriter	= NULL;
        IMFMediaType    *pMediaTypeOut	= NULL;   
        IMFMediaType    *pMediaTypeIn	= NULL;   
        DWORD           streamIndex; 
    
    	*ppSinkWriter	= NULL;
        *pStream		= NULL;
    
    	/* Creates the sink writer from a URL or byte stream. */
    	IF_FAIL_GOTO( hr = MFCreateSinkWriterFromURL( FileName, NULL, NULL, &pbufSinkWriter ) ); 
    	
    	/*-------------- SET OUTPUT MEDIA TYPE. --------------*/
    
    	/* Creates an empty media type. */
    	IF_FAIL_GOTO( hr = MFCreateMediaType( &pMediaTypeOut ) );
    	
    	/* Set the major type is video type. */
    	IF_FAIL_GOTO( hr = pMediaTypeOut->SetGUID( MF_MT_MAJOR_TYPE, MFMediaType_Video ) );
    
    	/* Set the encoding output format. */
    	IF_FAIL_GOTO( hr = pMediaTypeOut->SetGUID( MF_MT_SUBTYPE, FormatVideo ) );
    
    	/* Set the video bit rate. */
    	IF_FAIL_GOTO( hr = pMediaTypeOut->SetUINT32( MF_MT_AVG_BITRATE, BitRate ) );
    
    	/* Set the video interlace progressive. */
    	IF_FAIL_GOTO( hr = pMediaTypeOut->SetUINT32( MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive ) );
    
    	/* Set the frame size. */
    	IF_FAIL_GOTO( hr = MFSetAttributeSize( pMediaTypeOut, MF_MT_FRAME_SIZE, Width, Height ) );
    
    	/* Set the frame per second. */
    	IF_FAIL_GOTO( hr = MFSetAttributeRatio( pMediaTypeOut, MF_MT_FRAME_RATE, Fps, 1 ) );
    
    	/* Set the pixel aspect ratio. */
    	IF_FAIL_GOTO( hr = MFSetAttributeRatio( pMediaTypeOut, MF_MT_PIXEL_ASPECT_RATIO, 1, 1 ) );
    
    	/* Adds a stream to the sink writer. */
    	IF_FAIL_GOTO( hr = pbufSinkWriter->AddStream( pMediaTypeOut, &streamIndex ) );
    
    
    	/*--------------- SET INPUT MEDIA TYPE. ---------------*/
    
    	/* Creates an empty media type. */
    	IF_FAIL_GOTO( hr = MFCreateMediaType( &pMediaTypeIn ) );
    
    	/* Set the major type is video type. */
    	IF_FAIL_GOTO( hr = pMediaTypeIn->SetGUID( MF_MT_MAJOR_TYPE, MFMediaType_Video ) );
    
    	/* Set the encoding input format. */
    	if( SUCCEEDED(hr) )
    	{
    		switch( Channels )
    		{
    			case GRAY_CHANNELS  :	VideoInputFormat = MFVideoFormat_RGB8;   //******//
    									break;
    			case RGB24_CHANNELS :	VideoInputFormat = MFVideoFormat_RGB24;
    									break;
    			case RGB32_CHANNELS :	VideoInputFormat = MFVideoFormat_RGB32;
    									break;
    			default :				printf("Error InitializeSinkWriter : Cannot find specific channels.\n");
    									goto done;
    		}
    		hr = pMediaTypeIn->SetGUID( MF_MT_SUBTYPE, VideoInputFormat );
    	}
    	else
    	{	
    		goto done;	
    	}
    
    	/* Set the video interlace progressive. */
    	IF_FAIL_GOTO( hr = pMediaTypeIn->SetUINT32( MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive ) );
    
    	/* Set the frame size. */
    	IF_FAIL_GOTO( hr = MFSetAttributeSize( pMediaTypeIn, MF_MT_FRAME_SIZE, Width, Height ) );
    
    	/* Set the frame per second. */
    	IF_FAIL_GOTO( hr = MFSetAttributeRatio( pMediaTypeIn, MF_MT_FRAME_RATE, Fps, 1 ) );
    	
    	/* Set the pixel aspect ratio. */
    	IF_FAIL_GOTO( hr = MFSetAttributeRatio( pMediaTypeIn, MF_MT_PIXEL_ASPECT_RATIO, 1, 1 ) );
    
    	/* Sets the input format for a stream on the sink writer. */
    	IF_FAIL_GOTO( hr = pbufSinkWriter->SetInputMediaType( streamIndex, pMediaTypeIn, NULL ) );
    
    
    	/* Tell the sink writer to start accepting data. */
        IF_FAIL_GOTO( hr = pbufSinkWriter->BeginWriting() );
    
    	/* Return the pointer to the caller. */
        if( SUCCEEDED(hr) )
        {
            *ppSinkWriter = pbufSinkWriter;
            (*ppSinkWriter)->AddRef();
            *pStream = streamIndex;
        }
    
    done:
    
    	/* Deallocate memory */
    	SafeRelease( &pbufSinkWriter );
        SafeRelease( &pMediaTypeOut );
        SafeRelease( &pMediaTypeIn );
    	return hr;
    }
    
    void WriteAVI::WriteImage ( BYTE *pData )
    {
    	HRESULT hr = WriteFrame( pData, rtStart, rtDuration );
    	if( SUCCEEDED(hr) )
    	{	rtStart += rtDuration;		
    	}
    }
    
    HRESULT WriteAVI::WriteFrame ( BYTE *pData, const LONGLONG& artStart, const LONGLONG& artDuration )
    {
    	/* Initial variable */
    	HRESULT			hr;
    	BYTE			*pBufData = NULL;
    	IMFSample		*pSample  = NULL;
        IMFMediaBuffer  *pBuffer  = NULL;
    
    	/* Create a new memory buffer. */
        IF_FAIL_GOTO( hr = MFCreateMemoryBuffer( imageSize, &pBuffer ) );
    
    	/* Lock the buffer. */
        IF_FAIL_GOTO( hr = pBuffer->Lock( &pBufData, NULL, NULL ) );
    
    	/* copy the video frame to the buffer. */
    	IF_FAIL_GOTO( hr = MFCopyImage( pBufData,						/* Destination buffer.			*/
    									widthStep,						/* Destination stride.			*/
    									pData,							/* First row in source image.	*/
    									widthStep,						/* Source stride.				*/
    									widthStep,                      /* Image width in bytes.		*/
    									videoHeight ) );				/* Image height in pixels.		*/
    	
    	/* Unlock the buffer. */
    	if( pBuffer )
        {    pBuffer->Unlock();		}				
    
    	/* Set the data length of the buffer. */
        IF_FAIL_GOTO( hr = pBuffer->SetCurrentLength( imageSize ) );
    
    	/* Create a media sample */
        IF_FAIL_GOTO( hr = MFCreateSample( &pSample ) );
    
    	/* Add the buffer to the sample. */
    	IF_FAIL_GOTO( hr = pSample->AddBuffer( pBuffer ) );
    
    	/* Set the time stamp. */
        IF_FAIL_GOTO( hr = pSample->SetSampleTime( artStart ) );
        
    	/* Set the time duration. */
    	IF_FAIL_GOTO( hr = pSample->SetSampleDuration( artDuration ) );
    
    	/* Send the sample to the Sink Writer. */
        IF_FAIL_GOTO( hr = pSinkWriter->WriteSample( stream, pSample ) );
    
    done:
    
    	/* Deallocate memory */
    	SafeRelease( &pSample );
        SafeRelease( &pBuffer );
        return hr;
    }
    
    void WriteAVI::ReleaseVideo( )
    {
    	/* End the writer video */
        pSinkWriter->Finalize();
    
    	/* Deallocate memory */
        SafeRelease( &pSinkWriter );
    
    	/* Shut down Media Foundation. */
    	MFShutdown();
    
    	CoUninitialize();
    }
    
    template <class T> void WriteAVI::SafeRelease(T **ppT)
    {
        if (*ppT)
        {
            (*ppT)->Release();
            *ppT = NULL;
        }
    }
    
    
    //---------------------MAIN-------------------//
    void main ( void )
    {
    	WriteAVI c_WriteAVI;
    
    	/* Initializes the COM library for use by the calling thread. */
    	//HRESULT hr = CoInitializeEx(0, COINIT_APARTMENTTHREADED);
    	HRESULT hr = S_OK;
    	if (SUCCEEDED(hr))
        {   
    		/* Print the success text. */
    		printf("Initial COM runtime success\n");
    
    		/* Connect camera */
    		IplImage *img;
    		CvCapture *cap = cvCaptureFromCAM( 0 );
    		IplImage *g_img = cvCreateImage( cvSize( 640, 480 ), 8, 1 );
    
    		/* Convert char to LPCWSTR */
    		size_t   size;
    		char     FileName[] = "output.wmv";
    		wchar_t	 *lpFileName = (wchar_t *)malloc( 30 * sizeof( wchar_t ));
    		size = mbstowcs( lpFileName, FileName, 30 );
    
    		/* Create video */
    		c_WriteAVI.CreateVideo( lpFileName, 
    								MFVideoFormat_WMV3,
    								800000,
    								640,
    								480,
    								30,
    								3 );
    
    		int time = GetTickCount();
    		while( TRUE )
    		{
    			/* Get image */
    			img = cvQueryFrame( cap );
    			if( img != NULL )
    			{
    				/* Convert gray image */
    				cvCvtColor( img, g_img, CV_RGB2GRAY );
    
    				/* Write image. */
    				c_WriteAVI.WriteImage( (BYTE*)img->imageData );
    
    				/* Show image in window. */
    				cvShowImage( "Test", img );
    			}
    
    			if( (GetTickCount()-time)>15000 )
    			{	
    				printf("Time out\n");
    				time = GetTickCount();
    				c_WriteAVI.ReleaseVideo( );
    				/* Create video */
    				c_WriteAVI.CreateVideo( L"output.wmv", 
    										MFVideoFormat_WMV3,
    										800000,
    										640,
    										480,
    										30,
    										3 );
    			}
    
    			int key = cvWaitKey( 15 );
    			if( (char)key == 'q' )
    			{	break;
    			}
    		}
    	
    		/* Release image */
    		cvReleaseImage( &g_img );
    
    		/* Release video */
    		c_WriteAVI.ReleaseVideo( );
    
    		/* Deallocate memory */
    		cvReleaseCapture( &cap );
            //CoUninitialize();
        }
    }


    Saturday, July 28, 2012 10:31 AM

All replies

  • I test the example code ( http://msdn.microsoft.com/en-us/library/windows/desktop/ff819477%28v=vs.85%29.aspx ).

    I added the code (while loop) but the problem still occurs. Memory usage is increased slightly when the video is released each time.

    The results of my test (while loop when release of video in each time) as following:

    Loop 1: usaged memory -> 50700

    Loop 2: usaged memory -> 50824

    Loop 3: usaged memory -> 50916

    :

    Loop 25: usaged memory -> 53460

    How to release the video with memory usage is not increased ?

    Help!

    my test code

    #include <Windows.h>
    #include <stdio.h>
    #include <mfapi.h>
    #include <mfidl.h>
    #include <Mfreadwrite.h>
    #include <mferror.h>
    
    #pragma comment(lib, "mfreadwrite")
    #pragma comment(lib, "mfplat")
    #pragma comment(lib, "mfuuid")
    
    template <class T> void SafeRelease(T **ppT)
    {
        if (*ppT)
        {
            (*ppT)->Release();
            *ppT = NULL;
        }
    }
    
    // Format constants
    const UINT32 VIDEO_WIDTH = 640;
    const UINT32 VIDEO_HEIGHT = 480;
    const UINT32 VIDEO_FPS = 25;
    const UINT32 VIDEO_BIT_RATE = 800000;
    const GUID   VIDEO_ENCODING_FORMAT = MFVideoFormat_WMV3;
    const GUID   VIDEO_INPUT_FORMAT = MFVideoFormat_RGB32;
    const UINT32 VIDEO_PELS = VIDEO_WIDTH * VIDEO_HEIGHT;
    const UINT32 VIDEO_FRAME_COUNT = 20 * VIDEO_FPS;
    
    // Buffer to hold the video frame data.
    DWORD videoFrameBuffer[VIDEO_PELS];
    
    HRESULT InitializeSinkWriter(IMFSinkWriter **ppWriter, DWORD *pStreamIndex)
    {
        *ppWriter = NULL;
        *pStreamIndex = NULL;
    
        IMFSinkWriter   *pSinkWriter = NULL;
        IMFMediaType    *pMediaTypeOut = NULL;   
        IMFMediaType    *pMediaTypeIn = NULL;   
        DWORD           streamIndex;     
    
        HRESULT hr = MFCreateSinkWriterFromURL(L"output.wmv", NULL, NULL, &pSinkWriter);
    
        // Set the output media type.
        if (SUCCEEDED(hr))
        {
            hr = MFCreateMediaType(&pMediaTypeOut);   
        }
        if (SUCCEEDED(hr))
        {
            hr = pMediaTypeOut->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);     
        }
        if (SUCCEEDED(hr))
        {
            hr = pMediaTypeOut->SetGUID(MF_MT_SUBTYPE, VIDEO_ENCODING_FORMAT);   
        }
        if (SUCCEEDED(hr))
        {
            hr = pMediaTypeOut->SetUINT32(MF_MT_AVG_BITRATE, VIDEO_BIT_RATE);   
        }
        if (SUCCEEDED(hr))
        {
            hr = pMediaTypeOut->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);   
        }
        if (SUCCEEDED(hr))
        {
            hr = MFSetAttributeSize(pMediaTypeOut, MF_MT_FRAME_SIZE, VIDEO_WIDTH, VIDEO_HEIGHT);   
        }
        if (SUCCEEDED(hr))
        {
            hr = MFSetAttributeRatio(pMediaTypeOut, MF_MT_FRAME_RATE, VIDEO_FPS, 1);   
        }
        if (SUCCEEDED(hr))
        {
            hr = MFSetAttributeRatio(pMediaTypeOut, MF_MT_PIXEL_ASPECT_RATIO, 1, 1);   
        }
        if (SUCCEEDED(hr))
        {
            hr = pSinkWriter->AddStream(pMediaTypeOut, &streamIndex);   
        }
    
        // Set the input media type.
        if (SUCCEEDED(hr))
        {
            hr = MFCreateMediaType(&pMediaTypeIn);   
        }
        if (SUCCEEDED(hr))
        {
            hr = pMediaTypeIn->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);   
        }
        if (SUCCEEDED(hr))
        {
            hr = pMediaTypeIn->SetGUID(MF_MT_SUBTYPE, VIDEO_INPUT_FORMAT);     
        }
        if (SUCCEEDED(hr))
        {
            hr = pMediaTypeIn->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);   
        }
        if (SUCCEEDED(hr))
        {
            hr = MFSetAttributeSize(pMediaTypeIn, MF_MT_FRAME_SIZE, VIDEO_WIDTH, VIDEO_HEIGHT);   
        }
        if (SUCCEEDED(hr))
        {
            hr = MFSetAttributeRatio(pMediaTypeIn, MF_MT_FRAME_RATE, VIDEO_FPS, 1);   
        }
        if (SUCCEEDED(hr))
        {
            hr = MFSetAttributeRatio(pMediaTypeIn, MF_MT_PIXEL_ASPECT_RATIO, 1, 1);   
        }
        if (SUCCEEDED(hr))
        {
            hr = pSinkWriter->SetInputMediaType(streamIndex, pMediaTypeIn, NULL);   
        }
    
        // Tell the sink writer to start accepting data.
        if (SUCCEEDED(hr))
        {
            hr = pSinkWriter->BeginWriting();
        }
    
        // Return the pointer to the caller.
        if (SUCCEEDED(hr))
        {
            *ppWriter = pSinkWriter;
            (*ppWriter)->AddRef();
            *pStreamIndex = streamIndex;
        }
    
        SafeRelease(&pSinkWriter);
        SafeRelease(&pMediaTypeOut);
        SafeRelease(&pMediaTypeIn);
        return hr;
    }
    
    HRESULT WriteFrame(
        IMFSinkWriter *pWriter, 
        DWORD streamIndex, 
        const LONGLONG& rtStart,        // Time stamp.
        const LONGLONG& rtDuration      // Frame duration.
        )
    {
        IMFSample *pSample = NULL;
        IMFMediaBuffer *pBuffer = NULL;
    
        const LONG cbWidth = 4 * VIDEO_WIDTH;
        const DWORD cbBuffer = cbWidth * VIDEO_HEIGHT;
    
        BYTE *pData = NULL;
    
        // Create a new memory buffer.
        HRESULT hr = MFCreateMemoryBuffer(cbBuffer, &pBuffer);
    
        // Lock the buffer and copy the video frame to the buffer.
        if (SUCCEEDED(hr))
        {
            hr = pBuffer->Lock(&pData, NULL, NULL);
        }
        if (SUCCEEDED(hr))
        {
            hr = MFCopyImage(
                pData,                      // Destination buffer.
                cbWidth,                    // Destination stride.
                (BYTE*)videoFrameBuffer,    // First row in source image.
                cbWidth,                    // Source stride.
                cbWidth,                    // Image width in bytes.
                VIDEO_HEIGHT                // Image height in pixels.
                );
        }
        if (pBuffer)
        {
            pBuffer->Unlock();
        }
    
        // Set the data length of the buffer.
        if (SUCCEEDED(hr))
        {
            hr = pBuffer->SetCurrentLength(cbBuffer);
        }
    
        // Create a media sample and add the buffer to the sample.
        if (SUCCEEDED(hr))
        {
            hr = MFCreateSample(&pSample);
        }
        if (SUCCEEDED(hr))
        {
            hr = pSample->AddBuffer(pBuffer);
        }
    
        // Set the time stamp and the duration.
        if (SUCCEEDED(hr))
        {
            hr = pSample->SetSampleTime(rtStart);
        }
        if (SUCCEEDED(hr))
        {
            hr = pSample->SetSampleDuration(rtDuration);
        }
    
        // Send the sample to the Sink Writer.
        if (SUCCEEDED(hr))
        {
            hr = pWriter->WriteSample(streamIndex, pSample);
        }
    
        SafeRelease(&pSample);
        SafeRelease(&pBuffer);
        return hr;
    }
    
    void main()
    {
        // Set all pixels to green
        for (DWORD i = 0; i < VIDEO_PELS; ++i)
        {
            videoFrameBuffer[i] = 0x0000FF00;
        }
    
    	while( 1 )
    	{
    		HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
    		if (SUCCEEDED(hr))
    		{
    			hr = MFStartup(MF_VERSION);
    			if (SUCCEEDED(hr))
    			{
    				IMFSinkWriter *pSinkWriter = NULL;
    				DWORD stream;
    
    				hr = InitializeSinkWriter(&pSinkWriter, &stream);
    				if (SUCCEEDED(hr))
    				{
    					printf("Initial sink writer\n");
    
    					// Send frames to the sink writer.
    					LONGLONG rtStart = 0;
    					UINT64 rtDuration;
    
    					MFFrameRateToAverageTimePerFrame(VIDEO_FPS, 1, &rtDuration);
    
    					for (DWORD i = 0; i < VIDEO_FRAME_COUNT; ++i)
    					{
    						hr = WriteFrame(pSinkWriter, stream, rtStart, rtDuration);
    						if (FAILED(hr))
    						{
    							break;
    						}
    						rtStart += rtDuration;
    					}
    				}
    				if (SUCCEEDED(hr))
    				{
    					hr = pSinkWriter->Finalize();
    				}
    				SafeRelease(&pSinkWriter);
    				MFShutdown();
    			}
    			CoUninitialize();
    		}
    	}
    }

    Wednesday, August 22, 2012 9:46 AM
  • What tool are you using to measure memory usage?  I ran your most recent sample through leak detection and watching for increasing outstanding heap allocations.  I did not see either of those.  Depending on what metric is being measured, it may include code pages that are being held in memory after multiple accesses, data waiting on being flushed to disk, or other such things.

    Tuesday, August 28, 2012 10:32 PM
  • Thanks to reply.

    What tool are you using to measure memory usage?

      - I use Windows task Manager to measure memory usage in program.


    The results of my test (while IMFSinkWriter release video in each time) as following:   < Window 7 32 bit >

    Loop 1 : 18516

    Loop 2 : 18620

    Loop 3 : 18736

    Loop 4 : 18756

    Loop 5 : 18820

    Loop 6 : 18868

    Loop 7 : 18904

    Loop 8 : 18944

    Loop 9 : 18984

    Loop 10 : 19016


        i try to solve this problem by data waiting , deallocate memory with delete function or change properties of program but the problem still occurs.

        my test code (ref: http://msdn.microsoft.com/en-us/library/windows/desktop/ff819477%28v=vs.85%29.aspx )

    #include <stdio.h>

    . . void main() { // Set all pixels to green for (DWORD i = 0; i < VIDEO_PELS; ++i) { videoFrameBuffer[i] = 0x0000FF00; } HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); if (SUCCEEDED(hr)) { hr = MFStartup(MF_VERSION); if (SUCCEEDED(hr)) { while( 1 ) { IMFSinkWriter *pSinkWriter = NULL; DWORD stream; hr = InitializeSinkWriter(&pSinkWriter, &stream); if (SUCCEEDED(hr)) { // Send frames to the sink writer. LONGLONG rtStart = 0; UINT64 rtDuration; MFFrameRateToAverageTimePerFrame(VIDEO_FPS, 1, &rtDuration); for (DWORD i = 0; i < VIDEO_FRAME_COUNT; ++i) { hr = WriteFrame(pSinkWriter, stream, rtStart, rtDuration); if (FAILED(hr)) { break; } rtStart += rtDuration; } } if (SUCCEEDED(hr)) { hr = pSinkWriter->Finalize(); static int numLooop = 0; printf( "Loop %d\n", ++numLooop ); Sleep( 3000 ); } SafeRelease(&pSinkWriter); } MFShutdown(); } CoUninitialize(); } } . .





    Tuesday, September 11, 2012 4:30 AM
  • I face the same issue. I have a SinkWriter that generate mp4 videos.Not

    I think the leak is from

    pWriter->WriteSample(streamIndex, pSample);

    Every time I write out an sample, the memory used becomes more and more.

    If I comment out this line, the leak is gone. Although we won't be able to get the output that we want.

    Does anyone know what is the cause of this?

    Thanks

    Thursday, September 13, 2012 10:31 PM
  • I know the problem is. It is at this line:

     (*ppSinkWriter)->AddRef();

    Since you are not passing the ppSinkWriter back to a caller, you don't need to call this method.

    So the way to fix this memory leak is to remove this line. This solution works for me.

    Hope this helps :)

    Friday, September 14, 2012 5:03 PM
  • Thanks to reply.

    I solve your solution but memory leak.

    Do you modify another code ?

    my test code

    #include <stdio.h>
    .
    .
    void main()
    {
        // Set all pixels to green
        for (DWORD i = 0; i < VIDEO_PELS; ++i)
        {
            videoFrameBuffer[i] = 0x0000FF00;
        }
    
    	int num = 0;
        HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
        if (SUCCEEDED(hr))
        {
            hr = MFStartup(MF_VERSION);
            if (SUCCEEDED(hr))
            {
    			while(1)
    			{
    				BYTE *pData = NULL;
    				IMFSinkWriter *pSinkWriter = NULL;
    				DWORD stream;
    
    
    				IMFMediaType    *pMediaTypeOut = NULL;   
    				IMFMediaType    *pMediaTypeIn = NULL;
    				HRESULT hr = MFCreateSinkWriterFromURL(L"output.wmv", NULL, NULL, &pSinkWriter);
    
    				// Set the output media type.
    				if (SUCCEEDED(hr))
    				{	hr = MFCreateMediaType(&pMediaTypeOut);   }
    				if (SUCCEEDED(hr))
    				{	hr = pMediaTypeOut->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);    }
    				if (SUCCEEDED(hr))
    				{	hr = pMediaTypeOut->SetGUID(MF_MT_SUBTYPE, VIDEO_ENCODING_FORMAT);   }
    				if (SUCCEEDED(hr))
    				{	hr = pMediaTypeOut->SetUINT32(MF_MT_AVG_BITRATE, VIDEO_BIT_RATE);    }
    				if (SUCCEEDED(hr))
    				{	hr = pMediaTypeOut->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);   }
    				if (SUCCEEDED(hr))
    				{	hr = MFSetAttributeSize(pMediaTypeOut, MF_MT_FRAME_SIZE, VIDEO_WIDTH, VIDEO_HEIGHT); }
    				if (SUCCEEDED(hr))
    				{	hr = MFSetAttributeRatio(pMediaTypeOut, MF_MT_FRAME_RATE, VIDEO_FPS, 1);   }
    				if (SUCCEEDED(hr))
    				{	hr = MFSetAttributeRatio(pMediaTypeOut, MF_MT_PIXEL_ASPECT_RATIO, 1, 1);   }
    				if (SUCCEEDED(hr))
    				{	hr = pSinkWriter->AddStream(pMediaTypeOut, &stream);			 }
    
    				// Set the input media type.
    				if (SUCCEEDED(hr))
    				{	hr = MFCreateMediaType(&pMediaTypeIn);   }
    				if (SUCCEEDED(hr))
    				{	hr = pMediaTypeIn->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);   }
    				if (SUCCEEDED(hr))
    				{	hr = pMediaTypeIn->SetGUID(MF_MT_SUBTYPE, VIDEO_INPUT_FORMAT);     }
    				if (SUCCEEDED(hr))
    				{	hr = pMediaTypeIn->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive);   }
    				if (SUCCEEDED(hr))
    				{	hr = MFSetAttributeSize(pMediaTypeIn, MF_MT_FRAME_SIZE, VIDEO_WIDTH, VIDEO_HEIGHT); }
    				if (SUCCEEDED(hr))
    				{	hr = MFSetAttributeRatio(pMediaTypeIn, MF_MT_FRAME_RATE, VIDEO_FPS, 1);   }
    				if (SUCCEEDED(hr))
    				{	hr = MFSetAttributeRatio(pMediaTypeIn, MF_MT_PIXEL_ASPECT_RATIO, 1, 1);   }
    				if (SUCCEEDED(hr))
    				{	hr = pSinkWriter->SetInputMediaType( stream, pMediaTypeIn, NULL);     }
    
    				// Tell the sink writer to start accepting data.
    				if (SUCCEEDED(hr))
    				{	hr = pSinkWriter->BeginWriting();	}
    	
    				SafeRelease(&pMediaTypeOut);
    				SafeRelease(&pMediaTypeIn);
    
    
    				//hr = InitializeSinkWriter(&pSinkWriter, &stream);
    				printf("Initial sink writer %d\n", num++ );
    
    				#if 1
    				if (SUCCEEDED(hr))
    				{
    					// Send frames to the sink writer.
    					LONGLONG rtStart = 0;
    					UINT64 rtDuration;
    
    					MFFrameRateToAverageTimePerFrame(VIDEO_FPS, 1, &rtDuration);
    
    					for (DWORD i = 0; i < VIDEO_FRAME_COUNT; ++i)
    					{
    						hr = WriteFrame(pSinkWriter, stream, rtStart, rtDuration, pData );
    						if (FAILED(hr))
    						{
    							break;
    						}
    						rtStart += rtDuration;
    					}
    				}
    				#endif
    
    				if (SUCCEEDED(hr))
    				{
    					hr = pSinkWriter->Finalize();
    					pSinkWriter->Flush( MF_SINK_WRITER_ALL_STREAMS );				
    					Sleep ( 3000 );
    				}
    
    				SafeRelease(&pSinkWriter);
    				delete pSinkWriter;
    				delete pData;
    			}
    
                MFShutdown();
            }
            CoUninitialize();
        }
    }

    Monday, September 17, 2012 6:50 AM