Uso dell'indicizzatore per la ricerca all'interno di un file ASF
L'indicizzatore ASF è un componente livello WMContainer usato per leggere o scrivere oggetti index in un file ASF (Advanced Systems Format). In questo argomento vengono fornite informazioni sull'uso dell'indicizzatore ASF per eseguire la ricerca all'interno di un file ASF.
- Inizializzazione dell'indicizzatore per la ricerca
- Recupero della posizione di ricerca.
- Argomenti correlati
Per informazioni sulla struttura di un file ASF, vedere Struttura di file ASF.
Inizializzazione dell'indicizzatore per la ricerca
Per inizializzare l'indicizzatore ASF per la ricerca:
- Chiamare MFCreateASFIndexer per creare una nuova istanza dell'indicizzatore ASF.
- Chiamare IMFASFIndexer::Initialize per inizializzare l'indicizzatore. Questo metodo ottiene informazioni dall'intestazione ASF per determinare quali flussi ASF vengono indicizzati. Per impostazione predefinita, l'oggetto indicizzatore è configurato per la ricerca.
- Chiamare IMFASFIndexer::GetIndexPosition per trovare l'offset dell'indice all'interno del file ASF.
- Chiamare la funzione MFCreateASFIndexerByteStream per creare un flusso di byte per la lettura dell'indice. L'input di questa funzione è un puntatore a un flusso di byte che contiene il file ASF e l'offset dell'indice (dal passaggio precedente).
- Chiamare IMFASFIndexer::SetIndexByteStreams per impostare il flusso dei byte di indice sull'indicizzatore.
Il codice seguente illustra questi passaggi:
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;
}
Recupero della posizione di ricerca.
- Per verificare se un determinato flusso è indicizzato, chiamare IMFASFIndexer::GetIndexStatus. Se il flusso viene indicizzato, il parametro pfIsIndexed riceve il valore TRUE; in caso contrario riceve il valore FALSE.
- Per impostazione predefinita, l'indicizzatore usa la ricerca in avanti. Per la ricerca inversa ,ovvero la ricerca dalla fine del file, chiamare IMFASFIndexer::SetFlags e impostare il flag di MFASF_INDEXER_READ_FOR_REVERSEPLAYBACK . In caso contrario, ignorare questo passaggio.
- Se il flusso è indicizzato, ottenere la posizione di ricerca per un'ora di presentazione specificata chiamando IMFASFIndexer::GetSeekPositionForValue. Questo metodo legge l'indice ASF e trova la voce di indice più vicina all'ora richiesta. Il metodo restituisce l'offset di byte del pacchetto di dati specificato dalla voce di indice. L'offset dei byte è relativo all'inizio dell'oggetto dati ASF.
Il metodo GetSeekPositionForValue accetta un puntatore alla struttura ASF_INDEX_IDENTIFIER . Questa struttura specifica un tipo di indice e un identificatore di flusso. Attualmente, il tipo di indice deve essere GUID_NULL, che specifica l'indicizzazione basata sul tempo.
Il codice seguente ottiene una posizione di ricerca, in base a un identificatore di flusso e all'ora di presentazione di destinazione. Se la chiamata ha esito positivo, restituisce l'offset dei dati nel parametro pcbDataOffset e il tempo di ricerca effettivo approssimativo in 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;
}
Argomenti correlati