共用方式為


使用索引子在 ASF 檔案中搜尋

ASF 索引子 是 WMContainer 層元件,可用來讀取或寫入進階系統格式的 Index 物件 (ASF) 檔案。 本主題提供使用 ASF 索引子在 ASF 檔案中搜尋的相關資訊。

如需 ASF 檔案結構的相關資訊,請參閱 ASF 檔案結構

初始化索引子以進行搜尋

若要初始化 ASF 索引子以進行搜尋:

  1. 呼叫 MFCreateASFIndexer 以建立 ASF 索引子的新實例。
  2. 呼叫 IMFASFIndexer::Initialize 以初始化索引子。 這個方法會從 ASF 標頭取得資訊,以判斷要編制哪些 ASF 資料流程的索引。 根據預設,索引子物件會設定為搜尋。
  3. 呼叫 IMFASFIndexer::GetIndexPosition 以尋找 ASF 檔案中索引的位移。
  4. 呼叫 MFCreateASFIndexerByteStream 函式來建立位元組資料流程來讀取索引。 此函式的輸入是包含 ASF 檔案的位元組資料流程指標,以及上一個步驟中索引 (位移) 。
  5. 呼叫 IMFASFIndexer::SetIndexByteStreams 以在索引子上設定索引位元組資料流程。

下列程式碼顯示這些步驟:

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

取得搜尋位置。

  1. 若要找出特定資料流程是否已編制索引,請呼叫 IMFASFIndexer::GetIndexStatus。 如果資料流程已編制索引, pfIsIndexed 參數會收到 TRUE值;否則會收到 FALSE值。
  2. 根據預設,索引子會使用正向搜尋。 如需反向搜尋 (,請從檔案結尾) 搜尋,呼叫 IMFASFIndexer::SetFlags 並設定 MFASF_INDEXER_READ_FOR_REVERSEPLAYBACK 旗標。 否則,請略過此步驟。
  3. 如果已編制資料流程的索引,請呼叫 IMFASFIndexer::GetSeekPositionForValue來取得指定簡報時間的搜尋位置。 這個方法會讀取 ASF 索引,並尋找最接近所要求時間的索引項目目。 方法會傳回索引項目目所指定之資料封包的位元組位移。 位元組位移相對於 ASF 資料物件的開頭。

GetSeekPositionForValue方法會採用ASF_INDEX_IDENTIFIER結構的指標。 這個結構會指定索引類型和資料流程識別碼。 目前,索引類型必須GUID_Null,以指定以時間為基礎的索引編制。

下列程式碼會取得搜尋位置,指定資料流程識別碼和目標呈現時間。 如果呼叫成功,它會傳回在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;
}

ASF 索引子