새 ASF 데이터 패킷 생성

ASF 멀티플렉서는ASF 데이터 개체 와 함께 작동하며 ContentInfo 개체에 정의된 요구 사항과 일치하는 스트림에 대한 ASF 데이터 패킷을 생성할 수 있는 기능을 애플리케이션에 제공하는 WMContainer 계층 구성 요소입니다.

멀티플렉서에는 하나의 입력과 하나의 출력이 있습니다. 디지털 미디어 데이터를 포함하는 스트림 샘플을 수신하고 ASF 컨테이너에 쓸 수 있는 하나 이상의 데이터 패킷을 생성합니다.

다음 목록에서는 ASF 데이터 패킷을 생성하는 프로세스를 요약합니다.

  1. 입력 데이터를 IMFASFMultiplexer::P rocessSample의 멀티플렉서에 전달합니다.
  2. 모든 전체 패킷이 검색될 때까지 루프에서 IMFASFMultiplexer::GetNextPacket 을 호출하여 데이터 패킷을 수집합니다.
  3. 입력 데이터가 전체 패킷으로 변환된 후에는 GetNextPacket에서 검색되지 않은 일부 보류 중인 데이터가 멀티플렉서에 있을 수 있습니다. IMFASFMultiplexer::Flush를 호출하여 보류 중인 샘플을 패킷화하고 GetNextPacket을 다시 호출하여 멀티플렉서에서 수집합니다.
  4. 데이터 패킷 생성 중에 멀티플렉서의 변경 내용을 반영하도록 IMFASFMultiplexer::End 를 호출하여 연결된 ASF 헤더 개체를 업데이트합니다.

다음 다이어그램에서는 멀티플렉서에서 ASF 파일의 데이터 패킷 생성을 보여 줍니다.

asf 파일에 대한 데이터 패킷 생성을 보여 주는 다이어그램

ASF 데이터 패킷 만들기

Multiplexer 개체 만들기에 설명된 대로 멀티플렉서 만들기 및 초기화한 후 IMFASFMultiplexer::P rocessSample을 호출하여 입력 데이터를 멀티플렉서에 전달하여 데이터 패킷으로 처리합니다. 지정된 입력은 스트림에 대한 데이터를 포함하는 하나 이상의 미디어 버퍼(IMFMediaBuffer 인터페이스)를 가질 수 있는 미디어 샘플(IMFSample 인터페이스)에 있어야 합니다. ASF-ASF 변환의 경우 패킷화된 스트림 샘플을 만드는 분할자에서 입력 미디어 샘플을 생성할 수 있습니다. 자세한 내용은 ASF Splitter를 참조하세요.

ProcessSample을 호출하기 전에 입력 미디어 샘플의 타임스탬프를 올바른 프레젠테이션 시간인지 확인합니다. 그렇지 않으면 ProcessSample이 실패하고 MF_E_NO_SAMPLE_TIMESTAMP 코드를 반환합니다.

멀티플렉서는 ProcessSample을 통해 입력을 압축되거나 압축되지 않은 미디어 샘플로 허용할 수 있습니다. 멀티플렉서는 스트림의 대역폭 사용량에 따라 이러한 샘플에 전송 시간을 할당합니다. 이 프로세스 중에 멀티플렉서는 새는 버킷 매개 변수(비트 속도 및 버퍼 창 사용률)를 확인하고 해당 값을 준수하지 않는 샘플을 거부할 수 있습니다. 입력 미디어 샘플은 다음 이유 중 하나로 대역폭 검사 실패할 수 있습니다.

  • 마지막으로 할당된 전송 시간이 이 미디어 샘플의 타임스탬프를 초과하여 입력 미디어 샘플이 늦게 도착한 경우 ProcessSample 이 실패하고 MF_E_LATE_SAMPLE 오류 코드를 반환합니다.
  • 입력 미디어 샘플의 타임스탬프를 할당된 전송 시간보다 이전인 경우(버퍼 오버플로를 나타냅니다). 멀티플렉서가 멀티플렉서 초기화 중에 MFASF_MULTIPLEXER_AUTOADJUST_BITRATE 플래그를 설정하여 비트 속도를 조정하도록 구성된 경우 이 상황을 무시할 수 있습니다. 자세한 내용은 Multiplexer 개체 만들기의 "멀티플 렉서 초기화 및 새는 버킷 설정"을 참조하세요. 이 플래그가 설정되지 않고 멀티플렉서에서 대역폭 오버런이 발생하면 ProcessSample 이 실패하고 MF_E_BANDWIDTH_OVERRUN 오류 코드가 반환됩니다.

멀티플렉서가 송신 시간을 할당하면 입력 미디어 샘플이 송신 창에 추가됩니다. 이 샘플은 송신 시간을 기준으로 정렬되고 데이터 패킷으로 처리할 준비가 된 입력 미디어 샘플 목록입니다. 데이터 패킷 생성 중에 입력 미디어 샘플이 구문 분석되고 관련 데이터가 데이터 패킷에 페이로드로 기록됩니다. 전체 데이터 패킷에는 하나 이상의 입력 미디어 샘플의 데이터가 포함될 수 있습니다.

새 입력 미디어 샘플이 송신 창에 도착하면 하나의 전체 패킷을 형성하기에 충분한 미디어 샘플이 있을 때까지 큐에 추가됩니다. 입력 미디어 샘플에 포함된 미디어 버퍼의 데이터는 생성된 데이터 패킷에 복사되지 않습니다. 데이터 패킷은 입력 미디어 샘플이 완전히 패킷화되고 전체 패킷이 멀티플렉서에서 수집될 때까지 입력 미디어 버퍼에 대한 참조를 보유합니다.

전체 데이터 패킷을 사용할 수 있는 경우 IMFASFMultiplexer::GetNextPacket을 호출하여 검색할 수 있습니다. 검색할 준비가 된 전체 패킷이 있는 동안 ProcessSample 을 호출하면 실패하고 MF_E_NOTACCEPTING 오류 코드가 반환됩니다. 이는 멀티플렉서가 더 많은 입력을 수락할 수 없으며 GetNextPacket을 호출하여 대기 중인 패킷을 검색해야 했음을 나타냅니다. 전체 데이터 패킷을 얻으려면 모든 ProcessSample 호출 뒤에 하나 이상의 GetNextPacket 호출이 있어야 합니다. 전체 데이터 패킷을 만드는 데 둘 이상의 입력 미디어 샘플이 필요할 수 있습니다. 반대로 한 입력 미디어 샘플의 데이터는 여러 패킷에 걸쳐 있을 수 있습니다. 따라서 ProcessSample 에 대한 모든 호출이 출력 미디어 샘플을 생성하는 것은 아닙니다.

입력 미디어 샘플에 MFSampleExtension_CleanPoint 특성으로 표시된 키 프레임이 포함된 경우 멀티플렉서는 특성을 패킷에 복사합니다.

ASF 데이터 패킷 가져오기

멀티플렉서에서 생성된 전체 데이터 패킷에 대한 출력 미디어 샘플을 수집하려면 패킷에 대한 출력 미디어 샘플이 더 이상 남아 있지 않을 때까지 루프에서 IMFASFMultiplexer::GetNextPacket 을 호출합니다. 다음은 성공 사례를 나열합니다.

  • 사용할 수 있는 전체 데이터 패킷이 있는 경우 GetNextPacketpdwStatusFlags 매개 변수에서 ASF_STATUS_FLAGS_INCOMPLETE 플래그를 받습니다. ppIPacket 매개 변수는 첫 번째 데이터 패킷에 대한 포인터를 받습니다. 이 플래그를 수신하는 한 이 메서드를 호출해야 합니다. 반복할 때마다 ppIPacket 은 큐의 다음 패킷을 가리킵니다.
  • 데이터 패킷이 하나만 있는 경우 ppIPacket은 패킷을 가리키고 pdwStatusFlags에서 ASF_STATUS_FLAGS_INCOMPLETE 플래그를 수신하지 않습니다.
  • 멀티플렉서가 여전히 데이터 패킷을 패킷화하고 추가하는 과정에 있는 경우 GetNextPacket은 데이터 패킷을 생성하지 않고도 성공할 수 있습니다. 이 경우 ppIPacketNULL을 가리킵니다. 계속하려면 ProcessSample을 호출하여 멀티플렉서에 더 많은 입력 미디어 샘플을 제공해야 합니다.

다음 예제 코드는 멀티플렉서로 데이터 패킷을 생성하는 함수를 보여 줍니다. 생성된 데이터 패킷 콘텐츠는 호출자가 할당한 데이터 바이트 스트림에 기록됩니다.

//-------------------------------------------------------------------
// GenerateASFDataPackets
// 
// Gets data packets from the mux. This function is called after 
// calling IMFASFMultiplexer::ProcessSample. 
//-------------------------------------------------------------------

HRESULT GenerateASFDataPackets( 
    IMFASFMultiplexer *pMux, 
    IMFByteStream *pDataStream
    )
{
    HRESULT hr = S_OK;

    IMFSample *pOutputSample = NULL;
    IMFMediaBuffer *pDataPacketBuffer = NULL;

    DWORD dwMuxStatus = ASF_STATUSFLAGS_INCOMPLETE;

    while (dwMuxStatus & ASF_STATUSFLAGS_INCOMPLETE)
    {
        hr = pMux->GetNextPacket(&dwMuxStatus, &pOutputSample);

        if (FAILED(hr))
        {
            break;
        }

        if (pOutputSample)
        {
            //Convert to contiguous buffer
            hr = pOutputSample->ConvertToContiguousBuffer(&pDataPacketBuffer);
            
            if (FAILED(hr))
            {
                break;
            }

            //Write buffer to byte stream
            hr = WriteBufferToByteStream(pDataStream, pDataPacketBuffer, NULL);

            if (FAILED(hr))
            {
                break;
            }
        }

        SafeRelease(&pDataPacketBuffer);
        SafeRelease(&pOutputSample);
    }

    SafeRelease(&pOutputSample);
    SafeRelease(&pDataPacketBuffer);
    return hr;
}

함수는 WriteBufferToByteStreamIMFByteStream::Write 항목에 표시됩니다.

이 코드 예제를 사용하는 전체 애플리케이션을 보려면 자습서: 한 파일에서 다른 파일로 ASF 스트림 복사를 참조하세요.

Packet-Generation 통화 후

멀티플렉서에서 대기 중인 전체 데이터 패킷이 없는지 확인하려면 IMFASFMultiplexer::Flush를 호출합니다. 이렇게 하면 멀티플렉서가 진행 중인 모든 미디어 샘플을 패킷화합니다. 애플리케이션은 검색할 패킷이 더 이상 없을 때까지 루프에서 GetNextPacket 을 통해 미디어 샘플 형식으로 이러한 패킷을 수집할 수 있습니다.

모든 미디어 샘플이 생성되면 IMFASFMultiplexer::End 를 호출하여 이러한 데이터 패킷과 연결된 ASF 헤더 개체를 업데이트합니다. Header 개체는 멀티플렉서 초기화에 사용된 ContentInfo 개체를 전달하여 지정됩니다. 이 호출은 데이터 패킷 생성 중에 멀티플렉서의 변경 내용을 반영하도록 다양한 헤더 개체를 업데이트합니다. 이 정보에는 패킷 수, 전송 기간, 재생 기간 및 모든 스트림의 스트림 번호가 포함됩니다. 전체 헤더 크기도 업데이트됩니다.

모든 데이터 패킷을 검색한 후 End 가 호출되었는지 확인해야 합니다. 멀티플렉서에서 대기 중인 패킷이 있는 경우 End 가 실패하고 MF_E_FLUSH_NEEDED 오류 코드가 반환됩니다. 이 경우 루프에서 FlushGetNextPacket을 호출하여 대기 패킷을 가져옵니다.

참고

VBR 인코딩의 경우 End를 호출한 후 ContentInfo 개체의 인코딩 속성에서 인코딩 통계를 설정해야 합니다. 이 프로세스에 대한 자세한 내용은 ContentInfo 개체의 속성 설정에서 "인코더 설정을 사용하여 ContentInfo 개체 구성"을 참조하세요. 다음 목록에는 설정할 특정 속성이 나와 있습니다.

 

ASF 멀티플렉서

자습서: 한 파일에서 다른 파일로 ASF 스트림 복사

자습서: CBR 인코딩을 사용하여 WMA 파일 작성