2009年04月27日

libavcodec消化の道 二口目 SDL_Mixerに移植で微妙なはまりをみせる。

ffplayのコードのオープン化(非GPL)という事で模索したところ
ようするにキューの実装を入れ換えれば良さそうだと気づいた。
有限のストリームバッファなら事前に配列を作っておけばいいし
SDL_CondとSDL_Mutexの組み合わせでは無くて
glibの非同期キューGAsyncQueueを使えばアプリケーションコードからはGPL,LGPLのコードを排除できるし
サンプルとしても見やすくなりそうだと思った。
が、その前にMixer的部分をSDL_Mixerを使う方向で工夫してみることにした。(前回好まないとか言ったくせに)
とりあえずサンプリング周波数限定ではちゃんと動く様になった。


MP3やMOD等の音楽ファイルを用意してバックで鳴らす場合
通常のSDL_Mixerのプレーヤーで鳴らすんでいいと思う。
今回の需要はあくまでflvやMP4を動画と同期してならしたり
インターネットなどとのバッファリングで鳴らすとか時間の取得をしたいとか
そういうミュージックプレーヤー的方向でSDL_Mixerを使う用途の場合だ。

Mixerの選択肢としてのOpenALだが
OpenALは音楽を鳴らすようにはできていないしイフェクトもつけ辛い。
ある程度できているものとしてSDL_Mixerは充分なものを持っている。
音楽再生用途として複数の音楽をミキシングというのはやりたい人にやってもらうとして
とりあえずストリーム系での観賞用は一つだけ鳴らすとして
SDL_Mixerのmusic用のフックにlibavcodecでデコードしたデータを渡すことにした。
関数としてはMix_HookMusicを使えば良さそうだ。
これについてsoundの方にコールバックを書くと全チャンネルひとつのコールバックになるので
SDL_Mixerのうまみがなくなってしまうからということもある。

SDL_AudioからSDL_Mixerの移行に関してMusic限定にするメリットは計算関連のロスが少ないことだと思う。
方向性としてはsoundに使う効果音はPCMに変換して使い
Musicは長い音楽を使う。これはMP4なりMP3であるという前提でいいだろう。

今回Mix_HookMusicに書き換えてさらにスペースキーで再生中にwavファイルをミキシングするところまでは
なんとかできたがサンプリング周波数の違うものの変換ができていない。

Mix_HookMusicの使い方は
SDL_Mixerの初期化コードを入れて

Mix_HookMusic(audio_callback,aCodecCtx);

でSDL_Audioのコールバックと互換だった。

ポイントとしてMix_Musicオブジェクトは使わない事があげられる。
それに関してMix_PauseMusicやMix_VolumeMusic等の命令も一切機能しないようで
試していないがfadein等も使えなさそうだ。要するにそれらは内蔵player用関数ということだ。

つまりコールバックの中でボリウム関係の処理はする必要がある。
あとSDL_PauseAudioは有効だが音楽をこれで止めてしまうとSDL_Mixerを使う意味がほとんど無くなってしまう。

SDL_Audioの場合のコールバックを呼ぶ場合は


wanted_spec.freq = aCodecCtx->sample_rate;
wanted_spec.format = AUDIO_S16SYS;
wanted_spec.channels = aCodecCtx->channels;
wanted_spec.silence = 0;
wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;
wanted_spec.callback = audio_callback;
wanted_spec.userdata = aCodecCtx;
SDL_OpenAudio(&wanted_spec, &spec);


とするのでオーディオファイルのサンプリング周波数等と関係なくコールバックの結果を吸い取ってくれるのだが
SDL_Mixerの場合はチャンネル数とサンプリング周波数を

Mix_OpenAudio(44100, AUDIO_S16, 2, 4096);

と決め打ちでやって合成していくので11024HzモノチャンネルのMP3とかをそのまま再生しようとすると
速回しになってしまった。

たまたまテストファイルがそういうものだったから気づいたのだが

Mix_OpenAudio(11024, AUDIO_S16, 1, 4096);

としたら正常に動作した。これでは意味が無い。

どうもlibcodec側か自前で変換する必要があるみたいだが
今回はここまで

44100なflvのビデオの最中にシンバルの音をスペースキーで入れて
とりあえず自己満足した気になってみた。
Mixerについてはtimidity++直叩きという発想もある。
基本をしっかり抑え変更は可能な形にしつつ
この路線で進めていこうと思う。


ラベル:ffmpeg SDL_Mixer SDL
posted by Xo_ox at 23:59| Comment(0) | クロスプラットフォーム | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
×

この広告は180日以上新しい記事の投稿がないブログに表示されております。