Usando o indexador para procurar dentro de um arquivo ASF
O indexador ASF é um componente de camada WMContainer usado para ler ou gravar objetos de índice em um arquivo ASF (Advanced Systems Format). Este tópico fornece informações sobre como usar o indexador ASF a ser buscado em um arquivo ASF.
Para obter informações sobre a estrutura de um arquivo ASF, consulte Estrutura de Arquivos ASF.
Inicializando o indexador para busca
Para inicializar o indexador ASF para buscar:
- Chame MFCreateASFIndexer para criar uma nova instância do indexador ASF.
- Chame IMFASFIndexer::Initialize para inicializar o indexador. Esse método obtém informações do cabeçalho ASF para determinar quais fluxos ASF são indexados. Por padrão, o objeto indexador é configurado para busca.
- Chame IMFASFIndexer::GetIndexPosition para localizar o deslocamento do índice dentro do arquivo ASF.
- Chame a função MFCreateASFIndexerByteStream para criar um fluxo de bytes para ler o índice. A entrada para essa função é um ponteiro para um fluxo de bytes que contém o arquivo ASF e o deslocamento do índice (da etapa anterior).
- Chame IMFASFIndexer::SetIndexByteStreams para definir o fluxo de bytes de índice no indexador.
O código a seguir mostra essas etapas:
HRESULT CreateASFIndexer(
IMFByteStream *pContentByteStream, // Pointer to the content byte stream
IMFASFContentInfo *pContentInfo,
IMFASFIndexer **ppIndexer
)
{
IMFASFIndexer *pIndexer = NULL;
IMFByteStream *pIndexerByteStream = NULL;
QWORD qwLength = 0, qwIndexOffset = 0, qwBytestreamLength = 0;
// Create the indexer.
HRESULT hr = MFCreateASFIndexer(&pIndexer);
if (FAILED(hr))
{
goto done;
}
//Initialize the indexer to work with this ASF library
hr = pIndexer->Initialize(pContentInfo);
if (FAILED(hr))
{
goto done;
}
//Check if the index exists. You can only do this after creating the indexer
//Get byte stream length
hr = pContentByteStream->GetLength(&qwLength);
if (FAILED(hr))
{
goto done;
}
//Get index offset
hr = pIndexer->GetIndexPosition(pContentInfo, &qwIndexOffset);
if (FAILED(hr))
{
goto done;
}
if ( qwIndexOffset >= qwLength)
{
//index object does not exist, release the indexer
goto done;
}
else
{
// initialize the indexer
// Create a byte stream that the Indexer will use to read in
// and parse the indexers.
hr = MFCreateASFIndexerByteStream(
pContentByteStream,
qwIndexOffset,
&pIndexerByteStream
);
if (FAILED(hr))
{
goto done;
}
}
hr = pIndexer->SetIndexByteStreams(&pIndexerByteStream, 1);
if (FAILED(hr))
{
goto done;
}
// Return the pointer to the caller.
*ppIndexer = pIndexer;
(*ppIndexer)->AddRef();
done:
SafeRelease(&pIndexer);
SafeRelease(&pIndexerByteStream);
return hr;
}
Obtendo a Posição de Busca.
- Para descobrir se um fluxo específico é indexado, chame IMFASFIndexer::GetIndexStatus. Se o fluxo for indexado, o parâmetro pfIsIndexed receberá o valor TRUE; caso contrário, ele receberá o valor FALSE.
- Por padrão, o indexador usa a busca de encaminhamento. Para a busca inversa (ou seja, buscando no final do arquivo), chame IMFASFIndexer::SetFlags e defina o sinalizador MFASF_INDEXER_READ_FOR_REVERSEPLAYBACK . Caso contrário, pule essa etapa.
- Se o fluxo for indexado, obtenha a posição de busca para um horário de apresentação especificado chamando IMFASFIndexer::GetSeekPositionForValue. Esse método lê o índice ASF e localiza a entrada de índice mais próxima do tempo solicitado. O método retorna o deslocamento de bytes do pacote de dados especificado pela entrada de índice. O deslocamento de bytes é relativo ao início do objeto de dados ASF.
O método GetSeekPositionForValue usa um ponteiro para a estrutura ASF_INDEX_IDENTIFIER . Essa estrutura especifica um tipo de índice e um identificador de fluxo. Atualmente, o tipo de índice deve ser GUID_NULL, que especifica a indexação baseada em tempo.
O código a seguir obtém uma posição de busca, considerando um identificador de fluxo e o tempo de apresentação de destino. Se a chamada for bem-sucedida, ela retornará o deslocamento de dados no parâmetro pcbDataOffset e o tempo de busca real aproximado em phnsApproxSeekTime.
HRESULT GetSeekPositionWithIndexer(
IMFASFIndexer *pIndexer,
WORD wStreamNumber,
MFTIME hnsSeekTime, // Desired seek time, in 100-nsec.
BOOL bReverse,
QWORD *pcbDataOffset, // Receives the offset in bytes.
MFTIME *phnsApproxSeekTime // Receives the approximate seek time.
)
{
// Query whether the stream is indexed.
ASF_INDEX_IDENTIFIER IndexIdentifier = { GUID_NULL, wStreamNumber };
BOOL fIsIndexed = FALSE;
ASF_INDEX_DESCRIPTOR descriptor;
DWORD cbIndexDescriptor = sizeof(descriptor);
HRESULT hr = pIndexer->GetIndexStatus(
&IndexIdentifier,
&fIsIndexed,
(BYTE*)&descriptor,
&cbIndexDescriptor
);
if (hr == MF_E_BUFFERTOOSMALL)
{
hr = S_OK;
}
else if (FAILED(hr))
{
goto done;
}
if (!fIsIndexed)
{
hr = MF_E_ASF_NOINDEX;
goto done;
}
if (bReverse)
{
hr = pIndexer->SetFlags(MFASF_INDEXER_READ_FOR_REVERSEPLAYBACK);
if (FAILED(hr))
{
goto done;
}
}
// Get the offset from the indexer.
PROPVARIANT var;
var.vt = VT_I8;
var.hVal.QuadPart = hnsSeekTime;
hr = pIndexer->GetSeekPositionForValue(
&var,
&IndexIdentifier,
pcbDataOffset,
phnsApproxSeekTime,
0
);
done:
return hr;
}
Tópicos relacionados