かわせみおはらと言います。
DirectShowにて、ある特定のファイルで動画の長さを取得できないで困っています。
ご教授いただければと思い、書き込みさせていただきました。
環境は以下の通りです。
IDE:Visual Studio 2008
DirectShow: Windows SDK 6.1
言語: C++
動画:MPEG1
状況は以下の通りです。
1.IMediaPositionを利用した場合。
get_Duration()を呼びだすと、E_NOTIMPLが返ってきてしまいます。
また、IGraphBuilder::Render()呼び出し後に同じようにget_Duration()を呼びだすと、
今度はVFW_E_NO_TIME_FORMAT(0x80040261)が返ってきます。
どちらにしても、長さを取得することができません。
2.IMediaSeekingを利用した場合。
GetCapabilities()を呼び出し、AM_SEEKING_CanGetDurationビットが立っていることを確認し、
その後GetDuration()を呼びだしても、E_NOTIMPLが返ってきてしまいます。
こちらも1.と同様に、Render()呼び出し後VFW_E_NO_TIME_FORMAT(0x80040261)が返ってきます。
同じエンコードをしている他のファイルでは問題なく取得できるのですが、
1秒以下のファイルにて失敗している状況です。
WindowsMediaPlayerも長さの取得に失敗しているらしく、プログレスバーが表示されません。
質問は以下の通りです。
Q1.上記1&2以外の方法で動画の長さを取得することは可能でしょうか?
Q2.単純にコーデックなどの違いによる挙動の違いなのでしょうか?
Q3.そもそも1秒未満の動画を正常に扱うことができないのでしょうか?
質問ばかりになって申し訳ございませんが、
ご存知の方がいらっしゃいましたら、ご教授よろしくお願い致します。
対象のタイムフォーマットが TIME_FORMAT_NONE(Seeking is not supported)になってるとかない?
IMediaSeeking::GetTimeFormat() でフォーマット取得して確認してみては。
> 同じエンコードをしている他のファイルでは問題なく取得できるのですが、
> 1秒以下のファイルにて失敗している状況です。
デフォルトではタイムフォーマットは TIME_FORMAT_MEDIA_TIME に設定される仕様となっている。
だが、1秒以下の動画はseekを実装するのが難しい(1秒以下をseekしようとするとかなり細かい単位で
正確にseekする必要がある等で)ので、今、かわせみおはらさんの環境で利用している
MPEG1展開用DirectShowフィルタでは TIME_FORMAT_NONE を設定しseek関係の処理を無効にしている、
等あるかもしれない。
↑は、ソースなんて無い俺の完全な想像に過ぎないのであくまで”かもしれない”の話だが。
> Q1.上記1&2以外の方法で動画の長さを取得することは可能でしょうか?
仮に現在のタイムフォーマットが TIME_FORMAT_NONE だったとして、そのフィルタで他のタイムフォーマットを
指定可能(IMediaSeeking::IsFormatSupported)なら、IMediaSeeking::SetTimeFormat() でタイムフォーマットを
変更した後に GetDuration() してやればどうなるだろうか?
> Q2.単純にコーデックなどの違いによる挙動の違いなのでしょうか?
> Q3.そもそも1秒未満の動画を正常に扱うことができないのでしょうか?
今回利用しているのとは別のMPEG1展開用フィルタでは、1秒未満の動画でもseek可能かもしれない。
対応タイムフォーマットが TIME_FORMAT_NONE のみという独自DirectShowフィルタなんてものも作れるのだから、
利用するDirectShowフィルタ次第な気もするなぁ。
gak様
ご回答ありがとうございます。
また、返信が遅れてしまい大変申し訳ございません。
やはりフィルタ依存ですよね・・。
とりあえず別の手段で回避することにいたしました。
ご回答ありがとうございました!
ツイート | ![]() |