다음을 통해 공유


인덱서를 사용하여 ASF 파일 내에서 검색

ASF 인덱서는 ASF(Advanced Systems Format) 파일에서 인덱스 개체를 읽거나 쓰는 데 사용되는 WMContainer 계층 구성 요소입니다. 이 항목에서는 ASF 인덱서 를 사용하여 ASF 파일 내에서 검색하는 방법에 대한 정보를 제공합니다.

ASF 파일의 구조에 대한 자세한 내용은 ASF 파일 구조를 참조하세요.

검색을 위한 인덱서 초기화

검색을 위해 ASF 인덱서를 초기화하려면 다음을 수행합니다.

  1. MFCreateASFIndexer를 호출하여 ASF 인덱서의 새 instance 만듭니다.
  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 합니다.

다음 코드는 스트림 식별자와 대상 프레젠테이션 시간이 지정된 검색 위치를 가져옵니다. 호출이 성공하면 pcbDataOffset 매개 변수의 데이터 오프셋과 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 인덱서