自作ソースフィルタの映像と音声の同期について

解決


ごんぞー  2012-02-22 13:58:47  No: 73199  IP: 192.*.*.*

どうも、ごんぞーと申します。

現在、DirectShowを使用した自作のソースフィルタの作成を行っているのですが、
音声出力と映像出力の同期にて問題が発生しています。

映像はスムーズに出力されるのですが、音声がとぎれとぎれになってしまっています。

映像と音声の同期方法のサンプルプログラムを探したのですが、
どこにも見当たらないため、こちらにて質問させていただきました。

一般的に映像と音声を同期させるためには、どのようなことを行えばいいのでしょうか?

ご教授いただければと思います。

なお、ソースフィルタは、DirectXSDK(WindowsSDK)の「synth」と「PushSource」を参考に作成しており、
映像用と音声用二つの出力ピンを準備し、デコードDLLから映像・音声を1フレームづつ取得し、レンダラに出力しています。

レンダラは映像が「VMR9」、音声が「Default DirectSound Device」と接続しております。

よろしくお願いいたします。

編集 削除
gak  2012-02-22 18:13:53  No: 73200  IP: 192.*.*.*

> 一般的に映像と音声を同期させるためには、どのようなことを行えばいいのでしょうか?
基本的に、ソースフィルタは求められるがままにソースデータを提供する事に専念し、映像/音声の同期はレンダラに任せて良かったと思う。

> 映像はスムーズに出力されるのですが、音声がとぎれとぎれになってしまっています。
> デコードDLLから映像・音声を1フレームづつ取得し
レンダラが要求する速度でサンプルデータを提供できていない可能性は無いだろうか?
簡単希望的に考えて、CSourceStream::DecideBufferSize() でバッファのサイズや数を今より多く要求して、
CSourceStream::FillBuffer() でデータをどんどん渡してダウンストリームでキャッシュできればスムーズに流れたりはしないだろうか?

とりあえずプッシュ型ソースを実装する際の同期について書かれたドキュメントがあったので紹介しとく。
http://msdn.microsoft.com/ja-jp/library/cc370085.aspx

編集 削除
gak  2012-02-22 18:21:57  No: 73201  IP: 192.*.*.*

もう一つ別視点の回答。

FillBuffer() で IMediaSample にデータをセットする際 IMediaSample::SetActualLength() で正しいデータ長を設定できてないとか。
SetActualLength() で間違ったサイズを指定してしまって有効なデータをセットしていないバッファ領域を有効扱いされちゃうと、
その部分を再生した際におかしく再生される事があるかもしれない。

編集 削除
ごんぞー  2012-02-23 14:11:16  No: 73202  IP: 192.*.*.*

gak様
返信ありがとうございます。

回答していただいた内容にていろいろと確認したところ、
FillBuffer()のIMediaSample::SetActualLength()に設定していた値に
問題があったようです。

サンプルとしていた「synth」では、pSample->GetSize()を設定しており、
それをそのまま使用していたのですが、こちらで設定しようとしていた
GetSizeの内容は1秒間に出力するバッファサイズ(チャンネル数×サンプル周波数×コンテナ数)だったようで、
これをFPSの値で割った数字を設定することによりスムーズに
映像と音声の再生を行うことができました。

ありがとうございました。
また何かあれば、よろしくお願いいたします。

編集 削除