我目前正在开发一个应用程序,该应用程序需要记录音频,将其编码为AAC,对其进行流传输并反向进行相同操作-接收流,解码AAC并播放音频。
我使用MediaRecorder成功录制了AAC(包装在MP4容器中),并使用AudioRecord类成功地上传了音频。但是,我需要能够在对音频进行流式传输时对其进行编码,但是这些类似乎都无法帮助我做到这一点。
我进行了一些研究,发现大多数有此问题的人最终都使用了本地库,例如 ffmpeg 。
但是我想知道,由于Android已经包括 StageFright ,它具有可以进行编码和解码的 native 代码(例如AAC encoding和AAC decoding),是否可以在我的应用程序中使用此 native 代码?我怎样才能做到这一点?
如果我只需要使用其 native 代码实现一些JNI类,那就太好了。另外,由于它是一个Android库,因此不会有任何许可问题(如果我错了,请纠正我)。
最佳答案
是的,您可以使用libstagefright,它非常强大。
由于stagefright没有暴露于NDK,因此您将不得不做额外的工作。
有两种方法:
(1)使用android完整源代码树构建您的项目。这种方法需要几天的时间设置,一旦准备就绪,就非常容易,并且您可以充分利用stagefright的优势。
(2)您可以将包含文件复制到您的项目中,该文件位于此文件夹中:
android-4.0.4_r1.1/frameworks/base/include/media/stagefright
那么您将通过动态加载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();