Merge "When switching surface, do not set mSeekNotificationSent as true, because there could be a previous uncompleted seeking which needs to send back MEDIA_SEEK_COMPLETE message. If we set mSeekNotificationSent as true here, then mediaplayer.cpp will be waiting for message MEDIA_SEEK_COMPLETE. The getCurrentPosition() will always return the seek time before MEDIA_SEEK_COMPLETE being received by mediaplayer.cpp. Fix for bug 5181272."
diff --git a/camera/CameraParameters.cpp b/camera/CameraParameters.cpp
index 51b96c1..0eb5d50 100644
--- a/camera/CameraParameters.cpp
+++ b/camera/CameraParameters.cpp
@@ -160,6 +160,7 @@
 const char CameraParameters::FOCUS_MODE_FIXED[] = "fixed";
 const char CameraParameters::FOCUS_MODE_EDOF[] = "edof";
 const char CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO[] = "continuous-video";
+const char CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE[] = "continuous-picture";
 
 CameraParameters::CameraParameters()
                 : mMap()
diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h
index b661496..6c91dfc 100644
--- a/include/camera/CameraParameters.h
+++ b/include/camera/CameraParameters.h
@@ -597,13 +597,24 @@
     // CameraHardwareInterface.autoFocus in this mode.
     static const char FOCUS_MODE_EDOF[];
     // Continuous auto focus mode intended for video recording. The camera
-    // continuously tries to focus. This is ideal for shooting video.
-    // Applications still can call CameraHardwareInterface.takePicture in this
-    // mode but the subject may not be in focus. Auto focus starts when the
-    // parameter is set. Applications should not call
-    // CameraHardwareInterface.autoFocus in this mode. To stop continuous focus,
-    // applications should change the focus mode to other modes.
+    // continuously tries to focus. This is the best choice for video
+    // recording because the focus changes smoothly . Applications still can
+    // call CameraHardwareInterface.takePicture in this mode but the subject may
+    // not be in focus. Auto focus starts when the parameter is set.
+    // Applications should not call CameraHardwareInterface.autoFocus in this
+    // mode. To stop continuous focus, applications should change the focus mode
+    // to other modes.
     static const char FOCUS_MODE_CONTINUOUS_VIDEO[];
+    // Continuous auto focus mode intended for taking pictures. The camera
+    // continuously tries to focus. The speed of focus change is more aggressive
+    // than FOCUS_MODE_CONTINUOUS_VIDEO. Auto focus starts when the parameter is
+    // set. If applications call autoFocus in this mode, the focus callback will
+    // immediately return with a boolean that indicates 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. To
+    // stop continuous focus, applications should change the focus mode to other
+    // modes.
+    static const char FOCUS_MODE_CONTINUOUS_PICTURE[];
 
 private:
     DefaultKeyedVector<String8,String8>    mMap;
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 96eecce..f2673b3 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -59,6 +59,7 @@
 #include <cutils/properties.h>
 
 #define USE_SURFACE_ALLOC 1
+#define FRAME_DROP_FREQ 0
 
 namespace android {
 
@@ -820,7 +821,12 @@
         return;
     }
 
-    if (mFlags & (LOOPING | AUTO_LOOPING)) {
+    if ((mFlags & LOOPING)
+            || ((mFlags & AUTO_LOOPING)
+                && (mAudioSink == NULL || mAudioSink->realtime()))) {
+        // Don't AUTO_LOOP if we're being recorded, since that cannot be
+        // turned off and recording would go on indefinitely.
+
         seekTo_l(0);
 
         if (mVideoSource != NULL) {
@@ -1519,14 +1525,29 @@
     }
 
     if (mVideoSource != NULL) {
-        Mutex::Autolock autoLock(mStatsLock);
-        TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
-
-        const char *component;
+        const char *componentName;
         CHECK(mVideoSource->getFormat()
-                ->findCString(kKeyDecoderComponent, &component));
+                ->findCString(kKeyDecoderComponent, &componentName));
 
-        stat->mDecoderName = component;
+        {
+            Mutex::Autolock autoLock(mStatsLock);
+            TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
+
+            stat->mDecoderName = componentName;
+        }
+
+        static const char *kPrefix = "OMX.Nvidia.";
+        static const char *kSuffix = ".decode";
+        static const size_t kSuffixLength = strlen(kSuffix);
+
+        size_t componentNameLength = strlen(componentName);
+
+        if (!strncmp(componentName, kPrefix, strlen(kPrefix))
+                && componentNameLength >= kSuffixLength
+                && !strcmp(&componentName[
+                    componentNameLength - kSuffixLength], kSuffix)) {
+            modifyFlags(SLOW_DECODER_HACK, SET);
+        }
     }
 
     return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
@@ -1706,6 +1727,7 @@
 
     if (mFlags & FIRST_FRAME) {
         modifyFlags(FIRST_FRAME, CLEAR);
+        mSinceLastDropped = 0;
         mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
     }
 
@@ -1752,18 +1774,28 @@
 
         if (latenessUs > 40000) {
             // We're more than 40ms late.
-            LOGV("we're late by %lld us (%.2f secs), dropping frame",
+            LOGV("we're late by %lld us (%.2f secs)",
                  latenessUs, latenessUs / 1E6);
-            mVideoBuffer->release();
-            mVideoBuffer = NULL;
 
+            if (!(mFlags & SLOW_DECODER_HACK)
+                    || mSinceLastDropped > FRAME_DROP_FREQ)
             {
-                Mutex::Autolock autoLock(mStatsLock);
-                ++mStats.mNumVideoFramesDropped;
-            }
+                LOGV("we're late by %lld us (%.2f secs) dropping "
+                     "one after %d frames",
+                     latenessUs, latenessUs / 1E6, mSinceLastDropped);
 
-            postVideoEvent_l();
-            return;
+                mSinceLastDropped = 0;
+                mVideoBuffer->release();
+                mVideoBuffer = NULL;
+
+                {
+                    Mutex::Autolock autoLock(mStatsLock);
+                    ++mStats.mNumVideoFramesDropped;
+                }
+
+                postVideoEvent_l();
+                return;
+            }
         }
 
         if (latenessUs < -10000) {
@@ -1782,6 +1814,7 @@
     }
 
     if (mVideoRenderer != NULL) {
+        mSinceLastDropped++;
         mVideoRenderer->render(mVideoBuffer);
     }
 
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 95f2ae8..14476d3 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -141,6 +141,8 @@
 
         TEXT_RUNNING        = 0x10000,
         TEXTPLAYER_STARTED  = 0x20000,
+
+        SLOW_DECODER_HACK   = 0x40000,
     };
 
     mutable Mutex mLock;
@@ -181,6 +183,7 @@
 
     uint32_t mFlags;
     uint32_t mExtractorFlags;
+    uint32_t mSinceLastDropped;
 
     int64_t mTimeSourceDeltaUs;
     int64_t mVideoTimeUs;