yseki
2016年2月19日 10時51分
お世話になっております。
acmh264decでデコードした画像を処理してHDMI出力するようなことを考えています。
acmh264decからappsinkでアプリで確保(malloc)した領域にコピーして、appsrcからfbdevsinkでHDMI出力してみたのですが、時間が掛かるため、高速化が必要となっています。
そこで、下記のような方法を考えてみたのですが、具体的な方法(関数等)について、ご教示ください。
①acmh264decからappsinkで確保(malloc)した領域へDMA転送する。
②appsrcからacmfbdevsinkへDMA転送する。
③appsinkでフレームバッファのアドレスを取得し、未開放で終了。appsrcで左記フレームバッファからacmfbdevsinkへ出力し、フレームバッファ開放。
④専用のフィルタエレメント(filtter)を作成し、acmh264dec→filter→acmfbdevsinkを実行。
以上、よろしくお願いします。
コメント
yseki
at_yashi
2016年2月19日 11時46分
関数レベルの話ではないような気がするので、ちょっと説明を。
まず、動作が遅いのは DMAを使っていないからではなく、コピーしているからです。このコピーの速度は DMAを使っても、変わりません。メモリ帯域の問題なので。
現在の組み合わせ acmh264dec → acmfbdevsink は、acmfbdevsink が指定した LCDコントローラーが読み出すメモリ空間に、デコーダーは直接デコードしたデーターを書き込んでいます。つまり書き込みの一回しかデーターの移動が発生しません。
逆にアプリケーション側に転送すると、1) デコーダーの書き出し、2) アプリケーションのバッファーへのコピー、3) LCDコントローラーが読める場所へのコピーが発生します。毎秒30枚もあるFullHDのデーターを3倍コピーすると遅くなるのがわかると思います。
ではどうするかというと、acmfbdevsink が確保した場所にデコーダーがデーターを書いてくれるので、その場所をそのままアプリのメモリ空間にマップする、つまり触れるようにするという方法が考えられます。専用の filter を作成する場合に、upstreame からの buffer allocation request [1]を downstream の acmfbdevsink に渡し、バッファをもらいます。acmfbdevsink からもらった dmabuf対応の GstBuffer を、acmh264dec に渡してデコードデーターを書き込んでもらいます。データーが書き込まれたバッファーをもらったら、dmabuf の空間を mmap() [2]して画像を操作してください。この時、色空間の操作をしてしまうと、結局コピーが発生するので注意が必要です[3]。画像の操作が終われば、mumap()し、acmfbdevsink にバッファーを渡します。
イメージつきますでしょうか?
[1]: https://gstreamer.freedesktop.org/data/doc/gstreamer/head/pwg/html/sect…
[2]: https://github.com/torvalds/linux/blob/master/Documentation/dma-buf-sha…
[3]: たとえその場で変換しても全ピクセルデーターを触るのでおそくなります