Quantcast
Channel: Media Foundation Development for Windows Desktop forum
Viewing all articles
Browse latest Browse all 1079

IMFSourceReader::ReadSample or MFCaptureToFile memory leak?

$
0
0

I'm concerned that I may have a memory leak in the MFCaptureToFile sample, specifically related to IMFSourceReader::ReadSample.  

  • I believe this because on the task manager "Processes" tab I see the Memory for my program growing indefinitely, even as far as 25GB, which brings my computer to its knees, presumably from all the paged memory thrashing.
  • Nevertheless, when my program exits, all this memory is eventually freed (even in the 25GB case, after a couple minutes), so the memory isn't permanently lost.

I started with the MFCaptureToFile sample, so I've gone back to this sample to see if it has the same memory leak.  I don't have a working capture device at the moment, so I am temporarily re-routing to a file input.  So I re-created the trivial changes to make this happen, and MFCaptureToFile so modified indeed has the same memory leak.

Is it my modifications somehow, or does MFCaptureToFile actually have a memory leak?

Below are my trivial modifications.  With these done fresh to the MFCaptureToFile project, I see the growing memory usage in task manager.  So the leak is there already. 

Any comments please?

Trivial mods:

1) I added CreateMediaSource() that I got from some other sample, and then called it from MFCaptureToFile's StartCapture() function for the case that pActivate was NULL, having no capture device.  Below is the excerpt from capture.cpp.  OF course, I also declare CreateMediaSource in capture.h.

//-------------------------------------------------------------------
// CreateMediaSource
//
// Create a media source from a URL.
//-------------------------------------------------------------------

HRESULT CCapture::CreateMediaSource(PCWSTR sURL, IMFMediaSource **ppSource)
{
    MF_OBJECT_TYPE ObjectType = MF_OBJECT_INVALID;

    IMFSourceResolver* pSourceResolver = NULL;
    IUnknown* pSource = NULL;

    // Create the source resolver.
    HRESULT hr = MFCreateSourceResolver(&pSourceResolver);
    if (FAILED(hr))
    {
        goto done;
    }

    // Use the source resolver to create the media source.

    // Note: For simplicity this sample uses the synchronous method to create
    // the media source. However, creating a media source can take a noticeable
    // amount of time, especially for a network source. For a more responsive
    // UI, use the asynchronous BeginCreateObjectFromURL method.

    hr = pSourceResolver->CreateObjectFromURL(
        sURL,                       // URL of the source.
        MF_RESOLUTION_MEDIASOURCE,  // Create a source object.
        NULL,                       // Optional property store.&ObjectType,        // Receives the created object type.&pSource            // Receives a pointer to the media source.
        );
    if (FAILED(hr))
    {
        goto done;
    }

    // Get the IMFMediaSource interface from the media source.
    hr = pSource->QueryInterface(IID_PPV_ARGS(ppSource));

done:
    SafeRelease(&pSourceResolver);
    SafeRelease(&pSource);
    return hr;
}

//-------------------------------------------------------------------
// StartCapture
//
// Start capturing.
//-------------------------------------------------------------------

HRESULT CCapture::StartCapture(
    IMFActivate *pActivate,
    const WCHAR *pwszFileName,
    const EncodingParameters& param
    )
{
    HRESULT hr = S_OK;

    IMFMediaSource *pSource = NULL;

    EnterCriticalSection(&m_critsec);

    // Create the media source for the device.
	if (pActivate)
	{
		// If video capture device exists
		hr = pActivate->ActivateObject(
			__uuidof(IMFMediaSource),
			(void**)&pSource
			);

		// Get the symbolic link. This is needed to handle device-
		// loss notifications. (See CheckDeviceLost.)

		if (SUCCEEDED(hr))
		{
			hr = pActivate->GetAllocatedString(
				MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK,&m_pwszSymbolicLink,
				NULL
				);
		}
	}
	else
	{
		// Otherwise HARD-CODE read from file
		//m_bFileSource = TRUE;
		//m_bEOF = FALSE;

		hr = CreateMediaSource(L"M:\\SPIIRCAM\\Doc\\Video\\Media Foundation SDK\\Play\\PLAYDATA\\MVI_2620.wmv", &pSource);

		// Since we're reading from a file and not a device, don't need to handle device-loss notifications
		//unnecessary//m_pwszSymbolicLink = NULL;
	}

    if (SUCCEEDED(hr))
    {
        hr = OpenMediaSource(pSource);
    }

    // Create the sink writer
    if (SUCCEEDED(hr))
    {
        hr = MFCreateSinkWriterFromURL(
            pwszFileName,
            NULL,
            NULL,
            &m_pWriter
            );
    }

    // Set up the encoding parameters.
    if (SUCCEEDED(hr))
    {
        hr = ConfigureCapture(param);
    }

    if (SUCCEEDED(hr))
    {
        m_bFirstSample = TRUE;
        m_llBaseTime = 0;

        // Request the first video frame.

        hr = m_pReader->ReadSample(
            (DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM,
            0,
            NULL,
            NULL,
            NULL,
            NULL
            );
    }

    SafeRelease(&pSource);
    LeaveCriticalSection(&m_critsec);
    return hr;
}

2) I also had to enable the "Start Capture" button in this case, with no capture devices.  Below is an excerpt from winmain.cpp, where my ONLY change was that one line where I put in "TRUE" to the EnableDialogControl() call.

//-----------------------------------------------------------------------------
// UpdateUI
//
// Updates the dialog UI for the current state.
//-----------------------------------------------------------------------------

void UpdateUI(HWND hDlg)
{
    BOOL bEnable = (g_devices.Count() > 0);     // Are there any capture devices?
    BOOL bCapturing = (g_pCapture != NULL);     // Is video capture in progress now?

    HWND hButton = GetDlgItem(hDlg, IDC_CAPTURE);

    if (bCapturing)
    {
        SetWindowText(hButton, L"Stop Capture");
    }
    else
    {
        SetWindowText(hButton, L"Start Capture");
    }

    EnableDialogControl(hDlg, IDC_CAPTURE, TRUE/*bCapturing || bEnable*/);

    EnableDialogControl(hDlg, IDC_DEVICE_LIST, !bCapturing && bEnable);

    // The following cannot be changed while capture is in progress,
    // but are OK to change when there are no capture devices.

    EnableDialogControl(hDlg, IDC_CAPTURE_MP4, !bCapturing);
    EnableDialogControl(hDlg, IDC_CAPTURE_WMV, !bCapturing);
    EnableDialogControl(hDlg, IDC_OUTPUT_FILE, !bCapturing);
}



Viewing all articles
Browse latest Browse all 1079

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>