Bagikan melalui


Menggunakan Pengindeks untuk Menulis Indeks Baru

Topik ini menunjukkan cara menulis indeks untuk file Advanced Systems Format (ASF).

Berikut adalah prosedur umum untuk membuat indeks ASF:

  1. Menginisialisasi instans baru objek pengindeks ASF, seperti yang dijelaskan dalam Pembuatan dan Konfigurasi Pengindeks.
  2. Secara opsional, konfigurasikan pengindeks.
  3. Kirim paket data ASF ke pengindeks.
  4. Terapkan indeks.
  5. Dapatkan indeks yang telah selesai dari pengindeks, dan tulis ke aliran.

Mengonfigurasi Pengindeks

Untuk menggunakan pengindeks untuk menulis objek indeks baru, objek pengindeks harus memiliki bendera MFASF_INDEXER_WRITE_NEW_INDEX diatur dengan panggilan ke IMFASFIndexer::SetFlags sebelum diinisialisasi dengan IMFASFIndexer::Initialize.

Saat pengindeks dikonfigurasi untuk menulis indeks, penelepon memilih aliran yang akan diindeks. Secara default, pengindeks mencoba membuat Objek Indeks untuk semua aliran. Interval waktu default adalah satu detik.

IMFASFIndexer::SetIndexStatus dapat digunakan untuk mengambil alih pilihan default aliran dan jenis indeks objek pengindeks.

Contoh kode berikut menunjukkan inisialisasi ASF_INDEX_DESCRIPTOR dan ASF_INDEX_IDENTIFIER sebelum panggilan ke SetIndexStatus.

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);

Pengidentifikasi indeks harus memiliki jenis indeks GUID-nya yang diatur ke GUID_NULL untuk menunjukkan bahwa jenis indeks akan berbasis waktu presentasi. Pengidentifikasi indeks juga harus diinisialisasi dengan nomor aliran ASF yang akan diindeks. Setelah pengidentifikasi indeks diatur, gunakan untuk menginisialisasi pendeskripsi indeks.

Struktur deskriptor indeks memiliki anggota yang harus diatur sebelum panggilan ke SetIndexStatus. Pengidentifikasi adalah struktur ASF_INDEX_IDENTIFIER yang mengidentifikasi nomor aliran dan jenis indeks. cPerEntryBytes adalah jumlah byte yang digunakan untuk setiap entri indeks. Jika nilainya MFASFINDEXER_PER_ENTRY_BYTES_DYNAMIC, entri indeks memiliki ukuran variabel. dwInterval adalah interval pengindeksan. Nilai MFASFINDEXER_NO_FIXED_INTERVAL menunjukkan bahwa tidak ada interval pengindeksan tetap.

Mengirim Paket Data ASF ke Pengindeks

Karena pengindeks adalah objek tingkat WMContainer, pengindeks harus digunakan bersama dengan multiplexer selama pembuatan paket.

Paket yang dikembalikan dari GetNextPacket dapat dikirim ke objek pengindeks melalui panggilan ke GenerateIndexEntries tempat paket membuat entri indeks untuk setiap paket yang dikirim.

Kode berikut menunjukkan bagaimana hal ini dapat dilakukan:

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;
}

Untuk informasi selengkapnya, lihat Membuat Paket Data ASF Baru.

Menerapkan Indeks

Setelah paket terakhir memiliki entri indeks yang dibuat untuknya, indeks harus dilakukan. Ini dilakukan dengan panggilan ke IMFASFIndexer::CommitIndex. CommitIndex mengambil pointer ke objek ContentInfo yang menjelaskan konten file ASF. Menerapkan indeks menyelesaikan pengindeksan dan memperbarui header dengan informasi baru tentang ukuran file dan kemampuan pencarian.

Mendapatkan Indeks Yang Telah Selesai

Untuk mendapatkan indeks yang telah selesai dari pengindeks, lakukan langkah-langkah berikut:

  1. Panggil IMFASFIndexer::GetIndexWriteSpace untuk mendapatkan ukuran indeks.
  2. Panggil MFCreateMemoryBuffer untuk membuat buffer media. Anda dapat mengalokasikan buffer yang cukup besar untuk menahan seluruh indeks, mengalokasikan buffer yang lebih kecil dan mendapatkan indeks dalam gugus.
  3. Panggil IMFASFIndexer::GetCompletedIndex untuk mendapatkan data indeks. Pada panggilan pertama, atur parameter cbOffsetWithinIndex ke nol. Jika Anda mendapatkan indeks dalam gugus, kenaikan cbOffsetWithinIndex setiap kali dengan ukuran data dari panggilan sebelumnya.
  4. Panggil IMFMediaBuffer::Lock untuk mendapatkan penunjuk ke data indeks dan ukuran data.
  5. Tulis data indeks ke file ASF.
  6. Panggil IMFMediaBuffer::Buka kunci untuk membuka kunci buffer media.
  7. Ulangi langkah 3–6 hingga Anda menulis seluruh indeks.

Kode berikut menunjukkan langkah-langkah ini:

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;
};

Pengindeks ASF