다음을 통해 공유


인덱서를 사용하여 새 인덱스 작성

이 항목에서는 ASF(Advanced Systems Format) 파일에 대한 인덱스 작성 방법을 보여 줍니다.

ASF 인덱스 만들기에 대한 일반적인 절차는 다음과 같습니다.

  1. 인덱서 만들기 및 구성설명된 대로 ASF 인덱서 개체의 새 인스턴스를 초기화합니다.
  2. 필요에 따라 인덱서 구성
  3. ASF 데이터 패킷을 인덱서로 보냅니다.
  4. 인덱스를 커밋하세요.
  5. 인덱서에서 완료된 인덱서를 가져와서 스트림에 씁니다.

인덱서 구성

인덱서를 사용하여 새 인덱스 개체를 작성하려면 IMFASFIndexer::Initialize사용하여 초기화하기 전에 인덱서 개체에 IMFASFIndexer::SetFlags 호출과 함께 플래그 MFASF_INDEXER_WRITE_NEW_INDEX 설정해야 합니다.

인덱서를 작성하도록 구성된 경우 호출자는 인덱싱할 스트림을 선택합니다. 기본적으로 인덱서는 모든 스트림에 대한 Index 개체를 만들려고 시도합니다. 기본 시간 간격은 1초입니다.

IMFASFIndexer::SetIndexStatus 사용하여 인덱서 개체의 기본 스트림 및 인덱스 형식 선택을 재정의할 수 있습니다.

다음 예제 코드는 SetIndexStatus호출하기 전에 ASF_INDEX_DESCRIPTOR 및 ASF_INDEX_IDENTIFIER 초기화하는 방법을 보여 있습니다.

ASF_INDEX_DESCRIPTOR IndexerType;
ZeroMemory(&IndexerType, sizeof(ASF_INDEX_DESCRIPTOR));

ASF_INDEX_IDENTIFIER IndexIdentifier;
ZeroMemory(&IndexIdentifier, sizeof(ASF_INDEX_IDENTIFIER));

IndexIdentifier.guidIndexType = GUID_NULL;
IndexIdentifier.wStreamNumber = 1;

IndexerType.Identifier = IndexIdentifier;
IndexerType.cPerEntryBytes  = MFASFINDEXER_PER_ENTRY_BYTES_DYNAMIC;
IndexerType.dwInterval  = MFASFINDEXER_NO_FIXED_INTERVAL;

hr = pIndexer->SetIndexStatus((BYTE*)&IndexerType, sizeof(ASF_INDEX_DESCRIPTOR), TRUE);

인덱스 식별자는 인덱스 형식이 프레젠테이션 시간 기반이 되도록 나타내기 위해 GUID 인덱스 형식을 GUID_NULL 설정해야 합니다. 또한 인덱싱할 ASF 스트림의 스트림 번호로 인덱스 식별자를 초기화해야 합니다. 인덱스 식별자를 설정한 후 인덱스 설명자를 초기화하는 데 사용합니다.

인덱스 설명자 구조체에는 SetIndexStatus호출하기 전에 설정해야 하는 멤버가 있습니다. 식별자 스트림 번호와 인덱스의 형식을 식별하는 ASF_INDEX_IDENTIFIER 구조체입니다. cPerEntryBytes 각 인덱스 항목에 사용되는 바이트 수입니다. 값이 MFASFINDEXER_PER_ENTRY_BYTES_DYNAMIC인 경우, 인덱스 항목은 가변 크기를 가집니다. dwInterval 인덱싱 간격입니다. MFASFINDEXER_NO_FIXED_INTERVAL 값은 고정 인덱싱 간격이 없음을 나타냅니다.

인덱서에 ASF 데이터 패킷 보내기

인덱서는 WMContainer 수준 개체이므로 패킷 생성 중에 멀티플렉서와 함께 사용해야 합니다.

GetNextPacket 반환된 패킷은 송신된 각 패킷에 대한 인덱스 항목을 만드는GenerateIndexEntries 호출을 통해 인덱서 개체로 보낼 수 있습니다.

다음 코드는 이 작업을 수행하는 방법을 보여 줍니다.

HRESULT SendSampleToMux(
    IMFASFMultiplexer *pMux,
    IMFASFIndexer *pIndex,
    IMFSample *pSample,
    WORD wStream,
    IMFByteStream *pDestStream
    )
{
    IMFSample *pOutputSample = NULL;
    IMFMediaBuffer *pDataPacket = NULL;

    DWORD dwMuxStatus = ASF_STATUSFLAGS_INCOMPLETE;

    HRESULT hr = pMux->ProcessSample(wStream, pSample, 0);
    if (FAILED(hr))
    {
        goto done;
    }

    while (dwMuxStatus & ASF_STATUSFLAGS_INCOMPLETE)
    {
        hr = pMux->GetNextPacket(&dwMuxStatus, &pOutputSample);
        if (FAILED(hr))
        {
            goto done;
        }

        if (pOutputSample)
        {
            // Send the data packet to the indexer
            hr = pIndex->GenerateIndexEntries(pOutputSample);
            if (FAILED(hr))
            {
                goto done;
            }

            // Convert the sample to a contiguous buffer.
            hr = pOutputSample->ConvertToContiguousBuffer(&pDataPacket);
            if (FAILED(hr))
            {
                goto done;
            }

            // Write the buffer to the byte stream.
            hr = WriteBufferToByteStream(pDestStream, pDataPacket, NULL);
            if (FAILED(hr))
            {
                goto done;
            }
        }

        SafeRelease(&pOutputSample);
        SafeRelease(&pDataPacket);
    }

done:
    SafeRelease(&pOutputSample);
    SafeRelease(&pDataPacket);
    return hr;
}

자세한 내용은 새 ASF 데이터 패킷 생성참조하세요.

인덱스 커밋

마지막 패킷에 인덱스 항목이 생성된 후에는 인덱스가 커밋되어야 합니다. 이 작업은 IMFASFIndexer::CommitIndex호출하여 수행됩니다. CommitIndex ASF 파일의 내용을 설명하는 ContentInfo 개체에 대한 포인터를 사용합니다. 인덱스를 커밋하면 인덱싱이 완료되고 파일 크기 및 검색 가능성에 대한 새로운 정보로 헤더가 업데이트됩니다.

완료된 인덱스 가져오기

인덱서에서 완료된 인덱스 가져오기를 수행하려면 다음 단계를 수행합니다.

  1. IMFASFIndexer::GetIndexWriteSpace 호출하여 인덱스의 크기를 가져옵니다.
  2. MFCreateMemoryBuffer 호출하여 미디어 버퍼를 만듭니다. 전체 인덱스를 보유할 수 있을 만큼 큰 버퍼를 할당하고, 더 작은 버퍼를 할당하고, 인덱스를 청크로 가져올 수 있습니다.
  3. IMFASFIndexer::GetCompletedIndex 호출하여 인덱스 데이터를 가져옵니다. 첫 번째 호출에서 cbOffsetWithinIndex 매개 변수를 0으로 설정합니다. 청크 단위로 인덱스를 가져오는 경우, 이전 호출의 데이터 크기만큼 매번 cbOffsetWithinIndex을 증가시킵니다.
  4. IMFMediaBuffer::Lock 호출하여 인덱스 데이터 및 데이터 크기에 대한 포인터를 가져옵니다.
  5. ASF 파일에 인덱스 데이터를 씁니다.
  6. IMFMediaBuffer::Unlock 호출하여 미디어 버퍼의 잠금을 해제합니다.
  7. 전체 인덱스가 작성될 때까지 3~6단계를 반복합니다.

다음 코드는 다음 단계를 보여줍니다.

HRESULT WriteASFIndex(IMFASFIndexer *pIndex,IMFByteStream *pStream)
{
    const DWORD cbChunkSize = 4096;

    IMFMediaBuffer *pBuffer = NULL;

    QWORD cbIndex = 0;
    DWORD cbIndexWritten = 0;

    HRESULT hr = pIndex->GetIndexWriteSpace(&cbIndex);
    if (FAILED(hr))
    {
        goto done;
    }

    hr = MFCreateMemoryBuffer(cbChunkSize, &pBuffer);
    if (FAILED(hr))
    {
        goto done;
    }

    while (cbIndexWritten < cbIndex)
    {
        BYTE *pData = NULL;
        DWORD cbData = 0;
        DWORD cbWritten = 0;

        hr = pIndex->GetCompletedIndex(pBuffer, cbIndexWritten);
        if (FAILED(hr))
        {
            goto done;
        }

        hr = pBuffer->Lock(&pData, NULL, &cbData);
        if (FAILED(hr))
        {
            goto done;
        }

        hr = pStream->Write(pData, cbData, &cbWritten);

        (void)pBuffer->Unlock();

        if (FAILED(hr))
        {
            goto done;
        }

        cbIndexWritten += cbData;
    }

done:
    SafeRelease(&pBuffer);
    return hr;
};

ASF 인덱서