Merge "Fix a hang issue where the first frame can be dropped for timelapse video recording." into ics-mr1
diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h
index ef4cf5c..7edf6b4 100644
--- a/include/camera/CameraParameters.h
+++ b/include/camera/CameraParameters.h
@@ -644,15 +644,17 @@
     // than FOCUS_MODE_CONTINUOUS_VIDEO. Auto focus starts when the parameter is
     // set.
     //
-    // If applications call CameraHardwareInterface.autoFocus in this mode, the
-    // focus callback will immediately return with a boolean that indicates
-    // whether the focus is sharp or not. The apps can then decide if they want
-    // to take a picture immediately or to change the focus mode to auto, and
-    // run a full autofocus cycle. The focus position is locked after autoFocus
-    // call. If applications want to resume the continuous focus,
-    // cancelAutoFocus must be called. Restarting the preview will not resume
-    // the continuous autofocus. To stop continuous focus, applications should
-    // change the focus mode to other modes.
+    // Applications can call CameraHardwareInterface.autoFocus in this mode. If
+    // the autofocus is in the middle of scanning, the focus callback will
+    // return when it completes. If the autofocus is not scanning, focus
+    // callback will immediately return with a boolean that indicates whether
+    // the focus is sharp or not. The apps can then decide if they want to take
+    // a picture immediately or to change the focus mode to auto, and run a full
+    // autofocus cycle. The focus position is locked after autoFocus call. If
+    // applications want to resume the continuous focus, cancelAutoFocus must be
+    // called. Restarting the preview will not resume the continuous autofocus.
+    // To stop continuous focus, applications should change the focus mode to
+    // other modes.
     static const char FOCUS_MODE_CONTINUOUS_PICTURE[];
 
 private:
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index e98d55c..08835fb 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -209,7 +209,6 @@
             status_t        prepareAsync_l();
             status_t        getDuration_l(int *msec);
             status_t        attachNewPlayer(const sp<IMediaPlayer>& player);
-            void            disconnectNativeWindow();
             status_t        reset_l();
 
     sp<IMediaPlayer>            mPlayer;
@@ -233,8 +232,6 @@
     int                         mVideoHeight;
     int                         mAudioSessionId;
     float                       mSendLevel;
-    sp<ANativeWindow>           mConnectedWindow;
-    sp<IBinder>                 mConnectedWindowBinder;
 };
 
 }; // namespace android
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index efa1c45..5a1e93a 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -49,6 +49,16 @@
         }\
     }
 
+
+static inline int16_t clamp16(int32_t sample)
+{
+    // check overflow for both positive and negative values:
+    // all bits above short range must me equal to sign bit
+    if ((sample>>15) ^ (sample>>31))
+        sample = 0x7FFF ^ (sample>>31);
+    return sample;
+}
+
 // Namespaces
 namespace android {
 namespace {
@@ -707,13 +717,6 @@
 }   /* end LvmBundle_init */
 
 
-static inline int16_t clamp16(int32_t sample)
-{
-    if ((sample>>15) ^ (sample>>31))
-        sample = 0x7FFF ^ (sample>>31);
-    return sample;
-}
-
 //----------------------------------------------------------------------------
 // LvmBundle_process()
 //----------------------------------------------------------------------------
@@ -2459,6 +2462,9 @@
     LOGV("\tEffect_setEnabled() type %d, enabled %d", pContext->EffectType, enabled);
 
     if (enabled) {
+        // Bass boost or Virtualizer can be temporarily disabled if playing over device speaker due
+        // to their nature.
+        bool tempDisabled = false;
         switch (pContext->EffectType) {
             case LVM_BASS_BOOST:
                 if (pContext->pBundledContext->bBassEnabled == LVM_TRUE) {
@@ -2471,6 +2477,7 @@
                 pContext->pBundledContext->SamplesToExitCountBb =
                      (LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*0.1);
                 pContext->pBundledContext->bBassEnabled = LVM_TRUE;
+                tempDisabled = pContext->pBundledContext->bBassTempDisabled;
                 break;
             case LVM_EQUALIZER:
                 if (pContext->pBundledContext->bEqualizerEnabled == LVM_TRUE) {
@@ -2495,6 +2502,7 @@
                 pContext->pBundledContext->SamplesToExitCountVirt =
                      (LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*0.1);
                 pContext->pBundledContext->bVirtualizerEnabled = LVM_TRUE;
+                tempDisabled = pContext->pBundledContext->bVirtualizerTempDisabled;
                 break;
             case LVM_VOLUME:
                 if (pContext->pBundledContext->bVolumeEnabled == LVM_TRUE) {
@@ -2508,7 +2516,9 @@
                 LOGV("\tEffect_setEnabled() invalid effect type");
                 return -EINVAL;
         }
-        LvmEffect_enable(pContext);
+        if (!tempDisabled) {
+            LvmEffect_enable(pContext);
+        }
     } else {
         switch (pContext->EffectType) {
             case LVM_BASS_BOOST:
@@ -2683,12 +2693,19 @@
             LOGV("\tLVM_ERROR : LvmBundle_process returned error %d", lvmStatus);
             return lvmStatus;
         }
-    }else{
+    } else {
         //LOGV("\tEffect_process Not Calling process with %d effects enabled, %d called: Effect %d",
         //pContext->pBundledContext->NumberEffectsEnabled,
         //pContext->pBundledContext->NumberEffectsCalled, pContext->EffectType);
         // 2 is for stereo input
-        memcpy(outBuffer->raw, inBuffer->raw, outBuffer->frameCount*sizeof(LVM_INT16)*2);
+        if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
+            for (size_t i=0; i < outBuffer->frameCount*2; i++){
+                outBuffer->s16[i] =
+                        clamp16((LVM_INT32)outBuffer->s16[i] + (LVM_INT32)inBuffer->s16[i]);
+            }
+        } else {
+            memcpy(outBuffer->raw, inBuffer->raw, outBuffer->frameCount*sizeof(LVM_INT16)*2);
+        }
     }
 
     return status;
@@ -3047,9 +3064,10 @@
             LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_SET_DEVICE start");
             uint32_t device = *(uint32_t *)pCmdData;
 
-            if(pContext->EffectType == LVM_BASS_BOOST){
-                if((device == AUDIO_DEVICE_OUT_SPEAKER)||(device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT)||
-                   (device == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)){
+            if (pContext->EffectType == LVM_BASS_BOOST) {
+                if((device == AUDIO_DEVICE_OUT_SPEAKER) ||
+                        (device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT) ||
+                        (device == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)){
                     LOGV("\tEFFECT_CMD_SET_DEVICE device is invalid for LVM_BASS_BOOST %d",
                           *(int32_t *)pCmdData);
                     LOGV("\tEFFECT_CMD_SET_DEVICE temporary disable LVM_BAS_BOOST");
@@ -3058,30 +3076,31 @@
                     // the effect must still report its original state as this can only be changed
                     // by the ENABLE/DISABLE command
 
-                    if(pContext->pBundledContext->bBassEnabled == LVM_TRUE){
+                    if (pContext->pBundledContext->bBassEnabled == LVM_TRUE) {
                         LOGV("\tEFFECT_CMD_SET_DEVICE disable LVM_BASS_BOOST %d",
                              *(int32_t *)pCmdData);
                         android::LvmEffect_disable(pContext);
-                        pContext->pBundledContext->bBassTempDisabled = LVM_TRUE;
                     }
-                }else{
+                    pContext->pBundledContext->bBassTempDisabled = LVM_TRUE;
+                } else {
                     LOGV("\tEFFECT_CMD_SET_DEVICE device is valid for LVM_BASS_BOOST %d",
                          *(int32_t *)pCmdData);
 
                     // If a device supports bassboost and the effect has been temporarily disabled
                     // previously then re-enable it
 
-                    if(pContext->pBundledContext->bBassTempDisabled == LVM_TRUE){
+                    if (pContext->pBundledContext->bBassEnabled == LVM_TRUE) {
                         LOGV("\tEFFECT_CMD_SET_DEVICE re-enable LVM_BASS_BOOST %d",
                              *(int32_t *)pCmdData);
                         android::LvmEffect_enable(pContext);
-                        pContext->pBundledContext->bBassTempDisabled = LVM_FALSE;
                     }
+                    pContext->pBundledContext->bBassTempDisabled = LVM_FALSE;
                 }
             }
-            if(pContext->EffectType == LVM_VIRTUALIZER){
-                if((device == AUDIO_DEVICE_OUT_SPEAKER)||(device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT)||
-                   (device == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)){
+            if (pContext->EffectType == LVM_VIRTUALIZER) {
+                if((device == AUDIO_DEVICE_OUT_SPEAKER)||
+                        (device == AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT)||
+                        (device == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)){
                     LOGV("\tEFFECT_CMD_SET_DEVICE device is invalid for LVM_VIRTUALIZER %d",
                           *(int32_t *)pCmdData);
                     LOGV("\tEFFECT_CMD_SET_DEVICE temporary disable LVM_VIRTUALIZER");
@@ -3090,25 +3109,25 @@
                     // the effect must still report its original state as this can only be changed
                     // by the ENABLE/DISABLE command
 
-                    if(pContext->pBundledContext->bVirtualizerEnabled == LVM_TRUE){
+                    if (pContext->pBundledContext->bVirtualizerEnabled == LVM_TRUE) {
                         LOGV("\tEFFECT_CMD_SET_DEVICE disable LVM_VIRTUALIZER %d",
                               *(int32_t *)pCmdData);
                         android::LvmEffect_disable(pContext);
-                        pContext->pBundledContext->bVirtualizerTempDisabled = LVM_TRUE;
                     }
-                }else{
+                    pContext->pBundledContext->bVirtualizerTempDisabled = LVM_TRUE;
+                } else {
                     LOGV("\tEFFECT_CMD_SET_DEVICE device is valid for LVM_VIRTUALIZER %d",
                           *(int32_t *)pCmdData);
 
                     // If a device supports virtualizer and the effect has been temporarily disabled
                     // previously then re-enable it
 
-                    if(pContext->pBundledContext->bVirtualizerTempDisabled == LVM_TRUE){
+                    if(pContext->pBundledContext->bVirtualizerEnabled == LVM_TRUE){
                         LOGV("\tEFFECT_CMD_SET_DEVICE re-enable LVM_VIRTUALIZER %d",
                               *(int32_t *)pCmdData);
                         android::LvmEffect_enable(pContext);
-                        pContext->pBundledContext->bVirtualizerTempDisabled = LVM_FALSE;
                     }
+                    pContext->pBundledContext->bVirtualizerTempDisabled = LVM_FALSE;
                 }
             }
             LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_SET_DEVICE end");
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 37a82e9..f72300b 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -86,8 +86,6 @@
     if (p != 0) {
         p->disconnect();
     }
-
-    disconnectNativeWindow();
 }
 
 // always call with lock held
@@ -221,63 +219,12 @@
     return mPlayer->getMetadata(update_only, apply_filter, metadata);
 }
 
-void MediaPlayer::disconnectNativeWindow() {
-    if (mConnectedWindow != NULL) {
-        status_t err = native_window_api_disconnect(mConnectedWindow.get(),
-                NATIVE_WINDOW_API_MEDIA);
-
-        if (err != OK) {
-            LOGW("native_window_api_disconnect returned an error: %s (%d)",
-                    strerror(-err), err);
-        }
-    }
-    mConnectedWindow.clear();
-}
-
 status_t MediaPlayer::setVideoSurface(const sp<Surface>& surface)
 {
     LOGV("setVideoSurface");
     Mutex::Autolock _l(mLock);
     if (mPlayer == 0) return NO_INIT;
-
-    sp<IBinder> binder(surface == NULL ? NULL : surface->asBinder());
-    if (mConnectedWindowBinder == binder) {
-        return OK;
-    }
-
-    if (surface != NULL) {
-        status_t err = native_window_api_connect(surface.get(),
-                NATIVE_WINDOW_API_MEDIA);
-
-        if (err != OK) {
-            LOGE("setVideoSurface failed: %d", err);
-            // Note that we must do the reset before disconnecting from the ANW.
-            // Otherwise queue/dequeue calls could be made on the disconnected
-            // ANW, which may result in errors.
-            reset_l();
-
-            disconnectNativeWindow();
-
-            return err;
-        }
-    }
-
-    // Note that we must set the player's new surface before disconnecting the
-    // old one.  Otherwise queue/dequeue calls could be made on the disconnected
-    // ANW, which may result in errors.
-    status_t err = mPlayer->setVideoSurface(surface);
-
-    disconnectNativeWindow();
-
-    mConnectedWindow = surface;
-
-    if (err == OK) {
-        mConnectedWindowBinder = binder;
-    } else {
-        disconnectNativeWindow();
-    }
-
-    return err;
+    return mPlayer->setVideoSurface(surface);
 }
 
 status_t MediaPlayer::setVideoSurfaceTexture(
@@ -286,48 +233,7 @@
     LOGV("setVideoSurfaceTexture");
     Mutex::Autolock _l(mLock);
     if (mPlayer == 0) return NO_INIT;
-
-    sp<IBinder> binder(surfaceTexture == NULL ? NULL :
-            surfaceTexture->asBinder());
-    if (mConnectedWindowBinder == binder) {
-        return OK;
-    }
-
-    sp<ANativeWindow> anw;
-    if (surfaceTexture != NULL) {
-        anw = new SurfaceTextureClient(surfaceTexture);
-        status_t err = native_window_api_connect(anw.get(),
-                NATIVE_WINDOW_API_MEDIA);
-
-        if (err != OK) {
-            LOGE("setVideoSurfaceTexture failed: %d", err);
-            // Note that we must do the reset before disconnecting from the ANW.
-            // Otherwise queue/dequeue calls could be made on the disconnected
-            // ANW, which may result in errors.
-            reset_l();
-
-            disconnectNativeWindow();
-
-            return err;
-        }
-    }
-
-    // Note that we must set the player's new SurfaceTexture before
-    // disconnecting the old one.  Otherwise queue/dequeue calls could be made
-    // on the disconnected ANW, which may result in errors.
-    status_t err = mPlayer->setVideoSurfaceTexture(surfaceTexture);
-
-    disconnectNativeWindow();
-
-    mConnectedWindow = anw;
-
-    if (err == OK) {
-        mConnectedWindowBinder = binder;
-    } else {
-        disconnectNativeWindow();
-    }
-
-    return err;
+    return mPlayer->setVideoSurfaceTexture(surfaceTexture);
 }
 
 // must call with lock held
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 2ea2af9..b655358 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -40,6 +40,7 @@
 #include <binder/IServiceManager.h>
 #include <binder/MemoryHeapBase.h>
 #include <binder/MemoryBase.h>
+#include <gui/SurfaceTextureClient.h>
 #include <utils/Errors.h>  // for status_t
 #include <utils/String8.h>
 #include <utils/SystemClock.h>
@@ -528,6 +529,8 @@
         p->reset();
     }
 
+    disconnectNativeWindow();
+
     IPCThreadState::self()->flushCommands();
 }
 
@@ -793,13 +796,67 @@
     return p->setVideoSurface(surface);
 }
 
+void MediaPlayerService::Client::disconnectNativeWindow() {
+    if (mConnectedWindow != NULL) {
+        status_t err = native_window_api_disconnect(mConnectedWindow.get(),
+                NATIVE_WINDOW_API_MEDIA);
+
+        if (err != OK) {
+            LOGW("native_window_api_disconnect returned an error: %s (%d)",
+                    strerror(-err), err);
+        }
+    }
+    mConnectedWindow.clear();
+}
+
 status_t MediaPlayerService::Client::setVideoSurfaceTexture(
         const sp<ISurfaceTexture>& surfaceTexture)
 {
     LOGV("[%d] setVideoSurfaceTexture(%p)", mConnId, surfaceTexture.get());
     sp<MediaPlayerBase> p = getPlayer();
     if (p == 0) return UNKNOWN_ERROR;
-    return p->setVideoSurfaceTexture(surfaceTexture);
+
+    sp<IBinder> binder(surfaceTexture == NULL ? NULL :
+            surfaceTexture->asBinder());
+    if (mConnectedWindowBinder == binder) {
+        return OK;
+    }
+
+    sp<ANativeWindow> anw;
+    if (surfaceTexture != NULL) {
+        anw = new SurfaceTextureClient(surfaceTexture);
+        status_t err = native_window_api_connect(anw.get(),
+                NATIVE_WINDOW_API_MEDIA);
+
+        if (err != OK) {
+            LOGE("setVideoSurfaceTexture failed: %d", err);
+            // Note that we must do the reset before disconnecting from the ANW.
+            // Otherwise queue/dequeue calls could be made on the disconnected
+            // ANW, which may result in errors.
+            reset();
+
+            disconnectNativeWindow();
+
+            return err;
+        }
+    }
+
+    // Note that we must set the player's new SurfaceTexture before
+    // disconnecting the old one.  Otherwise queue/dequeue calls could be made
+    // on the disconnected ANW, which may result in errors.
+    status_t err = p->setVideoSurfaceTexture(surfaceTexture);
+
+    disconnectNativeWindow();
+
+    mConnectedWindow = anw;
+
+    if (err == OK) {
+        mConnectedWindowBinder = binder;
+    } else {
+        disconnectNativeWindow();
+    }
+
+    return err;
 }
 
 status_t MediaPlayerService::Client::invoke(const Parcel& request,
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 53e625a..62214ba 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -318,6 +318,9 @@
         // @param type Of the metadata to be recorded.
         void addNewMetadataUpdate(media::Metadata::Type type);
 
+        // Disconnect from the currently connected ANativeWindow.
+        void disconnectNativeWindow();
+
         mutable     Mutex                       mLock;
                     sp<MediaPlayerBase>         mPlayer;
                     sp<MediaPlayerService>      mService;
@@ -329,6 +332,8 @@
                     int32_t                     mConnId;
                     int                         mAudioSessionId;
                     uid_t                       mUID;
+                    sp<ANativeWindow>           mConnectedWindow;
+                    sp<IBinder>                 mConnectedWindowBinder;
 
         // Metadata filters.
         media::Metadata::Filter mMetadataAllow;  // protected by mLock
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 4c710b4..70208f8 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -282,7 +282,7 @@
 
                 if (err == -EWOULDBLOCK) {
                     if (mSource->feedMoreTSData() == OK) {
-                        msg->post();
+                        msg->post(10000ll);
                     }
                 }
             } else if (what == ACodec::kWhatEOS) {
@@ -796,7 +796,7 @@
         return;
     }
 
-    driver->sendEvent(msg, ext1, ext2);
+    driver->notifyListener(msg, ext1, ext2);
 }
 
 void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index b1e917d..452ba99 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -35,6 +35,7 @@
       mNumFramesDropped(0),
       mLooper(new ALooper),
       mState(UNINITIALIZED),
+      mAtEOS(false),
       mStartupSeekTimeUs(-1) {
     mLooper->setName("NuPlayerDriver Looper");
 
@@ -106,7 +107,7 @@
 }
 
 status_t NuPlayerDriver::prepareAsync() {
-    sendEvent(MEDIA_PREPARED);
+    notifyListener(MEDIA_PREPARED);
 
     return OK;
 }
@@ -117,6 +118,7 @@
             return INVALID_OPERATION;
         case STOPPED:
         {
+            mAtEOS = false;
             mPlayer->start();
 
             if (mStartupSeekTimeUs >= 0) {
@@ -173,7 +175,7 @@
 }
 
 bool NuPlayerDriver::isPlaying() {
-    return mState == PLAYING;
+    return mState == PLAYING && !mAtEOS;
 }
 
 status_t NuPlayerDriver::seekTo(int msec) {
@@ -190,6 +192,7 @@
         case PLAYING:
         case PAUSED:
         {
+            mAtEOS = false;
             mPlayer->seekToAsync(seekTimeUs);
             break;
         }
@@ -291,7 +294,7 @@
 }
 
 void NuPlayerDriver::notifySeekComplete() {
-    sendEvent(MEDIA_SEEK_COMPLETE);
+    notifyListener(MEDIA_SEEK_COMPLETE);
 }
 
 void NuPlayerDriver::notifyFrameStats(
@@ -320,4 +323,12 @@
     return OK;
 }
 
+void NuPlayerDriver::notifyListener(int msg, int ext1, int ext2) {
+    if (msg == MEDIA_PLAYBACK_COMPLETE || msg == MEDIA_ERROR) {
+        mAtEOS = true;
+    }
+
+    sendEvent(msg, ext1, ext2);
+}
+
 }  // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index 181c37d..aaa3de0 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -67,6 +67,7 @@
     void notifyPosition(int64_t positionUs);
     void notifySeekComplete();
     void notifyFrameStats(int64_t numFramesTotal, int64_t numFramesDropped);
+    void notifyListener(int msg, int ext1 = 0, int ext2 = 0);
 
 protected:
     virtual ~NuPlayerDriver();
@@ -95,6 +96,7 @@
     };
 
     State mState;
+    bool mAtEOS;
 
     int64_t mStartupSeekTimeUs;
 
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 1c7e58d..f37e75b 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -385,10 +385,12 @@
     for (size_t i = 0; i < extractor->countTracks(); ++i) {
         sp<MetaData> meta = extractor->getTrackMetaData(i);
 
-        const char *mime;
-        CHECK(meta->findCString(kKeyMIMEType, &mime));
+        const char *_mime;
+        CHECK(meta->findCString(kKeyMIMEType, &_mime));
 
-        if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
+        String8 mime = String8(_mime);
+
+        if (!haveVideo && !strncasecmp(mime.string(), "video/", 6)) {
             setVideoSource(extractor->getTrack(i));
             haveVideo = true;
 
@@ -409,9 +411,9 @@
                 mStats.mTracks.push();
                 TrackStat *stat =
                     &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
-                stat->mMIME = mime;
+                stat->mMIME = mime.string();
             }
-        } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
+        } else if (!haveAudio && !strncasecmp(mime.string(), "audio/", 6)) {
             setAudioSource(extractor->getTrack(i));
             haveAudio = true;
 
@@ -421,10 +423,10 @@
                 mStats.mTracks.push();
                 TrackStat *stat =
                     &mStats.mTracks.editItemAt(mStats.mAudioTrackIndex);
-                stat->mMIME = mime;
+                stat->mMIME = mime.string();
             }
 
-            if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
+            if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_AUDIO_VORBIS)) {
                 // Only do this for vorbis audio, none of the other audio
                 // formats even support this ringtone specific hack and
                 // retrieving the metadata on some extractors may turn out
@@ -436,7 +438,7 @@
                     modifyFlags(AUTO_LOOPING, SET);
                 }
             }
-        } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
+        } else if (!strcasecmp(mime.string(), MEDIA_MIMETYPE_TEXT_3GPP)) {
             addTextSource(extractor->getTrack(i));
         }
     }
diff --git a/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp b/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp
index 94a79ab..d361ef4 100644
--- a/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp
@@ -82,7 +82,11 @@
                 &mEncState, &mSidState, false /* dtx_enable */),
              0);
 
-    mSource->start(params);
+    status_t err = mSource->start(params);
+    if (err != OK) {
+        LOGE("AudioSource is not available");
+        return err;
+    }
 
     mAnchorTimeUs = 0;
     mNumFramesOutput = 0;
diff --git a/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp b/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp
index 002f055..5eacc16 100644
--- a/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp
+++ b/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp
@@ -137,8 +137,12 @@
     CHECK_EQ(OK, initCheck());
 
     mNumFramesOutput = 0;
-    mSource->start(params);
 
+    status_t err = mSource->start(params);
+    if (err != OK) {
+        LOGE("AudioSource is not available");
+        return err;
+    }
     mStarted = true;
 
     return OK;