다음을 통해 공유


인덱서로 ASF 파일 내에서 검색

ASF 인덱서 ASF(Advanced Systems Format) 파일에서 인덱스 개체를 읽거나 쓰는 데 사용되는 WMContainer 계층 구성 요소입니다. 이 항목에서는 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 합니다.

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