Android - 在我自己的项目中包含原生StageFright功能

时间:2012-03-23 00:22:26

标签: android stream native aac stagefright

我目前正在开发一个应用程序,它需要录制音频,将其编码为AAC,对其进行流式处理,然后反向执行 - 接收流,解码AAC和播放音频。

我使用MediaRecorder成功录制了AAC(包装在MP4容器中),并使用AudioRecord类成功上传了音频。但是,我需要能够在流式传输时对音频进行编码,但这些类似乎都没有帮助我这样做。

我研究了一下,发现大多数有这个问题的人最终都使用了像 ffmpeg 这样的本地库。

但我想知道,因为Android已经包含 StageFright ,它具有可以进行编码和解码的本机代码(例如,AAC encodingAAC decoding),是否存在在我的应用程序上使用此本机代码的方法?我怎么能这样做?

如果我只需要用他们的本机代码实现一些JNI类,那就太好了。另外,因为它是一个Android库,所以不会出现许可问题(如果我错了,请纠正我)。

1 个答案:

答案 0 :(得分:17)

是的,你可以使用libstagefright,它非常强大。

由于stagefright没有暴露给NDK,所以你将不得不做额外的工作。

有两种方法:

(1)使用android完整源代码树构建你的项目。这种方式需要几天的时间来设置,一旦准备就绪,这很容易,你可以充分利用stagefright。

(2)您可以将包含文件复制到您的项目中,它位于此文件夹中:

机器人-4.0.4_r1.1 /框架/碱/包含/媒体/怯场

然后你将通过动态加载libstagefright.so导出库函数,你可以链接到你的jni项目。

要使用statgefright进行编码/解码,它非常简单,可以做几百行。

我使用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();