다음을 통해 공유


파일 작성

[이 페이지와 연결된 기능인 DirectShow는 레거시 기능입니다. MediaPlayer, IMFMediaEngine 및 Media Foundation의 오디오/비디오 캡처로 대체되었습니다. 이러한 기능은 Windows 10 및 Windows 11 최적화되었습니다. 가능한 경우 새 코드가 DirectShow 대신 Media Foundation에서 MediaPlayer, IMFMediaEngine오디오/비디오 캡처를 사용하는 것이 좋습니다. 가능한 경우 레거시 API를 사용하는 기존 코드를 다시 작성하여 새 API를 사용하도록 제안합니다.]

파일을 작성하려면 IMediaControl::Run 메서드를 호출하여 필터 그래프를 실행하기만 하면됩니다. 재생이 완료되고 IMediaControl::Stop을 호출하여 그래프를 명시적으로 중지할 때까지 기다립니다. 그렇지 않으면 파일이 올바르게 작성되지 않습니다.

파일 작성 작업의 진행률을 표시하려면 IMediaSeeking 인터페이스에 대한 Mux 필터를 쿼리합니다. IMediaSeeking::GetDuration 메서드를 호출하여 파일의 기간을 검색합니다. 그래프가 실행되는 동안 주기적으로 IMediaSeeking::GetCurrentPosition 메서드를 호출하여 스트림에서 그래프의 현재 위치를 검색합니다. 현재 위치를 기간으로 나누면 백분율이 완료됩니다.

참고

애플리케이션은 일반적으로 IMediaSeeking용 Filter Graph Manager를 쿼리하지만 파일 쓰기는 이 규칙의 예외입니다. Filter Graph Manager는 시작 위치의 현재 위치와 그래프가 실행된 기간을 계산합니다. 이는 파일 재생에는 정확하지만 파일 쓰기에는 정확하지 않습니다. 따라서 정확한 결과를 얻으려면 MUX 필터에서 위치를 검색해야 합니다.

 

다음 코드는 파일의 기간을 가져오고, 애플리케이션 UI를 업데이트하는 타이머를 시작하고, 필터 그래프를 실행합니다. (명확성을 위해 오류 검사를 생략합니다.)

IMediaSeeking *pSeek = NULL;
IMediaEventEx *pEvent = NULL;
IMediaControl *pControl = NULL;
REFERENCE_TIME rtTotal;

// Query for interfaces. Remember to release them later.
hr = pMux->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
hr = pGraph->QueryInterface(IID_IMediaEventEx, (void**)&pEvent);
hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl);

// Error checking is omitted for clarity.

// Set the DirectShow event notification window.
hr = pEvent->SetNotifyWindow((OAHWND)hwnd, WM_GRAPHNOTIFY, 0);

// Set the range of the progress bar to the file length (in seconds).
hr = pSeek->GetDuration(&rtTotal);
SendDlgItemMessage(hwnd, IDC_PROGRESS1, PBM_SETRANGE, 0, 
   MAKELPARAM(0, rtTotal / 10000000));
// Start the timer.
UINT_PTR res = SetTimer(hwnd, nIDEvent, 100, NULL);
// Run the graph.
pControl->Run();

애플리케이션이 타이머 이벤트를 받으면 현재 위치로 UI를 업데이트할 수 있습니다.

void OnTimer(HWND hDlg, IMediaSeeking *pSeek)
{
    REFERENCE_TIME rtNow;
    HRESULT hr = pSeek->GetCurrentPosition(&rtNow);
    if (SUCCEEDED(hr))
    {
        SendDlgItemMessage(hDlg, IDC_PROGRESS1, PBM_SETPOS, rtNow/10000000, 0);
    }
}

애플리케이션이 DirectShow 완료 이벤트를 받으면 다음 코드와 같이 그래프를 중지해야 합니다.

// Application window procedure
LRESULT CALLBACK WndProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    /*  ...  */
    case WM_GRAPHNOTIFY:
        DoHandleEvent();
        break;
    /*  ...  */
    }
}

void DoHandleEvent()
{
    long evCode, param1, param2;
    bool bComplete = false;
    if (!pEvent) return;

    // Get all the events, and see we're done.
    while (SUCCEEDED(pEvent->GetEvent(&evCode, &param1, &param2, 0))
    {
        pEvent->FreeEventParams(evCode, param1, param2);
        switch(evCode)
        {
            case EC_USERABORT:
            case EC_ERRORABORT:
            case EC_COMPLETE:
                bComplete = true;
                break;
        }
    }
    if (bComplete)
    {
        pControl->Stop(); // Important! You must stop the graph!

        // Turn off event notification.
        pEvent->SetNotifyWindow(NULL, 0, 0);
        pEvent->Release();
        pEvent = NULL;
        // Reset the progress bar to zero and get rid of the timer.
        SendDlgItemMessage(IDC_PROGRESS1, PBM_SETPOS, 0, 0);
        KillTimer(hwnd, nIDEvent);
    }
}