CSourceSeeking クラス

CSourceSeeking クラスの階層

CSourceSeeking クラスは、1 つの出力ピンを持つソース フィルタで、シークを実装する抽象クラスである。

このクラスは、IMediaSeeking インターフェイスをサポートする。このクラスは、すべての IMediaSeeking メソッドにデフォルトの実装を提供する。プロテクト メンバ変数は、開始タイム、終了タイム、および現在の速度を格納する。デフォルトでは、このクラスによってサポートされる唯一のタイム フォーマットは、TIME_FORMAT_MEDIA_TIME (100 ナノ秒単位) である。詳細は、注意を参照すること。

要件

ヘッダー : Ctlutil.h 内で宣言し、Streams.h をインクルードする。

ライブラリ : Strmbase.lib (リテール ビルド) または Strmbasd.lib (デバッグ ビルド) を使う。

プロテクト メンバ変数  
m_rtDuration ストリームの時間幅。
m_rtStart 開始タイム。
m_rtStop 終了タイム。
m_dRateSeeking 再生速度。
m_dwSeekingCaps シーク能力。
m_pLock ロックのためのクリティカル セクション オブジェクトへのポインタ。
プロテクト メソッド  
CSourceSeeking コンストラクタ メソッド。
純粋仮想メソッド  
ChangeRate 再生速度が変更されたときに呼び出される。
ChangeStart 開始位置が変更されたときに呼び出される。
ChangeStop 停止位置が変更されたときに呼び出される。
IMediaSeeking メソッド  
IsFormatSupported 指定したタイム フォーマットがサポートされているかどうかを調べる。
QueryPreferredFormat オブジェクトの優先タイム フォーマットを取得する。
SetTimeFormat タイム フォーマットを設定する。
IsUsingTimeFormat 指定したタイム フォーマットが現在使われているフォーマットかどうかを調べる。
GetTimeFormat 現在のタイム フォーマットを取得する。
GetDuration ストリームの時間幅を取得する。
GetStopPosition ストリームの時間幅を基準として、再生が停止するタイムを取得する。
GetCurrentPosition ストリームの合計時間幅を基準とする、現在の位置を取得する。
GetCapabilities ストリームのすべてのシーク能力を取得する。
CheckCapabilities 指定したシーク能力をストリームが持っているかどうかを照会する。
ConvertTimeFormat 1 つのタイム フォーマットから別のタイム フォーマットに変換する。
SetPositions 現在位置と停止位置を設定する。
GetPositions 現在位置と停止位置を取得する。
GetAvailable シークが有効なタイムの範囲を取得する。
SetRate 再生速度を設定する。
GetRate 再生速度を取得する。
GetPreroll プリロール タイムを取得する。

注意

CSourceSeeking オブジェクトは、開始位置、停止位置、再生速度が変更されるたびに、次のように対応する純粋仮想メソッドを呼び出す。

派生クラスは、これらのメソッドを実装しなければならない。シーク処理後、フィルタは次のことを行う必要がある。

  1. ダウンストリームの入力ピンで IPin::BeginFlush メソッドを呼び出す。
  2. データを提供するワーカー スレッドを停止する。
  3. 入力ピンで IPin::EndFlush メソッドを呼び出す。
  4. ワーカー スレッドを再起動する。
  5. 入力ピンで IPin::NewSegment メソッドを呼び出す。
  6. 最初のサンプルで非継続プロパティを設定する。IMediaSample::SetDiscontinuity メソッドを呼び出す。

ワーカー スレッドがブロックされ、サンプル出力の待機状態になっている場合は、BeginFlush を呼び出してワーカー スレッドを解放する。

ステップ 2 で、スレッドによるデータの送信が停止したことを確認する。実装によっては、スレッドが終了するのを待つか、またはスレッドが何らかの応答を示すまで待つ必要がある。フィルタで CSourceStream クラスを使っている場合、CSourceStream::Stop メソッドは、ワーカー スレッドが応答するまで待機状態となる。

理想的には、新しいセグメント (ステップ 5) がワーカー スレッドから提供されることが望ましい。これは、フィルタがサンプルを使って継続して処理する限り、CSourceSeeking オブジェクトによっても実行できる。

次の例は、可能な実装を示している。ここでは、ソース フィルタの出力ピンが CSourceSeekingCSourceStream から派生することを想定している。この例では、ステップ 1 ~ 4 を実行するヘルパー メソッド UpdateFromSeek を定義している。CSourceStream::OnThreadStartPlay メソッドはオーバーライドされ、新しいセグメントを送ると共に、非連続を示すフラグを設定する。ワーカー スレッドはこのフラグをピックアップし、IMediaSample::SetDiscontinuity を呼び出す。

void CMyStream::UpdateFromSeek()
{
    if (ThreadExists()) 
    {
        DeliverBeginFlush();
        Stop();
        DeliverEndFlush();
        Run();
    }
}

HRESULT CMyStream::OnThreadStartPlay()
{
    m_bDiscontinuity = TRUE;
    return DeliverNewSegment(m_rtStart, m_rtStop, m_dRateSeeking);
}

追加のタイム フォーマットのサポート

デフォルトでは、このクラスは、基準タイム (TIME_FORMAT_MEDIA_TIME) の単位のみのシークをサポートする。追加のタイム フォーマットをサポートするには、タイム フォーマットを扱う IMediaSeeking メソッドをオーバーライドする。

また、残りの IMediaSeeking メソッドをオーバーライドして、タイム フォーマット間で必要な変換を実行する。SetTimeFormat メソッドが呼び出された後、すべての IMediaSeeking メソッドは、出入りするタイム パラメータが新規のタイム フォーマットであるかのように扱う必要がある。たとえば、m_rtDuration 変数が基準タイムの単位の時間幅を表し、現在のタイム フォーマットがフレームである場合、GetDuration メソッドは、フレームに変換された値 m_rtDuration を返す必要がある。以下に例を示す。

STDMETHODIMP GetDuration(LONGLONG *pDuration)
{
    HRESULT hr = CSourceSeeking::GetDuration(pDuration);
    if (SUCCEEDED(hr))
    {
        if (m_TimeFormat == TIME_FORMAT_FRAME)
        {
            // 基準タイムからフレームへの変換。
            *pDuration = TimeToFrame(*pDuration);  // プライベート メソッド。
        }
    }
    return hr
} 

また、IMediaSeeking::SetPositions メソッドの AM_SEEKING_ReturnTime フラグを確認する必要がある。このフラグがある場合は、呼び出し元に返すときに位置値を基準タイムに変換する。