2012-03-23 66 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