Bug 1192312 - Use MediaCodecSource for camera recording since gonkL r=aosmond
authorSotaro Ikeda <sikeda@mozilla.com>
Fri, 14 Aug 2015 07:34:24 -0700
changeset 290455 db0d6f44e3e909ac85fa3d066c3a4ae816bf2e59
parent 290454 d780f3b4f9f7df6f01c7238d8a2fff20aa4e69b0
child 290456 c5ee45f4af6bc440ae66dab199a6090952681efb
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaosmond
bugs1192312
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1192312 - Use MediaCodecSource for camera recording since gonkL r=aosmond
config/system-headers
dom/camera/GonkRecorder.cpp
dom/camera/GonkRecorder.h
--- a/config/system-headers
+++ b/config/system-headers
@@ -742,16 +742,17 @@ media/stagefright/foundation/AHandlerRef
 media/stagefright/foundation/ALooper.h
 media/stagefright/foundation/AMessage.h
 media/stagefright/foundation/AString.h
 media/stagefright/foundation/base64.h
 media/stagefright/foundation/hexdump.h
 media/stagefright/MediaBuffer.h
 media/stagefright/MediaBufferGroup.h
 media/stagefright/MediaCodec.h
+media/stagefright/MediaCodecSource.h
 media/stagefright/MediaDefs.h
 media/stagefright/MediaErrors.h
 media/stagefright/MediaExtractor.h
 media/stagefright/MediaSource.h
 media/stagefright/MediaWriter.h
 media/stagefright/MetaData.h
 media/stagefright/MPEG2TSWriter.h
 media/stagefright/MPEG4Writer.h
--- a/dom/camera/GonkRecorder.cpp
+++ b/dom/camera/GonkRecorder.cpp
@@ -35,17 +35,21 @@
 #include <media/stagefright/AudioSource.h>
 #include <media/stagefright/AMRWriter.h>
 #include <media/stagefright/AACWriter.h>
 #include <media/stagefright/MPEG2TSWriter.h>
 #include <media/stagefright/MPEG4Writer.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/OMXClient.h>
+#if ANDROID_VERSION >= 21
+#include <media/stagefright/MediaCodecSource.h>
+#else
 #include <media/stagefright/OMXCodec.h>
+#endif
 #include <media/MediaProfiles.h>
 
 #include <utils/Errors.h>
 #include <sys/types.h>
 #include <ctype.h>
 #include <unistd.h>
 
 #include <cutils/properties.h>
@@ -63,20 +67,31 @@ GonkRecorder::GonkRecorder()
 
     RE_LOGV("Constructor");
     reset();
 }
 
 GonkRecorder::~GonkRecorder() {
     RE_LOGV("Destructor");
     stop();
+
+#if ANDROID_VERSION >= 21
+    if (mLooper != NULL) {
+        mLooper->stop();
+    }
+#endif
 }
 
 status_t GonkRecorder::init() {
     RE_LOGV("init");
+#if ANDROID_VERSION >= 21
+    mLooper = new ALooper;
+    mLooper->setName("recorder_looper");
+    mLooper->start();
+#endif
     return OK;
 }
 
 status_t GonkRecorder::setAudioSource(audio_source_t as) {
     RE_LOGV("setAudioSource: %d", as);
     if (as < AUDIO_SOURCE_DEFAULT ||
         as >= AUDIO_SOURCE_CNT) {
         RE_LOGE("Invalid audio source: %d", as);
@@ -719,16 +734,81 @@ status_t GonkRecorder::start() {
 
     if ((status == OK) && (!mStarted)) {
         mStarted = true;
     }
 
     return status;
 }
 
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21
+sp<MediaSource> GonkRecorder::createAudioSource() {
+    sp<AudioSource> audioSource =
+        new AudioSource(
+                mAudioSource,
+                mSampleRate,
+                mAudioChannels);
+
+    status_t err = audioSource->initCheck();
+
+    if (err != OK) {
+        RE_LOGE("audio source is not initialized");
+        return NULL;
+    }
+
+    sp<AMessage> format = new AMessage;
+    switch (mAudioEncoder) {
+        case AUDIO_ENCODER_AMR_NB:
+        case AUDIO_ENCODER_DEFAULT:
+            format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
+            break;
+        case AUDIO_ENCODER_AMR_WB:
+            format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
+            break;
+        case AUDIO_ENCODER_AAC:
+            format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
+            format->setInt32("aac-profile", OMX_AUDIO_AACObjectLC);
+            break;
+        case AUDIO_ENCODER_HE_AAC:
+            format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
+            format->setInt32("aac-profile", OMX_AUDIO_AACObjectHE);
+            break;
+        case AUDIO_ENCODER_AAC_ELD:
+            format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
+            format->setInt32("aac-profile", OMX_AUDIO_AACObjectELD);
+            break;
+
+        default:
+            RE_LOGE("Unknown audio encoder: %d", mAudioEncoder);
+            return NULL;
+    }
+
+    int32_t maxInputSize;
+    CHECK(audioSource->getFormat()->findInt32(
+                kKeyMaxInputSize, &maxInputSize));
+
+    format->setInt32("max-input-size", maxInputSize);
+    format->setInt32("channel-count", mAudioChannels);
+    format->setInt32("sample-rate", mSampleRate);
+    format->setInt32("bitrate", mAudioBitRate);
+    if (mAudioTimeScale > 0) {
+        format->setInt32("time-scale", mAudioTimeScale);
+    }
+
+    sp<MediaSource> audioEncoder =
+            MediaCodecSource::Create(mLooper, format, audioSource);
+    mAudioSourceNode = audioSource;
+
+    if (audioEncoder == NULL) {
+        RE_LOGE("Failed to create audio encoder");
+    }
+
+    return audioEncoder;
+}
+#else
 sp<MediaSource> GonkRecorder::createAudioSource() {
     sp<AudioSource> audioSource =
         new AudioSource(
                 mAudioSource,
                 mSampleRate,
                 mAudioChannels);
 
     status_t err = audioSource->initCheck();
@@ -787,16 +867,17 @@ sp<MediaSource> GonkRecorder::createAudi
     CHECK_EQ(client.connect(), (status_t)OK);
     sp<MediaSource> audioEncoder =
         OMXCodec::Create(client.interface(), encMeta,
                          true /* createEncoder */, audioSource);
     mAudioSourceNode = audioSource;
 
     return audioEncoder;
 }
+#endif
 
 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
 status_t GonkRecorder::startAACRecording() {
     // FIXME:
     // Add support for OUTPUT_FORMAT_AAC_ADIF
     CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_AAC_ADTS);
 
     CHECK(mAudioEncoder == AUDIO_ENCODER_AAC ||
@@ -1208,16 +1289,97 @@ status_t GonkRecorder::setupCameraSource
     CHECK(mFrameRate != -1);
 
     mIsMetaDataStoredInVideoBuffers =
         (*cameraSource)->isMetaDataStoredInVideoBuffers();
 
     return OK;
 }
 
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21
+status_t GonkRecorder::setupVideoEncoder(
+        sp<MediaSource> cameraSource,
+        int32_t videoBitRate,
+        sp<MediaSource> *source) {
+    source->clear();
+
+    sp<AMessage> format = new AMessage();
+
+    switch (mVideoEncoder) {
+        case VIDEO_ENCODER_H263:
+            format->setString("mime", MEDIA_MIMETYPE_VIDEO_H263);
+            break;
+
+        case VIDEO_ENCODER_MPEG_4_SP:
+            format->setString("mime", MEDIA_MIMETYPE_VIDEO_MPEG4);
+            break;
+
+        case VIDEO_ENCODER_H264:
+            format->setString("mime", MEDIA_MIMETYPE_VIDEO_AVC);
+            break;
+
+        case VIDEO_ENCODER_VP8:
+            format->setString("mime", MEDIA_MIMETYPE_VIDEO_VP8);
+            break;
+
+        default:
+            CHECK(!"Should not be here, unsupported video encoding.");
+            break;
+    }
+
+    sp<MetaData> meta = cameraSource->getFormat();
+
+    int32_t width, height, stride, sliceHeight, colorFormat;
+    CHECK(meta->findInt32(kKeyWidth, &width));
+    CHECK(meta->findInt32(kKeyHeight, &height));
+    CHECK(meta->findInt32(kKeyStride, &stride));
+    CHECK(meta->findInt32(kKeySliceHeight, &sliceHeight));
+    CHECK(meta->findInt32(kKeyColorFormat, &colorFormat));
+
+    format->setInt32("width", width);
+    format->setInt32("height", height);
+    format->setInt32("stride", stride);
+    format->setInt32("slice-height", sliceHeight);
+    format->setInt32("color-format", colorFormat);
+
+    format->setInt32("bitrate", videoBitRate);
+    format->setInt32("frame-rate", mFrameRate);
+    format->setInt32("i-frame-interval", mIFramesIntervalSec);
+
+    if (mVideoTimeScale > 0) {
+        format->setInt32("time-scale", mVideoTimeScale);
+    }
+    if (mVideoEncoderProfile != -1) {
+        format->setInt32("profile", mVideoEncoderProfile);
+    }
+    if (mVideoEncoderLevel != -1) {
+        format->setInt32("level", mVideoEncoderLevel);
+    }
+
+    uint32_t flags = 0;
+    if (mIsMetaDataStoredInVideoBuffers) {
+        flags |= MediaCodecSource::FLAG_USE_METADATA_INPUT;
+    }
+
+    sp<MediaCodecSource> encoder =
+            MediaCodecSource::Create(mLooper, format, cameraSource, flags);
+    if (encoder == NULL) {
+        RE_LOGE("Failed to create video encoder");
+        // When the encoder fails to be created, we need
+        // release the camera source due to the camera's lock
+        // and unlock mechanism.
+        cameraSource->stop();
+        return UNKNOWN_ERROR;
+    }
+
+    *source = encoder;
+
+    return OK;
+}
+#else
 status_t GonkRecorder::setupVideoEncoder(
         sp<MediaSource> cameraSource,
         int32_t videoBitRate,
         sp<MediaSource> *source) {
     source->clear();
 
     sp<MetaData> enc_meta = new MetaData;
     enc_meta->setInt32(kKeyBitRate, videoBitRate);
@@ -1296,16 +1458,17 @@ status_t GonkRecorder::setupVideoEncoder
         cameraSource->stop();
         return UNKNOWN_ERROR;
     }
 
     *source = encoder;
 
     return OK;
 }
+#endif
 
 status_t GonkRecorder::setupAudioEncoder(const sp<MediaWriter>& writer) {
     status_t status = BAD_VALUE;
     if (OK != (status = checkAudioEncoderCapabilities())) {
         return status;
     }
 
     switch(mAudioEncoder) {
--- a/dom/camera/GonkRecorder.h
+++ b/dom/camera/GonkRecorder.h
@@ -19,16 +19,20 @@
 
 #include "nsISupportsImpl.h"
 #include "GonkCameraHwMgr.h"
 
 #include <media/MediaRecorderBase.h>
 #include <camera/CameraParameters.h>
 #include <utils/String8.h>
 #include <system/audio.h>
+#if ANDROID_VERSION >= 21
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AMessage.h>
+#endif
 
 #include "mozilla/RefPtr.h"
 #include "GonkCameraHwMgr.h"
 
 namespace android {
 
 class GonkCameraSource;
 struct MOZ_EXPORT MediaSource;
@@ -106,20 +110,20 @@ private:
     int32_t mStartTimeOffsetMs;
 
     String8 mParams;
 
     bool mIsMetaDataStoredInVideoBuffers;
     MediaProfiles *mEncoderProfiles;
 
     bool mStarted;
-    // Needed when GLFrames are encoded.
-    // An <IGraphicBufferProducer> pointer
-    // will be sent to the client side using which the
-    // frame buffers will be queued and dequeued
+
+#if ANDROID_VERSION >= 21
+    sp<ALooper> mLooper;
+#endif
 
     sp<GonkCameraHardware> mCameraHw;
 
     status_t setupMPEG4Recording(
         int outputFd,
         int32_t videoWidth, int32_t videoHeight,
         int32_t videoBitRate,
         int32_t *totalBitRate,