7

オーディオ ファイルを生の PCM データにデコードして、ローカル ネットワークの再生デバイスにストリーミングしたいと考えています。そのために、API レベル 16 で導入された新しいMediaExtractorクラスとMediaCodecクラスを使用します。このデバイスでは、PCM データが 44,100 kHz で、2 つのチャネルと 16 ビットのサンプル サイズが必要です。入力ファイルがこれらの要件にほぼ一致する限り、これは正常に機能します。ただし、たとえば、32,000 kHz のサンプル レートを使用し、チャネルが 1 つしかない MP3 ファイルをデコードしている場合は、MediaCodec クラスから必要な出力が得られません。

MediaCodec クラスの出力形式を指定できないようです。そこで、別の MediaCodec オブジェクトをインスタンス化して、生データを目的の形式に再エンコードすることにしました。サポートされているメディア形式のリストによると、Android は Android 4.1 以降、PCM/Wave へのエンコードをサポートしています。ただし、 PCM/Wave にエンコードする MediaCodec オブジェクトを作成できません。あらゆる種類の MIME タイプを MediaCodec.createEncoderByType(type); に渡してみました。しかし、私は常に IOException で失敗しました:

java.io.IOException: Failed to allocate component instance
at android.media.MediaCodec.native_setup(Native Method)
at android.media.MediaCodec.<init>(MediaCodec.java:210)
at android.media.MediaCodec.createEncoderByType(MediaCodec.java:194)
[..]

PCM/Wave にエンコードする MediaCodec インスタンスを正常に作成でき、実際の例を提供してくれる人はいますか?

4

1 に答える 1

6

コメントでの会話によると、この回答は、OpenSL を使用してオーディオ データを PCM にデコードすることに関するものです。残念ながら、MediaCodecクラスを使用して同様の回答を提供することはできません。

開始するには、Android NDK プロジェクトをセットアップします (Eclipse を使用: プロジェクトを右クリックし、[Android ツール] -> [ネイティブ サポートを追加...])。次に、作成された Android.mk ファイルで、少なくとも OpenSL ライブラリにリンクする必要があります。

LOCAL_LDLIBS += -lOpenSLES

NDK プロジェクトに慣れていない場合は、古いインターウェブ (ここここなど) に豊富なチュートリアルがあります。

NDK プロジェクトが機能したら、一般的な目標は、PCM のデコーダーとして機能するオーディオ プレーヤーをセットアップすることです。実際、NDK サンプルには、まさにそれを行う例があります。最小限の機能を備えたツールを作成する場合よりも少し複雑になりますが、それで作業を進めることができます。このリンクで何が起こっているかについての非常にわかりやすい説明があります(「オーディオを PCM にデコード」を検索してください)。コメントで関連するOpenSL 仕様へのリンクを提供しましたが、やはりあります。データ シンクを指定するときに使用する必要がある構造は、次のSLDataFormat_PCMようになります。

SLDataFormat_PCM pcm = {
    SL_DATAFORMAT_PCM,
    2,                            // numChannels
    SL_SAMPLINGRATE_44_1,         // samplesPerSec
    SL_PCMSAMPLEFORMAT_FIXED_16,  // bitsPerSample
    SL_PCMSAMPLEFORMAT_FIXED_16,  // containerSize
    SL_SPEAKER_FRONT_LEFT |
        SL_SPEAKER_FRONT_RIGHT,   // channelMask
    SL_BYTEORDER_LITTLEENDIAN     // endianness
};

例と説明ガイドに従って、Android シンプル バッファー キュー データ ロケーターと前述のデータ形式を使用して SLDataSink を定義します。プレーヤーは、正しい形式のデータを含む一連のバッファを提供する必要があります。その後、そのデータを Java に戻すか、(より良い) ネイティブ コードからデータをストリーミングすることができます。

于 2013-12-25T14:28:06.137 に答える