다음을 통해 공유


파일을 재생하는 방법

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

이 문서는 DirectShow 프로그래밍의 맛을 제공하기 위한 것입니다. 오디오 또는 비디오 파일을 재생하는 간단한 콘솔 애플리케이션을 제공합니다. 이 프로그램은 몇 줄 길이에 불과하지만 DirectShow 프로그래밍의 몇 가지 기능을 보여 줍니다.

DirectShow 애플리케이션 프로그래밍 소개 문서에서 설명한 것처럼 DirectShow 애플리케이션은 항상 동일한 기본 단계를 수행합니다.

  1. 필터 그래프 관리자의 instance 만듭니다.
  2. 필터 그래프 관리자를 사용하여 필터 그래프를 작성합니다.
  3. 그래프를 실행하여 데이터가 필터를 통해 이동되도록 합니다.

이 항목의 코드를 컴파일하고 연결하려면 헤더 파일 Dshow.h를 포함하고 정적 라이브러리 파일 strmiids.lib에 연결합니다. 자세한 내용은 DirectShow 애플리케이션 빌드를 참조하세요.

먼저 CoInitialize 또는 CoInitializeEx를 호출하여 COM 라이브러리를 초기화합니다.

HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
    // Add error-handling code here. (Omitted for clarity.)
}

작업을 간단하게 유지하기 위해 이 예제에서는 반환 값을 무시하지만 항상 메서드 호출에서 HRESULT 값을 검사 합니다.

다음으로 , CoCreateInstance 를 호출하여 필터 그래프 관리자를 만듭니다.

IGraphBuilder *pGraph;
HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, 
    CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);

표시된 것처럼 CLSID(클래스 식별자)는 CLSID_FilterGraph. Filter Graph Manager는 in-process DLL에서 제공되므로 실행 컨텍스트가 CLSCTX_INPROC_SERVER. DirectShow는 자유 스레딩 모델을 지원하므로 COINIT_MULTITHREADED 플래그를 사용하여 CoInitializeEx를 호출할 수도 있습니다.

CoCreateInstance 호출은 주로 필터 그래프를 빌드하는 메서드를 포함하는 IGraphBuilder 인터페이스를 반환합니다. 이 예제에는 두 개의 다른 인터페이스가 필요합니다.

  • IMediaControl 은 스트리밍을 제어합니다. 그래프를 중지하고 시작하는 메서드가 포함되어 있습니다.
  • IMediaEvent 에는 필터 그래프 관리자에서 이벤트를 가져오는 메서드가 있습니다. 이 예제에서는 인터페이스를 사용하여 재생이 완료되기를 기다립니다.

이러한 인터페이스는 모두 Filter Graph Manager에 의해 노출됩니다. 반환된 IGraphBuilder 포인터를 사용하여 쿼리합니다.

IMediaControl *pControl;
IMediaEvent   *pEvent;
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);

이제 필터 그래프를 빌드할 수 있습니다. 파일 재생의 경우 단일 메서드 호출을 통해 수행됩니다.

hr = pGraph->RenderFile(L"C:\\Example.avi", NULL);

IGraphBuilder::RenderFile 메서드는 지정된 파일을 재생할 수 있는 필터 그래프를 빌드합니다. 첫 번째 매개 변수는 와이드 문자(2 바이트) 문자열로 표현되는 파일 이름입니다. 두 번째 매개 변수는 예약되어 있으며 NULL과 같아야 합니다.

지정된 파일이 없거나 파일 형식이 인식되지 않으면 이 메서드가 실패할 수 있습니다. 그러나 메서드가 성공한다고 가정하면 이제 필터 그래프를 재생할 준비가 되었습니다. 그래프를 실행하려면 IMediaControl::Run 메서드를 호출합니다.

hr = pControl->Run();

필터 그래프가 실행되면 데이터가 필터를 통해 이동하고 비디오 및 오디오로 렌더링됩니다. 재생은 별도의 스레드에서 발생합니다. IMediaEvent::WaitForCompletion 메서드를 호출하여 재생이 완료되기를 기다릴 수 있습니다.

long evCode = 0;
pEvent->WaitForCompletion(INFINITE, &evCode);

이 메서드는 파일 재생이 완료될 때까지 또는 지정된 제한 시간 간격이 경과할 때까지 차단합니다. INFINITE 값은 파일이 재생될 때까지 애플리케이션이 무기한 차단되는 것을 의미합니다. 이벤트 처리의 보다 현실적인 예는 이벤트에 응답을 참조하세요.

애플리케이션이 완료되면 인터페이스 포인터를 해제하고 COM 라이브러리를 닫습니다.

pControl->Release();
pEvent->Release();
pGraph->Release();
CoUninitialize();

코드 예

다음은 이 문서에 설명된 예제의 전체 코드입니다.

#include <dshow.h>
void main(void)
{
    IGraphBuilder *pGraph = NULL;
    IMediaControl *pControl = NULL;
    IMediaEvent   *pEvent = NULL;

    // Initialize the COM library.
    HRESULT hr = CoInitialize(NULL);
    if (FAILED(hr))
    {
        printf("ERROR - Could not initialize COM library");
        return;
    }

    // Create the filter graph manager and query for interfaces.
    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
                        IID_IGraphBuilder, (void **)&pGraph);
    if (FAILED(hr))
    {
        printf("ERROR - Could not create the Filter Graph Manager.");
        return;
    }

    hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
    hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);

    // Build the graph. IMPORTANT: Change this string to a file on your system.
    hr = pGraph->RenderFile(L"C:\\Example.avi", NULL);
    if (SUCCEEDED(hr))
    {
        // Run the graph.
        hr = pControl->Run();
        if (SUCCEEDED(hr))
        {
            // Wait for completion.
            long evCode;
            pEvent->WaitForCompletion(INFINITE, &evCode);

            // Note: Do not use INFINITE in a real application, because it
            // can block indefinitely.
        }
    }
    pControl->Release();
    pEvent->Release();
    pGraph->Release();
    CoUninitialize();
}

기본 DirectShow 작업