인덱서를 사용하여 새 인덱스 작성
이 항목에서는 ASF(Advanced Systems Format) 파일에 대한 인덱스 작성 방법을 보여 줍니다.
ASF 인덱스 만들기에 대한 일반적인 절차는 다음과 같습니다.
- 인덱서 만들기 및 구성설명된 대로 ASF 인덱서 개체의 새 인스턴스를 초기화합니다.
- 필요에 따라 인덱서 구성
- ASF 데이터 패킷을 인덱서로 보냅니다.
- 인덱스를 커밋하세요.
- 인덱서에서 완료된 인덱서를 가져와서 스트림에 씁니다.
인덱서 구성
인덱서를 사용하여 새 인덱스 개체를 작성하려면 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 개체에 대한 포인터를 사용합니다. 인덱스를 커밋하면 인덱싱이 완료되고 파일 크기 및 검색 가능성에 대한 새로운 정보로 헤더가 업데이트됩니다.
완료된 인덱스 가져오기
인덱서에서 완료된 인덱스 가져오기를 수행하려면 다음 단계를 수행합니다.
- IMFASFIndexer::GetIndexWriteSpace 호출하여 인덱스의 크기를 가져옵니다.
- MFCreateMemoryBuffer 호출하여 미디어 버퍼를 만듭니다. 전체 인덱스를 보유할 수 있을 만큼 큰 버퍼를 할당하고, 더 작은 버퍼를 할당하고, 인덱스를 청크로 가져올 수 있습니다.
- IMFASFIndexer::GetCompletedIndex 호출하여 인덱스 데이터를 가져옵니다. 첫 번째 호출에서 cbOffsetWithinIndex 매개 변수를 0으로 설정합니다. 청크 단위로 인덱스를 가져오는 경우, 이전 호출의 데이터 크기만큼 매번 cbOffsetWithinIndex을 증가시킵니다.
- IMFMediaBuffer::Lock 호출하여 인덱스 데이터 및 데이터 크기에 대한 포인터를 가져옵니다.
- ASF 파일에 인덱스 데이터를 씁니다.
- IMFMediaBuffer::Unlock 호출하여 미디어 버퍼의 잠금을 해제합니다.
- 전체 인덱스가 작성될 때까지 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;
};
관련 항목