14

私は現在、オーディオを録音し、AAC としてエンコードし、ストリーミングし、ストリームを受信し、AAC をデコードし、オーディオを再生するという逆の処理を行う必要があるアプリケーションを開発しています。

MediaRecorderを使用して AAC (MP4 コンテナーにラップ) を正常に記録し、 AudioRecordクラスを使用してオーディオを正常にアップストリームしました。ただし、オーディオをストリーミングするときにオーディオをエンコードできる必要がありますが、これらのクラスはどれもそれを行うのに役立たないようです。

少し調べたところ、この問題を抱えているほとんどの人がffmpegのようなネイティブ ライブラリを使用することになることがわかりました。

しかし、Android には既にStageFrightが含まれているため、エンコードとデコードを実行できるネイティブ コード (たとえば、AAC エンコードAAC デコード) が含まれているため、アプリケーションでこのネイティブ コードを使用する方法はありますか? どうやってやるの?

ネイティブ コードでいくつかの JNI クラスを実装するだけでよければ、すばらしいことです。さらに、これは Android ライブラリであるため、ライセンスの問題はまったくありません (間違っていたら訂正してください)。

4

1 に答える 1

17

はい、libstagefright を使用できます。非常に強力です。

stagefright は NDK に公開されていないため、追加の作業を行う必要があります。

次の 2 つの方法があります。

(1) Android の完全なソース ツリーを使用してプロジェクトをビルドします。この方法では、セットアップに数日かかります。準備ができたら、非常に簡単で、stagefright を最大限に活用できます。

(2)インクルードファイルをプロジェクトにコピーするだけで、次のフォルダー内にあります。

Android-4.0.4_r1.1/frameworks/base/include/media/stagefright

次に、libstagefright.so を動的にロードしてライブラリ関数をエクスポートし、jni プロジェクトとリンクできます。

sttgefright を使用してエンコード/デコードするのは非常に簡単で、数百行で十分です。

私は、stagefright を使用してスクリーンショットをキャプチャし、ビデオを作成しました。このビデオは、Android VNC サーバーで利用できるようになり、まもなくリリースされます。

以下はスニペットです。ffmpeg を使用してムービーをエンコードするよりも優れていると思います。オーディオ ソースも追加できます。

class ImageSource : public MediaSource {
   ImageSource(int width, int height, int colorFormat)
    : mWidth(width),
      mHeight(height),
      mColorFormat(colorFormat)
   {
   }

   virtual status_t read(
        MediaBuffer **buffer, const MediaSource::ReadOptions *options) {
       // here you can fill the buffer with your pixels
   }

   ...
};

int width = 720;
int height = 480;
sp<MediaSource> img_source = new ImageSource(width, height, colorFormat);

sp<MetaData> enc_meta = new MetaData;
// enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
// enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
enc_meta->setInt32(kKeyWidth, width);
enc_meta->setInt32(kKeyHeight, height);
enc_meta->setInt32(kKeySampleRate, kFramerate);
enc_meta->setInt32(kKeyBitRate, kVideoBitRate);
enc_meta->setInt32(kKeyStride, width);
enc_meta->setInt32(kKeySliceHeight, height);
enc_meta->setInt32(kKeyIFramesInterval, kIFramesIntervalSec);
enc_meta->setInt32(kKeyColorFormat, colorFormat);

sp<MediaSource> encoder =
    OMXCodec::Create(
            client.interface(), enc_meta, true, image_source);

sp<MPEG4Writer> writer = new MPEG4Writer("/sdcard/screenshot.mp4");
writer->addSource(encoder);

// you can add an audio source here if you want to encode audio as well
// 
//sp<MediaSource> audioEncoder =
//    OMXCodec::Create(client.interface(), encMetaAudio, true, audioSource);
//writer->addSource(audioEncoder);

writer->setMaxFileDuration(kDurationUs);
CHECK_EQ(OK, writer->start());
while (!writer->reachedEOS()) {
    fprintf(stderr, ".");
    usleep(100000);
}
err = writer->stop();
于 2012-05-02T20:18:09.117 に答える