비동기 MFT

이 항목에서는 MFT(Media Foundation 변환)에 대한 비동기 데이터 처리에 대해 설명합니다.

참고

이 항목은 Windows 7 이상에 적용됩니다.

 

비동기 MFT 정보

Windows Vista에서 MFT가 도입되었을 때 API는 동기 데이터 처리를 위해 설계되었습니다. 해당 모델에서 MFT는 항상 입력을 받기 위해 대기하거나 출력을 생성하기 위해 대기합니다.

일반적인 비디오 디코더를 고려합니다. 디코딩된 프레임을 가져오기 위해 클라이언트는 IMFTransform::P rocessOutput을 호출합니다. 디코더에 프레임을 디코딩하기에 충분한 데이터가 있는 경우 ProcessOutput 은 프레임을 디코딩하는 동안 를 차단합니다. 그렇지 않으면 ProcessOutput클라이언트IMFTransform::P rocessInput을 호출해야 함을 나타내는 MF_E_TRANSFORM_NEED_MORE_INPUT 반환합니다.

디코더가 한 스레드에서 모든 디코딩 작업을 수행하는 경우 이 모델은 잘 작동합니다. 그러나 디코더가 여러 스레드를 사용하여 프레임을 병렬로 디코딩한다고 가정해 보겠습니다. 최상의 성능을 위해 디코더는 디코딩 스레드가 유휴 상태가 될 때마다 새 입력을 받아야 합니다. 그러나 스레드가 디코딩 작업을 완료하는 속도는 ProcessInputProcessOutput에 대한 클라이언트의 호출과 정확히 일치하지 않으므로 스레드가 작업을 기다리고 있습니다.

Windows 7에는 MFT에 대한 이벤트 기반 비동기 처리가 도입되었습니다. 이 모델에서는 MFT에 입력이 필요하거나 출력이 있을 때마다 클라이언트에 이벤트를 보냅니다.

일반 요구 사항

이 항목에서는 비동기 MFT와 동기 MFT의 차이점에 대해 설명합니다. 이 항목에서 설명한 경우를 제외하고 두 처리 모델은 동일합니다. (특히 형식 협상은 동일합니다.)

비동기 MFT는 다음 인터페이스를 구현해야 합니다.

이벤트

비동기 MFT는 다음 이벤트를 사용하여 데이터 처리 상태 신호를 보냅니다.

이벤트 Description
METransformNeedInput MFT가 더 많은 입력을 수락할 수 있을 때 전송됩니다.
METransformHaveOutput MFT에 출력이 있을 때 전송됩니다.
METransformDrainComplete 드레이닝 작업이 완료되면 전송됩니다. 드레이닝 을 참조하세요.
METransformMarker 표식이 프로세스일 때 전송됩니다. 표식을 참조하세요.

 

이러한 이벤트는 대역 외로 전송됩니다. MFT 컨텍스트에서 대역 내 이벤트와 대역 외 이벤트의 차이점을 이해하는 것이 중요합니다.

원래 MFT 디자인은 대역 내 이벤트를 지원합니다. 대역 내 이벤트에는 형식 변경에 대한 정보와 같은 데이터 스트림에 대한 정보가 포함됩니다. 클라이언트는 IMFTransform::P rocessEvent를 호출하여 MFT에 대역 내 이벤트를 보냅니다. MFT는 ProcessOutput 메서드에서 대역 내 이벤트를 클라이언트로 다시 보낼 수 있습니다. (특히 이벤트는 MFT_OUTPUT_DATA_BUFFER 구조체의 pEvents 멤버에서 전달됩니다.)

MFT는 다음과 같이 IMFMediaEventGenerator 인터페이스를 통해 대역 외 이벤트를 보냅니다.

  1. MFT는 미디어 이벤트 생성기에 설명된 대로 IMFMediaEventGenerator 인터페이스를 구현합니다.
  2. 클라이언트는 IMFMediaEventGenerator 인터페이스에 대한 MFT에서 IUnknown::QueryInterface를 호출합니다. 비동기 MFT는 이 인터페이스를 노출해야 합니다. 동기 MFT는 이 인터페이스를 노출해서는 안 됩니다.
  3. 클라이언트는 IMFMediaEventGenerator::BeginGetEventIMFMediaEventGenerator::EndGetEvent 를 호출하여 MFT에서 대역 외 이벤트를 수신합니다.

ProcessInput

IMFTransform::P rocessInput 메서드는 다음과 같이 수정됩니다.

  1. 스트리밍이 시작되면 클라이언트는 MFT_MESSAGE_NOTIFY_START_OF_STREAM 메시지를 보냅니다.
  2. 스트리밍하는 동안 MFT는 METransformNeedInput 이벤트를 전송하여 데이터를 요청합니다. 이벤트 데이터는 스트림 식별자입니다.
  3. METransformNeedInput 이벤트에 대해 클라이언트는 지정된 스트림에 대해 ProcessInput 을 호출합니다.
  4. 스트리밍이 끝나면 클라이언트는 MFT_MESSAGE_NOTIFY_END_OF_STREAM 메시지를 사용하여 ProcessMessage를 호출할 수 있습니다.

구현 정보:

ProcessOutput

IMFTransform::P rocessOutput 메서드는 다음과 같이 수정됩니다.

  1. MFT에 출력이 있을 때마다 METransformHaveOutput 이벤트를 보냅니다.
  2. METransformHaveOutput 이벤트에 대해 클라이언트는 ProcessOutput을 호출합니다.

구현 정보:

  • 클라이언트가 다른 시간에 ProcessOutput 을 호출하는 경우 메서드는 E_UNEXPECTED 반환합니다.
  • 비동기 MFT는 ProcessOutput 메서드에서 MF_E_TRANSFORM_NEED_MORE_INPUT 반환해서는 안 됩니다. MFT에 더 많은 입력이 필요한 경우 METransformNeedInput 이벤트를 보냅니다.

배출

MFT를 드레이닝하면 MFT는 이미 전송된 입력 데이터에서 가능한 한 많은 출력을 생성합니다. 비동기 MFT 드레이닝은 다음과 같이 작동합니다.

  1. 클라이언트는 MFT_MESSAGE_COMMAND_DRAIN 메시지를 보냅니다.
  2. MFT는 처리할 데이터가 더 이상 없을 때까지 METransformHaveOutput 이벤트를 계속 보냅니다. 이 시간 동안 METransformNeedInput 이벤트를 보내지 않습니다.
  3. MFT가 마지막 METransformHaveOutput 이벤트를 보낸 후 METransformDrainComplete 이벤트를 보냅니다.

드레이닝이 완료되면 MFT는 클라이언트로부터 MFT_MESSAGE_NOTIFY_START_OF_STREAM 메시지를 받을 때까지 다른 METransformNeedInput 이벤트를 보내지 않습니다.

플러싱

클라이언트는 MFT_MESSAGE_COMMAND_FLUSH 메시지를 보내 MFT를 플러시할 수 있습니다. MFT는 보유하고 있는 모든 입력 및 출력 샘플을 삭제합니다.

MFT는 클라이언트에서 MFT_MESSAGE_NOTIFY_START_OF_STREAM 메시지를 받을 때까지 다른 METransformNeedInput 이벤트를 보내지 않습니다.

표식

클라이언트는 MFT_MESSAGE_COMMAND_MARKER 메시지를 보내 스트림의 점을 표시할 수 있습니다. MFT는 다음과 같이 응답합니다.

  1. MFT는 기존 입력 데이터에서 가능한 한 많은 출력 샘플을 생성하여 각 출력 샘플에 대해 METransformHaveOutput 이벤트를 보냅니다.
  2. 모든 출력이 생성되면 MFT는 METransformMarker 이벤트를 보냅니다. 이 이벤트는 모든 METransformHaveOutput 이벤트 후에 전송되어야 합니다.

예를 들어 디코더에 4개의 출력 샘플을 생성하기에 충분한 입력 데이터가 있다고 가정합니다. 클라이언트가 MFT_MESSAGE_COMMAND_MARKER 메시지를 보내는 경우 MFT는 4 개의 METransformHaveOutput 이벤트(출력 샘플당 하나씩)와 METransformMarker 이벤트를 큐에 대기합니다.

표식 메시지는 드레이닝 메시지와 유사합니다. 그러나 드레이닝은 스트림에서 중단으로 간주되는 반면 마커는 중단되지 않습니다. 드레이닝 및 마커에는 다음과 같은 차이점이 있습니다.

배출:

  • MFT는 드레이닝하는 동안 METransformNeedInput 이벤트를 보내지 않습니다.
  • MFT는 출력 샘플을 만드는 데 사용할 수 없는 모든 입력 데이터를 삭제합니다.
  • 일부 MFT는 데이터 끝에 "tail"을 생성합니다. 예를 들어 반향 또는 에코와 같은 오디오 효과는 입력 데이터가 중지된 후 추가 데이터를 생성합니다. 꼬리를 생성하는 MFT는 드레이닝 작업이 끝날 때 이 작업을 수행해야 합니다.
  • MFT가 드레이닝이 완료되면 다음 출력 샘플을 MFSampleExtension_Discontinuity 특성으로 표시하여 스트림의 불연속성을 나타냅니다.

마커:

  • MFT는 마커 이벤트를 보내기 전에 METransformNeedInput 이벤트를 계속 보냅니다.
  • MFT는 입력 데이터를 삭제하지 않습니다. 부분 데이터가 있는 경우 표식 점 다음에 처리해야 합니다.
  • MFT는 마커 지점에서 꼬리를 생성하지 않습니다.
  • MFT는 마커 지점 다음에 불연속성 플래그를 설정하지 않습니다.

변경 내용 서식 지정

비동기 MFT는 스트림 변경 처리에 설명된 대로 동적 형식 변경을 지원해야 합니다.

특성

비동기 MFT는 유효한 특성 저장소를 반환하려면 IMFTransform::GetAttributes 메서드를 구현해야 합니다. 다음 특성은 비동기 MFT에 적용됩니다.

attribute 설명
MF_TRANSFORM_ASYNC MFT는 이 특성을 TRUE (1)로 설정해야 합니다. 클라이언트는 이 특성을 쿼리하여 MFT가 비동기인지 여부를 검색할 수 있습니다.
MF_TRANSFORM_ASYNC_UNLOCK
MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE MFT는 이 특성을 TRUE (1)로 설정해야 합니다. 클라이언트는 이 특성이 설정된다고 가정할 수 있습니다.

 

비동기 MFT 잠금 해제

비동기 MFT는 원래 MFT 데이터 처리 모델과 호환되지 않습니다. 비동기 MFT가 기존 애플리케이션을 중단하지 않도록 하기 위해 다음 메커니즘이 정의됩니다.

클라이언트는 MFT 에서 IMFTransform::GetAttributes 를 호출합니다. 클라이언트는 이 MF_TRANSFORM_ASYNC 특성에 대해 를 쿼리합니다. 비동기 MFT의 경우 이 특성의 값은 **TRUE**입니다. MFT의 잠금을 해제하려면 클라이언트가 MF_TRANSFORM_ASYNC_UNLOCK 특성을 **TRUE**로 설정해야 합니다.

클라이언트가 MFT의 잠금을 해제할 때까지 모든 IMFTransform 메서드는 다음 예외를 제외하고 MF_E_TRANSFORM_ASYNC_LOCKED 반환해야 합니다.

다음 코드는 비동기 MFT의 잠금을 해제하는 방법을 보여줍니다.

HRESULT UnlockAsyncMFT(IMFTransform *pMFT)
{
    IMFAttributes *pAttributes = NULL;

    HRESULT hr = hr = pMFT->GetAttributes(&pAttributes);

    if (SUCCEEDED(hr))
    {
        hr = pAttributes->SetUINT32(MF_TRANSFORM_ASYNC_UNLOCK, TRUE);
        pAttributes->Release();
    }
    
    return hr;
}

MFT 종료

비동기 MFT는 IMFShutdown 인터페이스를 구현해야 합니다.

  • 종료: MFT는 이벤트 큐를 종료해야 합니다. 표준 이벤트 큐를 사용하는 경우 IMFMediaEventQueue::Shutdown을 호출합니다. 필요에 따라 MFT는 다른 리소스를 해제할 수 있습니다. 클라이언트는 Shutdown을 호출한 후 MFT를 사용하지 않아야 합니다.
  • GetShutdownStatus: 종료가 호출된 후 MFT는 pStatus 매개 변수에 MFSHUTDOWN_COMPLETED 값을 반환해야 합니다. MFSHUTDOWN_INITIATED 값을 반환해서는 안 됩니다.

등록 및 열거형

비동기 MFT를 등록하려면 MFTRegister 함수를 호출하고 Flags 매개 변수에서 MFT_ENUM_FLAG_ASYNCMFT 플래그를 설정합니다. (이전에는 이 플래그가 예약되었습니다.)

비동기 MFT를 열거하려면 MFTEnumEx 함수를 호출하고 Flags 매개 변수에서 MFT_ENUM_FLAG_ASYNCMFT 플래그를 설정합니다. 이전 버전과의 호환성을 위해 MFTEnum 함수는 비동기 MFT를 열거하지 않습니다. 그렇지 않으면 사용자의 컴퓨터에 비동기 MFT를 설치하면 기존 애플리케이션이 중단됩니다.

Media Foundation 변환