Menggunakan Pengindeks untuk Mencari Dalam File ASF
pengindeks ASF adalah komponen lapisan WMContainer yang digunakan untuk membaca atau menulis Objek Indeks dalam file Advanced Systems Format (ASF). Topik ini menyediakan informasi tentang menggunakan pengindeks ASF untuk dicari dalam file ASF.
Untuk informasi tentang struktur file ASF, lihat Struktur File ASF.
Menginisialisasi Pengindeks untuk Mencari
Untuk menginisialisasi pengindeks ASF untuk pencarian:
- Panggil MFCreateASFIndexer untuk membuat instans baru pengindeks ASF.
- Panggil IMFASFIndexer::Inisialisasi untuk menginisialisasi pengindeks. Metode ini mendapatkan informasi dari header ASF untuk menentukan aliran ASF mana yang diindeks. Secara default, objek pengindeks dikonfigurasi untuk pencarian.
- Panggil IMFASFIndexer::GetIndexPosition untuk menemukan offset indeks dalam file ASF.
- Panggil fungsiMFCreateASFIndexerByteStream untuk membuat aliran byte untuk membaca indeks. Input ke fungsi ini adalah penunjuk ke aliran byte yang berisi file ASF, dan offset indeks (dari langkah sebelumnya).
- Panggil IMFASFIndexer::SetIndexByteStreams untuk mengatur aliran byte indeks pada pengindeks.
Kode berikut menunjukkan langkah-langkah berikut:
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;
}
Mendapatkan Posisi Pencarian.
- Untuk mengetahui apakah aliran tertentu diindeks, panggil IMFASFIndexer::GetIndexStatus. Jika aliran diindeks, parameter pfIsIndexed menerima nilai TRUE; jika tidak, ia menerima nilai FALSE.
- Secara default, pengindeks menggunakan pencarian maju. Untuk pencarian terbalik (yaitu, mencari dari akhir file), panggil IMFASFIndexer::SetFlags dan atur bendera MFASF_INDEXER_READ_FOR_REVERSEPLAYBACK. Jika tidak, lewati langkah ini.
- Jika aliran diindeks, dapatkan posisi pencarian untuk waktu presentasi tertentu dengan memanggil IMFASFIndexer::GetSeekPositionForValue. Metode ini membaca indeks ASF dan menemukan entri indeks yang paling dekat dengan waktu yang diminta. Metode ini mengembalikan offset byte dari paket data yang ditentukan oleh entri indeks. Offset byte relatif terhadap awal Objek Data ASF.
Metode GetSeekPositionForValue membawa penunjuk ke struktur ASF_INDEX_IDENTIFIER. Struktur ini menentukan jenis indeks dan pengidentifikasi aliran. Saat ini, jenis indeks harus GUID_NULL, yang menentukan pengindeksan berbasis waktu.
Kode berikut mendapatkan posisi pencarian, diberikan ID aliran dan waktu presentasi tujuan. Jika panggilan berhasil, akan mengembalikan offset data dalam parameter pcbDataOffset dan waktu pencarian aktual perkiraan dalam 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;
}
Topik terkait