Uso del indexador para buscar en un archivo ASF
El indexador ASF es un componente de capa WMContainer que se usa para leer o escribir objetos de índice en un archivo de formato de sistemas avanzados (ASF). En este tema se proporciona información sobre el uso del indexador ASF para buscar en un archivo ASF.
Para obtener información sobre la estructura de un archivo ASF, vea ASF File Structure.
Inicialización del indexador para buscar
Para inicializar el indexador ASF para buscar:
- Llame a MFCreateASFIndexer para crear una nueva instancia del indexador ASF.
- Llame a IMFASFIndexer::Initialize para inicializar el indexador. Este método obtiene información del encabezado ASF para determinar qué secuencias asf se indexan. De forma predeterminada, el objeto indexador está configurado para buscar.
- Llame a IMFASFIndexer::GetIndexPosition para buscar el desplazamiento del índice dentro del archivo ASF.
- Llame a la función MFCreateASFIndexerByteStream para crear una secuencia de bytes para leer el índice. La entrada de esta función es un puntero a una secuencia de bytes que contiene el archivo ASF y el desplazamiento del índice (del paso anterior).
- Llame a IMFASFIndexer::SetIndexByteStreams para establecer la secuencia de bytes de índice en el indexador.
El siguiente código muestra estos pasos:
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;
}
Obtener la posición de búsqueda.
- Para averiguar si se indexa una secuencia determinada, llame a IMFASFIndexer::GetIndexStatus. Si la secuencia está indizada, el parámetro pfIsIndexed recibe el valor TRUE; de lo contrario, recibe el valor FALSE.
- De forma predeterminada, el indexador usa la búsqueda hacia delante. Para la búsqueda inversa (es decir, buscar desde el final del archivo), llame a IMFASFIndexer::SetFlags y establezca la marca MFASF_INDEXER_READ_FOR_REVERSEPLAYBACK . De lo contrario, omita este paso.
- Si la secuencia se indexa, obtenga la posición de búsqueda de un tiempo de presentación especificado llamando a IMFASFIndexer::GetSeekPositionForValue. Este método lee el índice ASF y busca la entrada de índice más cercana a la hora solicitada. El método devuelve el desplazamiento de bytes del paquete de datos especificado por la entrada de índice. El desplazamiento de bytes es relativo al inicio del objeto de datos asf.
El método GetSeekPositionForValue toma un puntero a la estructura ASF_INDEX_IDENTIFIER . Esta estructura especifica un tipo de índice y un identificador de secuencia. Actualmente, el tipo de índice debe ser GUID_NULL, que especifica la indexación basada en el tiempo.
El código siguiente obtiene una posición de búsqueda, dado un identificador de secuencia y el tiempo de presentación de destino. Si la llamada se realiza correctamente, devuelve el desplazamiento de datos en el parámetro pcbDataOffset y el tiempo de búsqueda real aproximado en 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;
}
Temas relacionados