Armadilloフォーラム

DMA転送について

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を実行。

以上、よろしくお願いします。

コメント

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]: たとえその場で変換しても全ピクセルデーターを触るのでおそくなります

yseki

2016年6月3日 2時54分

お世話になっております。

いろいろ試しているのですが、思ったように動きません。
何か簡単なサンプルを提示いただけませんでしょうか。

以上、よろしくお願いします。