web-dev-qa-db-ja.com

AndroidでRaw H264ストリームをデコードしますか?

Androidでビデオストリームを表示するように要求されたプロジェクトがあります。ストリームは生のH.264であり、サーバーに接続しており、サーバーからバイトストリームを受信します。

基本的に、Androidで生のバイトをデコーダに送信し、それを表面に表示する方法はありますか?

Android 4.1の新しいMediaCodecおよびMediaExtractor APIを使用して、mp4コンテナにラップされたH264のデコードに成功しました。残念ながら、これらのAPIを使用して生のH264ファイルまたはストリーム。

FFmpegをコンパイルして使用することが1つの方法であることを理解していますが、ハードウェアアクセラレーションを使用できる組み込みのメソッドを使用したいです。また、RTSPストリーミングはAndroidでサポートされていますが、これはオプションではありません。Androidバージョンは問題ではありません。

33
will

残念ながらこのためのコードを提供することはできませんが、どのように機能するかに基づいて説明するために最善を尽くします。

MediaCodec クラスを使用して、H.264でエンコードされた生のビデオを動作させる方法の概要を次に示します。

上記のリンクを使用して、デコーダーのセットアップとその使用方法を取得する例があります。H264AVCをデコードするためにセットアップする必要があります。

H.264の形式は、NALユニットで構成され、それぞれが値0x00、0x00、0x01の3バイトの開始プレフィックスで始まり、各ユニットはこれらの直後の4番目のバイトの値に応じて異なるタイプを持ちます。 3開始バイト。 1つのNALユニットはビデオの1フレームではなく、各フレームはいくつかのNALユニットで構成されています。

基本的に、個々のユニットを見つけてデコーダーに渡すメソッドを作成しました(1つのNALユニットが開始プレフィックスであり、次の開始プレフィックスまでのバイトがあります)。

これで、H.264 AVCをデコードするためのデコーダーのセットアップがあり、デコーダーからのInputBufferがあれば、準備は完了です。このInputBufferをNALユニットで満たし、デコーダーに渡し、ストリームの長さだけこれを続ける必要があります。しかし、これを機能させるには、まずデコーダーにSPS(シーケンスパラメーターセット)NALユニットを渡す必要がありました。このユニットには、開始プレフィックス(4番目のバイト)の後に0x67のバイト値があります。一部のデバイスでは、このユニットを最初に受信しないとデコーダーがクラッシュします。基本的にこのユニットを見つけるまで、他のすべてのNALユニットを無視し、このユニットを取得するまでストリームの解析を続けます。その後、他のすべてのユニットをデコーダに渡すことができます。

一部のデバイスは最初にSPSを必要としませんでしたが、いくつかは必要でしたが、最初に渡す方が良いでしょう。

これで、構成時にデコーダーに渡したサーフェスがある場合、フレームに十分なNALユニットを取得したら、サーフェスに表示する必要があります。

29
will

同様のプロジェクトで役立ったと思うリソースを以下に示します。

  1. このビデオ MediaCodecが未加工のh.264ストリームを高レベルで処理する方法を理解する上で非常に洞察力に富んでいます。
  2. このスレッド は、SPS/PPS NALUの具体的な処理に関してもう少し詳しく説明します。前述のように、開始プレフィックスを使用して個々のNALユニットを分離し、残りのデータをMediaCodecに渡す必要があります。
  3. このレポ (libstreaming)は、Android送信にRTSP/RTPを使用してH264ストリームをデコードする素晴らしい例です。
1
Jk Jensen