재생 목록을 만드는 방법

이 항목에서는 시퀀스 원본을 사용하여 파일 시퀀스를 재생하는 방법을 설명합니다.

개요

시퀀스에서 미디어 파일을 재생하려면 애플리케이션이 재생 목록을 만들기 위해 시퀀스에 토폴로지 를 추가하고 재생을 위해 미디어 세션에서 이러한 토폴로지 큐에 대기해야 합니다.

시퀀서 소스는 미디어 세션이 현재 토폴로지 재생을 시작하기 전에 다음 토폴로지를 초기화하고 로드하여 원활한 재생을 보장합니다. 이렇게 하면 애플리케이션이 필요할 때마다 신속하게 다음 토폴로지를 시작할 수 있습니다.

미디어 세션은 싱크에 데이터를 공급하고 시퀀스 원본에서 토폴로지 재생을 담당합니다. 또한 미디어 세션은 세그먼트의 프레젠테이션 시간을 관리합니다.

시퀀서 원본이 토폴로지를 관리하는 방법에 대한 자세한 내용은 Sequencer 원본 정보를 참조하세요.

이 연습에는 다음 단계가 포함됩니다.

  1. 필수 구성 요소
  2. Media Foundation 초기화
  3. Media Foundation 개체 만들기
  4. 미디어 원본 만들기
  5. 부분 토폴로지 만들기
  6. Sequencer 원본에 토폴로지 추가
  7. 미디어 세션에서 첫 번째 토폴로지 설정
  8. 미디어 세션에서 다음 토폴로지 큐
  9. Sequencer 원본 해제

이 항목에 표시된 코드 예제는 전체 예제 코드를 포함하는 Sequencer 소스 예제 코드 항목에서 발췌한 것입니다.

사전 요구 사항

이 연습을 시작하기 전에 다음 Media Foundation 개념을 숙지하세요.

여기에서 예제 코드가 해당 항목의 코드에서 확장되므로 Media Foundation을 사용하여 미디어 파일을 재생하는 방법도 참조하세요.

Media Foundation 초기화

Media Foundation 인터페이스 또는 메서드를 사용하려면 먼저 MFStartup 함수를 호출하여 Media Foundation을 초기화합니다. 자세한 내용은 Media Foundation 초기화를 참조하세요.

    hr = MFStartup(MF_VERSION);

Media Foundation 개체 만들기

다음으로, 다음 Media Foundation 개체를 만듭니다.

  • 미디어 세션. 이 개체는 현재 토폴로지를 재생, 일시 중지 및 중지하는 메서드를 제공하는 IMFMediaSession 인터페이스를 노출합니다.
  • Sequencer 원본입니다. 이 개체는 시퀀스에서 토폴로지 추가, 업데이트 및 삭제하는 메서드를 제공하는 IMFSequencerSource 인터페이스를 노출합니다.
  1. MFCreateMediaSession 함수를 호출하여 미디어 세션을 만듭니다.
  2. IMFMediaEventQueue::BeginGetEvent를 호출하여 미디어 세션에서 첫 번째 이벤트를 요청합니다.
  3. MFCreateSequencerSource 함수를 호출하여 시퀀서 원본을 만듭니다.

다음 코드는 미디어 세션을 만들고 첫 번째 이벤트를 요청합니다.

//  Create a new instance of the media session.
HRESULT CPlayer::CreateSession()
{
    // Close the old session, if any.
    HRESULT hr = CloseSession();
    if (FAILED(hr))
    {
        goto done;
    }

    assert(m_state == Closed);

    // Create the media session.
    hr = MFCreateMediaSession(NULL, &m_pSession);
    if (FAILED(hr))
    {
        goto done;
    }

    // Start pulling events from the media session
    hr = m_pSession->BeginGetEvent((IMFAsyncCallback*)this, NULL);
    if (FAILED(hr))
    {
        goto done;
    }

    m_state = Ready;

done:
    return hr;
}

미디어 원본 만들기

다음으로, 첫 번째 재생 목록 세그먼트에 대한 미디어 원본을 만듭니다. 원본 확인자를 사용하여 URL에서 미디어 원본을 만듭니다. 이렇게 하려면 MFCreateSourceResolver 함수를 호출하여 원본 확인자를 만든 다음 IMFSourceResolver::CreateObjectFromURL 메서드를 호출하여 미디어 원본을 만듭니다.

미디어 원본에 대한 자세한 내용은 미디어 원본을 참조하세요.

부분 토폴로지 만들기

시퀀서 원본의 각 세그먼트에는 자체 부분 토폴로지가 있습니다. 다음으로 미디어 원본에 대한 부분 토폴로지 만들기 부분 토폴로지의 경우 토폴로지 원본 노드는 중간 변환을 지정하지 않고 출력 노드에 직접 연결됩니다. 미디어 세션은 토폴로지 로더 개체를 사용하여 토폴로지를 resolve. 토폴로지를 확인하면 필요한 디코더 및 기타 변환 노드가 추가됩니다. 시퀀서 원본에는 전체 토폴로지도 포함될 수 있습니다.

토폴로지 개체를 만들려면 MFCreateTopology 함수를 사용한 다음 IMFTopologyNode 인터페이스를 사용하여 스트림 노드를 만듭니다.

이러한 프로그래밍 요소를 사용하여 토폴로지 만들기에 대한 전체 지침은 재생 토폴로지 만들기를 참조하세요.

애플리케이션은 원본 노드를 구성하여 네이티브 소스의 선택한 부분을 재생할 수 있습니다. 이렇게 하려면 MF_TOPOLOGY_SOURCESTREAM_NODE 토폴로지 노드에서 MF_TOPONODE_MEDIASTART 특성 및 MF_TOPONODE_MEDIASTOP 특성을 설정합니다. 네이티브 소스의 시작을 기준으로 미디어 시작 시간과 미디어 중지 시간을 UINT64 형식으로 지정합니다.

Sequencer 원본에 토폴로지 추가

다음으로, 만든 부분 토폴로지를 시퀀서 소스에 추가합니다. 세그먼트라고 하는 각 시퀀스 요소에는 MFSequencerElementId 식별자가 할당됩니다. 시퀀서 원본이 토폴로지를 관리하는 방법에 대한 자세한 내용은 Sequencer 원본 정보를 참조하세요.

모든 토폴로지를 시퀀서 원본에 추가한 후 애플리케이션은 파이프라인에서 재생을 종료하기 위해 시퀀스의 마지막 세그먼트에 플래그를 지정해야 합니다. 이 플래그가 없으면 시퀀서 소스에 더 많은 토폴로지 추가가 예상됩니다.

  1. IMFSequencerSource::AppendTopology 메서드를 호출하여 시퀀서 원본에 특정 토폴로지를 추가합니다.

        hr = m_pSequencerSource->AppendTopology(
            pTopology, 
            SequencerTopologyFlags_Last, 
            &SegmentId
            );
    

    AppendTopology 는 지정된 토폴로지를 시퀀스에 추가합니다. 이 메서드는 pdwId 매개 변수의 세그먼트 식별자를 반환합니다.

    토폴로지가 시퀀서 원본의 마지막 토폴로지인 경우 dwFlags 매개 변수에 SequencerTopologyFlags_Last 전달합니다. 이 값은 MFSequencerTopologyFlags 열거형에 정의되어 있습니다.

  2. IMFSequencerSource::UpdateTopologyFlags를 호출하여 입력 목록의 세그먼트 식별자와 연결된 토폴로지의 플래그를 업데이트합니다. 이 경우 호출은 지정된 세그먼트가 시퀀서의 마지막 세그먼트임을 나타냅니다. (마지막 토폴로지를 AppendTopology 호출에 지정한 경우 이 호출은 선택 사항입니다.)

        BOOL bFirstSegment = (NumSegments() == 0);
    
        if (!bFirstSegment)
        {
            // Remove the "last segment" flag from the last segment.
            hr = m_pSequencerSource->UpdateTopologyFlags(LastSegment(), 0);
            if (FAILED(hr))
            {
                goto done;
            }
        }
    

애플리케이션은 IMFSequencerSource::UpdateTopology 를 호출하고 pTopology에서 새 토폴로지를 전달하여 세그먼트의 토폴로지를 다른 토폴로지로 바꿀 수 있습니다. 새 토폴로지에서 새 네이티브 원본이 있는 경우 원본이 원본 캐시에 추가됩니다. 사전 등록 목록도 새로 고쳐집니다.

미디어 세션에서 첫 번째 토폴로지 설정

다음으로 미디어 세션의 시퀀스 원본에서 첫 번째 토폴로지를 큐에 대기합니다. 시퀀서 원본에서 첫 번째 토폴로지를 얻으려면 애플리케이션에서 IMFMediaSourceTopologyProvider::GetMediaSourceTopology 메서드를 호출해야 합니다. 이 메서드는 미디어 세션에서 확인하는 부분 토폴로지를 반환합니다.

부분 토폴로지에 대한 자세한 내용은 토폴로지 정보를 참조하세요.

  1. 시퀀스 원본의 첫 번째 토폴로지의 네이티브 미디어 원본을 검색합니다.

  2. IMFMediaSource::CreatePresentationDescriptor 메서드를 호출하여 미디어 원본에 대한 프레젠테이션 설명자를 만듭니다.

  3. IMFMediaSourceTopologyProvider::GetMediaSourceTopology 메서드를 호출하여 프레젠테이션에 연결된 토폴로지를 검색합니다.

  4. IMFMediaSession::SetTopology를 호출하여 미디어 세션에서 첫 번째 토폴로지를 설정합니다.

    dwSetTopologyFlags 매개 변수가 NULL로 설정된 SetTopology를 호출합니다. 그러면 미디어 세션이 현재 토폴로지를 완료할 때 지정된 토폴로지를 시작하도록 지시합니다. 이 경우 지정된 토폴로지는 첫 번째 토폴로지이고 현재 프레젠테이션이 없으므로 미디어 세션에서 새 프레젠테이션을 즉시 시작합니다.

    또한 NULL 값은 토폴로지 공급자가 반환하는 토폴로지는 항상 부분 토폴로지이므로 미디어 세션이 토폴로지를 resolve 있음을 나타냅니다.

// Queues the next topology on the session.

HRESULT CPlaylist::QueueNextSegment(IMFPresentationDescriptor *pPD)
{
    IMFMediaSourceTopologyProvider *pTopoProvider = NULL;
    IMFTopology *pTopology = NULL;

    //Get the topology for the presentation descriptor
    HRESULT hr = m_pSequencerSource->QueryInterface(IID_PPV_ARGS(&pTopoProvider));
    if (FAILED(hr))
    {
        goto done;
    }

    hr = pTopoProvider->GetMediaSourceTopology(pPD, &pTopology);
    if (FAILED(hr))
    {
        goto done;
    }

    //Set the topology on the media session
    m_pSession->SetTopology(NULL, pTopology);

done:
    SafeRelease(&pTopoProvider);
    SafeRelease(&pTopology);
    return hr;
}

미디어 세션에서 다음 토폴로지 큐

다음으로, 애플리케이션은 MENewPresentation 이벤트를 처리해야 합니다.

Sequencer 원본은 미디어 세션이 그 다음에 다른 세그먼트가 있는 세그먼트를 재생하기 시작할 때 MENewPresentation 을 발생합니다. 이 이벤트는 사전 등록 목록의 다음 세그먼트에 대한 프레젠테이션 설명자를 제공하여 시퀀스 원본의 다음 토폴로지를 애플리케이션에 알릴 수 있습니다. 애플리케이션은 토폴로지 공급자를 사용하여 연결된 토폴로지를 검색하고 미디어 세션에서 큐에 대기해야 합니다. 그런 다음 시퀀서 소스는 이 토폴로지를 미리 등록하여 프레젠테이션 간에 원활한 전환을 보장합니다.

애플리케이션이 여러 세그먼트를 검색할 때 시퀀서 원본이 사전 등록 목록을 새로 고치고 올바른 토폴로지를 설정함에 따라 애플리케이션은 여러 MENewPresentation 이벤트를 받습니다. 애플리케이션은 각 이벤트를 처리하고 미디어 세션의 이벤트 데이터에 반환된 토폴로지를 큐에 대기시켜야 합니다. 세그먼트를 건너뛰는 방법에 대한 자세한 내용은 Sequencer 원본 사용을 참조하세요.

sequencer 원본 알림을 받는 방법에 대한 자세한 내용은 Sequencer 원본 이벤트를 참조하세요.

  1. MENewPresentation 이벤트 처리기에서 이벤트 데이터에서 다음 세그먼트에 대한 프레젠테이션 설명자를 검색합니다.

  2. IMFMediaSourceTopologyProvider::GetMediaSourceTopology 메서드를 호출하여 프레젠테이션에 연결된 토폴로지를 가져옵니다.

  3. IMFMediaSession::SetTopology 메서드를 호출하여 미디어 세션에서 토폴로지를 설정합니다.

    미디어 세션은 현재 프레젠테이션이 완료되면 새 프레젠테이션을 시작합니다.

HRESULT CPlaylist::OnNewPresentation(IMFMediaEvent *pEvent)
{
    IMFPresentationDescriptor *pPD = NULL;

    HRESULT hr = GetEventObject(pEvent, &pPD);

    if (SUCCEEDED(hr))
    {
        // Queue the next segment on the media session
        hr = QueueNextSegment(pPD);
    }

    SafeRelease(&pPD);
    return hr;
}

Sequencer 원본 해제

마지막으로 시퀀서 원본을 종료합니다. 이렇게 하려면 시퀀서 원본에서 IMFMediaSource::Shutdown 메서드를 호출합니다. 이 호출은 시퀀서 원본의 모든 기본 네이티브 미디어 원본을 종료합니다.

시퀀서 소스를 릴리스한 후 애플리케이션은 해당 순서대로 IMFMediaSession::Close 및 IMFMediaSession::Shutdown을 호출하여 미디어 세션을 종료하고 종료해야 합니다.

메모리 누수 방지를 위해 애플리케이션은 더 이상 필요하지 않은 경우 Media Foundation 인터페이스에 대한 포인터를 해제해야 합니다.

다음 단계

이 연습에서는 시퀀서 원본을 사용하여 기본 재생 목록을 만드는 방법을 설명했습니다. 재생 목록을 만든 후 세그먼트 건너뛰기, 재생 상태 변경 및 세그먼트 내에서 검색과 같은 고급 기능을 추가할 수 있습니다. 다음 목록에서는 관련 topics 대한 링크를 제공합니다.

Sequencer 원본