미디어 싱크

미디어 싱크는 미디어 데이터를 수신하는 파이프라인 개체입니다. 미디어 싱크는 하나 이상의 미디어 스트림에 대한 대상입니다. 미디어 싱크는 다음 두 가지 일반 범주로 분류됩니다.

  • 렌더러는 재생을 위한 데이터를 제공하는 미디어 싱크입니다. 향상된 EVR(비디오 렌더러)은 비디오 프레임을 표시하고 오디오 렌더러는 사운드 카드 또는 기타 오디오 디바이스를 통해 오디오 스트림을 재생합니다.

  • 보관 싱크는 파일 또는 다른 스토리지에 데이터를 쓰는 미디어 싱크입니다.

기본 차이점은 보관 싱크가 고정 재생 속도로 데이터를 사용하지 않는다는 것입니다. 대신 가능한 한 빨리 수신하는 데이터를 씁니다.

미디어 싱크는 IMFMediaSink 인터페이스를 노출합니다. 각 미디어 싱크에는 하나 이상의 스트림 싱크가 포함되어 있습니다. 각 스트림 싱크는 한 스트림에서 데이터를 받습니다. 스트림 싱크는 IMFStreamSink 인터페이스를 노출합니다. 일반적으로 애플리케이션은 미디어 싱크를 직접 만들지 않습니다. 대신 애플리케이션은 미디어 세션에서 싱크를 만드는 데 사용하는 하나 이상의 활성화 개체를 만듭니다. 싱크의 다른 모든 작업은 미디어 세션에서 처리되며 애플리케이션은 미디어 싱크 또는 스트림 싱크에서 메서드를 호출하지 않습니다. 활성화 개체에 대한 자세한 내용은 활성화 개체를 참조하세요.

사용자 지정 미디어 싱크를 작성하거나 미디어 세션 없이 미디어 싱크를 직접 사용하려는 경우 이 항목의 나머지 부분을 읽어야 합니다.

스트림 싱크

미디어 싱크에는 고정된 수의 스트림 싱크가 있거나 스트림 싱크 추가 및 제거를 지원할 수 있습니다. 고정된 수의 스트림 싱크가 있는 경우 IMFMediaSink::GetCharacteristics 메서드는 MEDIASINK_FIXED_STREAMS 플래그를 반환합니다. 그렇지 않으면 스트림 싱크를 추가하고 제거할 수 있습니다. 새 스트림 싱크를 추가하려면 IMFMediaSink::AddStreamSink를 호출합니다. 스트림 싱크를 제거하려면 IMFMediaSink::RemoveStreamSink를 호출합니다. MEDIASINK_FIXED_STREAMS 플래그는 미디어 싱크가 이러한 두 메서드를 지원하지 않음을 나타냅니다. (예를 들어 싱크를 만들 때 초기화 매개 변수를 설정하여 스트림 수를 구성하는 다른 방법을 지원할 수 있습니다.) 스트림 싱크 목록이 정렬됩니다. 인덱스 값으로 열거하려면 IMFMediaSink::GetStreamSinkByIndex 메서드를 호출합니다.

스트림 싱크에는 식별자도 있습니다. 스트림 식별자는 미디어 싱크 내에서 고유하지만 연속될 필요는 없습니다. 미디어 싱크에 따라 스트림 식별자는 콘텐츠와 관련된 의미를 가질 수 있습니다. 예를 들어 보관 싱크는 스트림 식별자를 파일 헤더에 쓸 수 있습니다. 그렇지 않으면 임의입니다. 식별자를 통해 스트림 싱크를 얻으려면 IMFMediaSink::GetStreamSinkById를 호출합니다.

프레젠테이션 시계

미디어 싱크에서 샘플을 사용하는 속도는 프레젠테이션 시계에 의해 제어됩니다. 미디어 세션은 프레젠테이션 시계를 선택하고 미디어 싱크의 IMFMediaSink::SetPresentationClock 메서드를 호출하여 미디어 싱크에서 설정합니다. 스트리밍을 시작하려면 먼저 미디어 싱크에서 프레젠테이션 시계를 설정해야 합니다. 모든 미디어 싱크를 실행하려면 프레젠테이션 시계가 필요합니다. 미디어 싱크는 다음 두 가지 용도로 프레젠테이션 시계를 사용합니다.

  • 스트리밍이 시작되거나 중지될 때 알림을 받으려면 미디어 싱크는 모든 미디어 싱크가 구현해야 하는 IMFClockStateSink 인터페이스를 통해 이러한 알림을 받습니다.

  • 샘플을 렌더링해야 하는 시기를 결정합니다. 미디어 싱크가 새 샘플을 받으면 샘플에서 타임스탬프를 가져오고 해당 프레젠테이션 시간에 샘플을 렌더링하려고 시도합니다.

프레젠테이션 시계는 프레젠테이션 시간 원본이라는 다른 개체에서 시계 시간을 파생합니다. 프레젠테이션 시간 원본은 IMFPresentationTimeSource 인터페이스를 노출합니다. 일부 미디어 싱크는 정확한 클록에 액세스할 수 있으므로 이 인터페이스를 노출합니다. 즉, 미디어 싱크는 자체 클록에서 제공하는 시간에 대해 샘플을 예약할 수 있습니다. 그러나 미디어 싱크는 이를 사례로 간주할 수 없습니다. 프레젠테이션 시계가 미디어 싱크 자체에 의해 구동되는지 또는 다른 시계에 의해 구동되는지에 관계없이 항상 프레젠테이션 시계의 시간을 사용해야 합니다.

미디어 싱크가 자체 클록 이외의 클록과 속도를 일치시킬 수 없는 경우 GetCharacteristics 메서드는 MEDIASINK_CANNOT_MATCH_CLOCK 플래그를 반환합니다. 이 플래그가 있고 프레젠테이션 시계가 다른 프레젠테이션 시간 원본을 사용하는 경우 미디어 싱크의 성능이 저하될 수 있습니다. 예를 들어 재생 중에 결함이 발생할 수 있습니다.

속도 없는 싱크는 샘플의 타임스탬프를 무시하고 각 샘플이 도착하는 즉시 데이터를 사용하는 미디어 싱크입니다. 속도 없는 미디어 싱크는 GetCharacteristics 메서드에서 MEDIASINK_RATELESS 플래그를 반환합니다. 일반적으로 이 플래그는 보관 싱크에 적용됩니다. 파이프라인의 모든 미디어 싱크가 속도 없는 경우 미디어 세션은 특별한 속도 없는 프레젠테이션 시계를 사용합니다. 이 클록은 싱크에서 샘플을 사용하는 만큼 빠르게 실행됩니다.

스트림 형식

미디어 싱크가 샘플을 수신하려면 먼저 클라이언트가 스트림 싱크에서 미디어 형식을 설정해야 합니다. 미디어 형식을 설정하려면 스트림 싱크의 IMFStreamSink::GetMediaTypeHandler 메서드를 호출합니다. 이 메서드는 IMFMediaTypeHandler 인터페이스에 대한 포인터를 반환합니다. 이 인터페이스를 사용하여 기본 미디어 형식 목록을 가져와 현재 미디어 형식을 가져와 미디어 형식을 설정합니다.

기본 설정 미디어 형식 목록을 얻으려면 IMFMediaTypeHandler::GetMediaTypeByIndex를 호출합니다. 기본 설정 형식은 클라이언트에 대한 힌트로 사용해야 합니다. 목록이 불완전하거나 부분 미디어 형식을 포함할 수 있습니다. 부분 미디어 형식은 유효한 형식을 설명하는 데 필요한 모든 특성이 없는 형식입니다. 예를 들어 부분 비디오 형식은 색 공간과 비트 깊이를 지정할 수 있지만 이미지 너비나 높이는 지정할 수 없습니다. 부분 오디오 유형은 압축 형식과 샘플 속도를 지정할 수 있지만 오디오 채널 수는 지정할 수 없습니다.

스트림 싱크의 현재 미디어 형식을 얻으려면 IMFMediaTypeHandler::GetCurrentMediaType을 호출합니다. 스트림 싱크를 처음 만들 때 기본 미디어 형식이 이미 설정되어 있거나 클라이언트가 설정할 때까지 미디어 형식이 없을 수 있습니다.

미디어 유형을 설정하려면 IMFMediaTypeHandler::SetCurrentMediaType을 호출합니다. 일부 스트림 싱크는 가 설정된 후 형식 변경을 지원하지 않을 수 있습니다. 따라서 미디어 형식을 설정하기 전에 테스트하는 것이 유용합니다. 미디어 싱크가 형식을 설정하지 않고 미디어 형식을 허용할지 여부를 테스트하려면 IMFMediaTypeHandler::IsMediaTypeSupported를 호출합니다.

데이터 흐름

미디어 싱크는 끌어오기 모델을 사용합니다. 즉, 스트림 싱크는 필요에 따라 데이터를 요청합니다. 클라이언트는 결함을 방지하기 위해 적시에 응답해야 합니다.

일부 미디어 싱크는 사전 등록을 지원합니다. 미리 등록은 프레젠테이션 시계가 시작되기 전에 미디어 싱크에 데이터를 제공하는 프로세스입니다. 미디어 싱크가 사전 등록을 지원하는 경우 미디어 싱크는 IMFMediaSinkPreroll 인터페이스를 노출하고 GetCharacteristics 메서드는 MEDIASINK_CAN_PREROLL 플래그를 반환합니다. 미리 등록하면 프레젠테이션 클록이 시작될 때 미디어 싱크가 첫 번째 샘플을 표시할 준비가 되었는지 확인합니다. 재생 중에 결함이나 간격을 방지할 수 있으므로 미디어 싱크가 지원하는 경우 클라이언트는 항상 미리 등록하는 것이 좋습니다.

미디어 싱크로의 데이터 흐름은 다음과 같이 작동합니다.

  1. 클라이언트는 미디어 유형 및 프레젠테이션 시계를 설정합니다. 미디어 싱크는 프레젠테이션 클록에 자신을 등록하여 클록 상태 변경에 대한 알림을 받습니다.
  2. 필요에 따라 클라이언트는 IMFMediaSinkPreroll을 쿼리합니다. 미디어 싱크가 이 인터페이스를 노출하는 경우 클라이언트는 IMFMediaSinkPreroll::NotifyPreroll을 호출합니다. 그렇지 않으면 클라이언트가 5단계로 건너뜁니다.
  3. 각 스트림 싱크는 하나 이상의 MEStreamSinkRequestSample 이벤트를 보냅니다. 이러한 각 이벤트에 대한 응답으로 클라이언트는 해당 스트림에 대한 다음 데이터 샘플을 가져오고 IMFStreamSink::P rocessSample을 호출합니다.
  4. 각 스트림 싱크가 충분한 사전 등록 데이터를 받으면 MEStreamSinkPrerolled 이벤트를 보냅니다.
  5. 클라이언트는 IMFPresentationClock::Start 를 호출하여 프레젠테이션 시계를 시작합니다.
  6. 프레젠테이션 시계는 IMFClockStateSink::OnClockStart를 호출하여 미디어 싱크에 시계가 시작되고 있음을 알 수 있습니다.
  7. 더 많은 데이터를 가져오기 위해 각 스트림 싱크는 MEStreamSinkRequestSample 이벤트를 보냅니다. 이러한 각 이벤트에 대한 응답으로 클라이언트는 다음 샘플을 가져오고 ProcessSample을 호출합니다. 이 단계는 프레젠테이션이 끝날 때까지 반복됩니다.

대부분의 미디어 싱크는 샘플을 비동기적으로 처리하므로 스트림 싱크는 한 번에 둘 이상의 샘플 요청을 보낼 수 있습니다.

스트리밍하는 동안 클라이언트는 언제든지 IMFStreamSink::P laceMarkerIMFStreamSink::Flush 를 호출할 수 있습니다. 표식은 다음 섹션에서 설명합니다. 플러시하면 스트림 싱크가 큐에 대기되었지만 아직 렌더링되지 않은 샘플을 삭제합니다.

표식

표식은 클라이언트가 스트림의 특정 지점을 나타내는 방법을 제공합니다. 표식은 다음 정보로 구성됩니다.

  • MFSTREAMSINK_MARKER_TYPE 열거형의 멤버로 정의된 표식 형식입니다.
  • 표식과 연결된 데이터입니다. 데이터의 의미는 표식 형식에 따라 달라집니다. 일부 표식 형식에는 데이터가 없습니다.
  • 클라이언트 자체 사용을 위한 선택적 데이터입니다.

마커를 배치하기 위해 클라이언트는 IMFStreamSink::P laceMarker를 호출합니다. 스트림 싱크는 PlaceMarker 호출 전에 받은 샘플 처리를 완료한 다음 MEStreamSinkMarker 이벤트를 보냅니다.

대부분의 미디어 싱크는 비동기적으로 처리하는 보류 중인 샘플 큐를 유지합니다. 마커 이벤트는 샘플 처리로 직렬화되어야 하므로 미디어 싱크는 마커를 동일한 큐에 배치해야 합니다. 예를 들어 클라이언트가 다음 메서드 호출을 수행한다고 가정합니다.

  1. ProcessSample (샘플 #1)
  2. ProcessSample (샘플 #2)
  3. PlaceMarker (표식 #1)
  4. ProcessSample (샘플 #3)
  5. PlaceMarker (표식 #2)

이 예제에서 스트림 싱크는 샘플 #2를 처리한 후 마커 #1에 MEStreamSinkMarker 이벤트를 보내고 샘플 #3을 처리한 후 마커 #2에 대한 이벤트를 보내야 합니다.

클라이언트가 스트림 싱크를 플러시하는 경우 스트림 싱크는 큐에 있던 마커를 즉시 처리합니다. 이러한 이벤트에 대해 E_ABORT 상태 코드를 설정합니다.

일부 표식에는 미디어 싱크와 관련된 정보가 포함됩니다.

  • MFSTREAMSINK_MARKER_TICK: 스트림에 간격이 있음을 나타냅니다. 다음 샘플은 불연속성입니다.
  • MFSTREAMSINK_MARKER_ENDOFSEGMENT: 세그먼트의 끝 또는 스트림의 끝을 나타냅니다. 다음 샘플(있는 경우)은 불연속성일 수 있습니다.
  • MFSTREAMSINK_MARKER_EVENT: 이벤트를 포함합니다. 미디어 싱크의 이벤트 유형 및 구현에 따라 미디어 싱크에서 이벤트를 처리하거나 무시할 수 있습니다.

상태 변경

미디어 싱크의 IMFClockStateSink 인터페이스를 통해 프레젠테이션 시계의 상태 변경에 대한 알림이 미디어 싱크에 표시됩니다. 클라이언트가 프레젠테이션 시계를 설정하면 미디어 싱크가 IMFPresentationClock::AddClockStateSink 를 호출하여 시계의 알림에 대해 자신을 등록합니다. 다음 표에서는 클록 상태 변경에 대한 응답으로 미디어 싱크가 작동하는 방식을 요약합니다.

클록 상태 변경 샘플 처리 표식 처리
OnClockStart 타임스탬프를 클록 시작 시간과 같거나 이후인 프로세스 샘플입니다. 마커가 처리되기 전에 모든 샘플이 수신되면 MEStreamSinkMarker 이벤트를 보냅니다.
OnClockPause 미디어 싱크가 일시 중지된 동안 ProcessSample 에 실패할 수 있습니다.
미디어 싱크가 일시 중지된 동안 샘플을 수락하는 경우 시계가 다시 시작될 때까지 큐에 대기해야 합니다. 일시 중지된 동안 큐에 대기 중인 샘플을 처리하지 마세요.
큐에 대기 중인 샘플이 있는 경우 마커를 동일한 큐에 배치합니다. 시계가 다시 시작될 때 표식 이벤트를 보냅니다.
그렇지 않으면 마커 이벤트를 즉시 보냅니다.
OnClockRestart 일시 중지된 동안 큐에 대기된 샘플을 처리한 다음 OnClockStart와 동일하게 처리합니다. 큐에 대기 중인 마커(샘플 처리로 직렬화됨)에 MEStreamSinkMarker 이벤트를 보낸 다음 OnClockStart와 동일하게 처리합니다.
OnClockStop 큐에 대기된 모든 샘플을 삭제합니다. ProcessSample에 대한 추가 호출이 실패할 수 있습니다. 큐에 대기된 마커 이벤트를 보냅니다. PlaceMarker에 대한 후속 호출에서 마커 이벤트를 즉시 보냅니다.

 

또한 스트림 싱크는 상태 전환을 완료했을 때 다음 이벤트를 보내야 합니다.

종료하는 중

일부 미디어 싱크는 마지막 샘플이 전달된 후 추가 처리 단계가 필요합니다. 일반적으로 이 요구 사항은 파일에 헤더 또는 인덱스를 작성해야 하는 보관 싱크에 적용됩니다. 미디어 싱크에 최종 처리가 필요한 경우 IMFFinalizableMediaSink 인터페이스가 노출됩니다.

클라이언트가 마지막 샘플을 전달한 후 클라이언트는 이 인터페이스에 대해 쿼리합니다. 미디어 싱크가 인터페이스를 지원하는 경우 클라이언트는 IMFFinalizableMediaSink::BeginFinalize 를 호출하여 최종 처리를 비동기적으로 수행합니다. 이 메서드는 비동기 콜백 메서드에 설명된 표준 Media Foundation 비동기 모델을 따릅니다. 미디어 싱크는 클라이언트가 BeginFinalize를 호출한다고 가정할 수 있습니다. BeginFinalize를 호출하지 않으면 잘못 작성된 파일이 발생할 수 있습니다.

종료 중

클라이언트가 미디어 싱크를 사용하여 완료되면 클라이언트는 IMFMediaSink::Shutdown을 호출합니다. 이 메서드 내에서 미디어 싱크는 순환 참조 수를 중단해야 합니다. 일반적으로 미디어 싱크와 스트림 싱크 간에 순환 참조가 있습니다.

이벤트 큐 도우미 개체를 사용하여 IMFMediaEventGenerator를 구현하는 경우 이벤트 큐에서 IMFMediaEventQueue::Shutdown 을 호출합니다. 이 메서드는 이벤트 큐를 종료하고 현재 이벤트를 대기 중인 모든 호출자에게 신호를 보냅니다.

종료 후 미디어 싱크의 모든 메서드는 IUnknown 메서드를 제외하고 MF_E_SHUTDOWN 반환합니다.

미디어 싱크 인터페이스

다음 표에서는 미디어 싱크가 QueryInterface를 통해 노출할 수 있는 표준 인터페이스를 나열합니다. 미디어 싱크는 사용자 지정 인터페이스를 노출할 수도 있습니다.

인터페이스 설명
IMFMediaSink 미디어 싱크의 기본 인터페이스입니다. (필수)
IMFClockStateSink 프레젠테이션 클록이 상태를 변경할 때 미디어 싱크에 알리는 데 사용됩니다. (필수)
IMFFinalizableMediaSink 미디어 싱크가 최종 처리 단계를 수행해야 하는 경우 를 구현합니다. 선택 사항입니다.
IMFGetService 미디어 싱크가 서비스 인터페이스를 노출하는 경우 를 구현합니다. 선택 사항입니다.
IMFMediaEventGenerator 미디어 싱크가 이벤트를 보내는 경우 를 구현합니다. 선택 사항입니다.
IMFMediaSinkPreroll 미디어 싱크가 사전 등록을 지원하는 경우 를 구현합니다. 선택 사항입니다.
IMFPresentationTimeSource 미디어 싱크가 프레젠테이션 시계에 대한 시간 원본을 제공할 수 있는지를 구현합니다. 선택 사항입니다.
IMFQualityAdvise 미디어 싱크가 재생 품질을 조정할 수 있는지를 구현합니다. 선택 사항입니다.

 

필요에 따라 미디어 싱크는 다음 인터페이스를 서비스로 구현할 수 있습니다.

서비스 인터페이스 설명
IMFRateSupport 지원되는 재생 속도의 범위를 보고합니다.

 

서비스 인터페이스 및 IMFGetService에 대한 자세한 내용은 서비스 인터페이스를 참조하세요.

스트림 싱크 인터페이스

스트림 싱크는 QueryInterface를 통해 다음 인터페이스를 노출해야 합니다.

인터페이스 Description
IMFStreamSink 스트림 싱크의 기본 인터페이스입니다. (필수)
IMFMediaEventGenerator 이벤트를 큐에 대기합니다. IMFStreamSink 인터페이스는 이 인터페이스를 상속합니다. (필수)

 

현재 스트림 싱크에 대해 정의된 서비스 인터페이스는 없습니다.

스트림 싱크 이벤트

다음 표에서는 제네릭 스트림 싱크에 대해 정의된 이벤트를 나열합니다. 스트림 싱크는 여기에 나열되지 않은 사용자 지정 이벤트를 보낼 수도 있습니다.

이벤트 Description
MEStreamSinkFormatChanged 스트림 싱크의 미디어 형식이 더 이상 유효하지 않습니다. 선택 사항입니다.
MEStreamSinkMarker 마커가 처리되었습니다. (필수)
MEStreamSinkPaused 스트림 싱크가 일시 중지되었습니다. (필수)
MEStreamSinkPrerolled 사전 등록이 완료되었습니다. 선택 사항입니다.
MEStreamSinkRateChanged 스트림 싱크의 재생 속도가 변경되었습니다. 선택 사항입니다.
MEStreamSinkRequestSample 새 샘플이 요청됩니다. (필수)
MEStreamSinkScrubSampleComplete 스크럽 요청이 완료되었습니다. 선택 사항입니다.
MEStreamSinkStarted 스트림 싱크가 시작되었습니다. (필수)
MEStreamSinkStopped 스트림 싱크가 중지되었습니다. (필수)

 

현재 미디어 싱크에 대한 범용 이벤트는 정의되지 않습니다. 일부 미디어 싱크는 사용자 지정 이벤트를 보낼 수 있습니다.

Media Foundation 파이프라인

미디어 파운데이션 아키텍처