webdino / gecko-embedded

Main (meta) repository for Project GEM (Gecko Embedded)
https://gecko-embedded.org
21 stars 2 forks source link

OpenMAX のゼロコピー化 #83

Open dynamis opened 5 years ago

dynamis commented 5 years ago

H.264 再生に OpenMAX を使ってもバッファのコピーが発生しているのをなくして CPU 使用率削減をしたい件、長期間後回しにしていますがこちらに issue たてておきます&以前の調査時の報告を貼り付けておきます:

Ashie Takuro wrote on https://redmine.clear-code.com/issues/3869

はじめに

本文書はGeckoでのOpenMAXによるH.264の再生において、映像バッファのコピーを行わ ずにデコードデータを直接参照(以下、ゼロコピー)することによりCPU使用率を削減 することが可能であるか否か、可能である場合はその実装方法について調査した結果を まとめたものである。

調査結果

OpenMAX ILにおけるゼロコピー実装

OpenMAX ILでは、映像バッファをEGLImageの形式で提供することで映像バッファのコピ ーを回避するためのAPI OMX_UseEGLImage が提供されている。

同APIが実装されている場合はプラットフォームに依存しないゼロコピー手段を実装す ることが可能である。しかしRZ/Gにおいて同APIをコールすると以下のようなログが出 力されることから、同APIは実装されていないと考えられる。

ts:1512023249.299315 level:0x10000 func:OmxrMcApiProxy_UseEGLImage(1211) tid:1294 mes:This function is not implemented

同APIが実装されていない場合は、プラットフォームに依存した方法でのゼロコピーを 別途実装する必要がある。

RZ/Gの場合、Qtでの実装例から見て、以下の方法で実装が可能であると考えられる。

  • 同プラットフォームの独自APIであるmmngrbuf APIを使用して映像バッファの物理メ モリ参照を取得
  • eglCreateImageKHR()のルネサス拡張機能を使用して、上記映像バッファに対応した EGLImageを作成

RZ/G向けGStremaerおよびQtでのゼロコピー実装

RZ/G上のQtでは、以下のパッチによってEGLImageによるゼロコピー実装が組み込まれる ことを確認した。なお、本パッチはmeta-rzg-demosに存在するため、meta-rzg-demosを 使用せずmeta-qt5のみでQtをビルドした場合には、映像バッファのコピーが発生する。

また、Qtでの動画再生ではバックエンドとしてGStreamerを使用しているが、主に以下 のパッチによってmmngrbuf APIによる物理メモリ参照を実現していることを確認した。

Geckoへの組み込み方法

Geckoでの他のプラットフォーム向けの実装においては、例えばFirefox OS向けのゼロ コピー実装が存在する。

https://hg.mozilla.org/mozilla-central/file/2b520bbe1d52/dom/media/platforms/omx/GonkOmxPlatformLayer.cpp

RZ/G向けのOpenMAX実装は上記実装をベースとしているため、基本となるメカニズムは 上記のものを使用可能である。ただし、Firefox OSでのメモリ共有の仕組みはAndroid OSのGrallocをベースとしており、RZ/Gのそれとは実装が異なる。 この点についてはRZ/G向けにポーティングが必要であり、具体的には PureOmxBufferData::GetPlatformMediaData()の実装、およびVideoDataへのEGLImage 用追加実装が必要である。

Geckoでのmmngrbuf APIの使用検証

詳細については割愛するが、上記GStraemerへのパッチを参考に、Geckoにおいて mmngrbuf APIを実際に使用可能であることを確認した。そのコードの主要部分を 以下に抜粋する。

already_AddRefed<MediaData>
PureOmxBufferData::GetPlatformMediaData()
{
  LOG_BUF("");

  if (!mPlatformLayer.IsVideo())
    return nullptr;

#ifdef HAVE_MMNGRBUF
  OMXR_MC_VIDEO_DECODERESULTTYPE *decodeResult =
    (OMXR_MC_VIDEO_DECODERESULTTYPE*) mBuffer->pOutputPortPrivate;
  unsigned long physicalAddr = (unsigned long) decodeResult->pvPhysImageAddressY;
  int size = mPortDef.nBufferSize;
  int idExport, dmabufFd;
  int res = mmngr_export_start_in_user(&idExport, size, physicalAddr, &dmabufFd);

  if (res == R_MM_OK) {
    LOG_BUF("Succeeded to start export: local: %p, physical: %p\n",
            mBuffer->pBuffer, physicalAddr);
  } else {
    LOG_BUF("Failed to start export\n");
  }

  mmngr_export_end_in_user(idExport);
#endif

  return nullptr;
}

結論

  • GeckoへのH.264再生のゼロコピー実装は可能である。
    • mmngrbufによりデコードデータのDMAバッファを取得
    • eglCreateImageKHR()のルネサス拡張で上記データからEGLImageを生成
    • Gecko側VideDataクラスにEGLImageに対応した実装を追加

懸念事項

  • Gecko向けの実装においてはYUV(NV12)データからルネサス拡張版eglCreateImageKHR() を使用してEGLImageを作成予定であるが、現時点ではこれが実際に可能であるかどう かの検証を行っておらず、またサンプル実装を見つけることもできていない(Qtにお ける実装では、vspmfilterでRGBデータに変換してからEGLImageを生成している)。 vspmfilterによるRGB変換が必須な場合、上記よりも工数が増大する可能性がある。
ashie commented 4 years ago

FYI: VA-APIの実装がmozilla-centralに入った https://bugzilla.mozilla.org/show_bug.cgi?id=1610199#c31

dynamis commented 4 years ago

note: VA API https://01.org/linuxgraphics/community/vaapi Intel 環境向けの HW サポート (Sandy Bridge 以降に入ってる QSV などを利用する?)

他の SoC サポートについても直接使えることはないが、実装の参考にはなりそうあるいは共通化なり再利用すると良い部分もあるかも知れないという感じでしょうか。

ashie commented 4 years ago

Intel 環境向けの HW サポート (Sandy Bridge 以降に入ってる QSV などを利用する?)

もともとはインテルが作ったAPIですけど、一応AMDやNVIDIAのGPUでも使えます。 (NVIDIA由来のvdpauというAPIもあって事情が複雑ですけど)

他の SoC サポートについても直接使えることはないが、実装の参考にはなりそうあるいは共通化なり再利用すると良い部分もあるかも知れないという感じでしょうか。

組み込み機器向けSoCだと多分どちらもサポートされていないので直接的には使えませんが、実装は参考になるはずです、というかe10sを有効化したままアクセラレーションを効かせるには、いずれにしても今回入ったDMABufの実装を使うことになります。