2012-03-23 39 views
14

我目前正在开发一款应用程序,需要记录音频,将其编码为AAC,将其编码,然后在反向接收流,解码AAC和播放音频中执行相同的操作。Android - 在我自己的项目中包含原生StageFright功能

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

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

但我想知道,由于Android已经包括怯场,具有原生代码,可以做编码和解码(例如,AAC encodingAAC decoding),是否有使用该本机代码在我的应用程序的方法吗?我怎样才能做到这一点?

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

回答

16

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

由于stagefright不会暴露于NDK,所以您将不得不做额外的工作。

有两种方式:

(1)构建采用了android完整的源代码树中的项目。这种方式需要几天才能完成,一旦准备就绪,这很容易,你可以充分利用stagefright。

(2)你可以复制包含文件到您的项目,这是该文件夹中:

Android的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(); 
+2

复制时,要注意JNI函数是C,Stagefright是C++。一些Stagefright所依赖的头文件看起来与JNI的NDK环境不兼容。 – 2012-05-07 09:53:52

+2

请注意,并非所有Android设备都有stagefright,并且API取决于版本。因为这些API没有合同,所以要非常小心,因此它们可能不稳定。 – dagalpin 2012-05-07 20:33:42

+0

StraightFright可以使用图像渲染视频? – 2012-09-03 19:20:44

相关问题