Merge "- Add another parameter in notify() to be able to send timed text sample through listener during video playback. - Add OnTimedTextListener in the MediaPlayer For feature request 800939."
diff --git a/camera/CameraParameters.cpp b/camera/CameraParameters.cpp
index 1e7abae..214cd4d 100644
--- a/camera/CameraParameters.cpp
+++ b/camera/CameraParameters.cpp
@@ -68,6 +68,8 @@
 const char CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION[] = "max-exposure-compensation";
 const char CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION[] = "min-exposure-compensation";
 const char CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP[] = "exposure-compensation-step";
+const char CameraParameters::KEY_MAX_NUM_METERING_AREAS[] = "max-num-metering-areas";
+const char CameraParameters::KEY_METERING_AREAS[] = "metering-areas";
 const char CameraParameters::KEY_ZOOM[] = "zoom";
 const char CameraParameters::KEY_MAX_ZOOM[] = "max-zoom";
 const char CameraParameters::KEY_ZOOM_RATIOS[] = "zoom-ratios";
diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h
index 7930f47..e272839 100644
--- a/include/camera/CameraParameters.h
+++ b/include/camera/CameraParameters.h
@@ -308,6 +308,44 @@
     // 0.3333, EV is -2.
     // Example value: "0.333333333" or "0.5". Read only.
     static const char KEY_EXPOSURE_COMPENSATION_STEP[];
+    // The maximum number of metering areas supported. This is the maximum
+    // length of KEY_METERING_AREAS.
+    // Example value: "0" or "2". Read only.
+    static const char KEY_MAX_NUM_METERING_AREAS[];
+    // Current metering areas. Camera driver uses these areas to decide
+    // exposure.
+    //
+    // Before accessing this parameter, apps should check
+    // KEY_MAX_NUM_METERING_AREAS first to know the maximum number of metering
+    // areas first. If the value is 0, metering area is not supported.
+    //
+    // Each metering area is a rectangle with specified weight. The direction is
+    // relative to the sensor orientation, that is, what the sensor sees. The
+    // direction is not affected by the rotation or mirroring of
+    // CAMERA_CMD_SET_DISPLAY_ORIENTATION. Coordinates of the rectangle range
+    // from -1000 to 1000. (-1000, -1000) is the upper left point. (1000, 1000)
+    // is the lower right point. The length and width of metering areas cannot
+    // be 0 or negative.
+    //
+    // The weight ranges from 1 to 1000. The sum of the weights of all metering
+    // areas must be 1000. Metering areas can partially overlap and the driver
+    // will add the weights in the overlap region. But apps should not set two
+    // metering areas that have identical coordinates.
+    //
+    // A special case of all-zero single metering area means driver to decide
+    // the metering area. For example, the driver may use more signals to decide
+    // metering areas and change them dynamically. Apps can set all-zero if they
+    // want the driver to decide metering areas.
+    //
+    // Metering areas are relative to the current field of view (KEY_ZOOM).
+    // No matter what the zoom level is, (-1000,-1000) represents the top of the
+    // currently visible camera frame. The metering area cannot be set to be
+    // outside the current field of view, even when using zoom.
+    //
+    // No matter what metering areas are, the final exposure are compensated
+    // by KEY_EXPOSURE_COMPENSATION.
+    // Example value: "(-10,-10,0,0,300),(0,0,10,10,700)". Read/write.
+    static const char KEY_METERING_AREAS[];
     // Current zoom value.
     // Example value: "0" or "6". Read/write.
     static const char KEY_ZOOM[];
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index f31c2ac..1bfdd8e 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -184,7 +184,8 @@
       mFlags(0),
       mExtractorFlags(0),
       mVideoBuffer(NULL),
-      mDecryptHandle(NULL) {
+      mDecryptHandle(NULL),
+      mLastVideoTimeUs(-1) {
     CHECK_EQ(mClient.connect(), (status_t)OK);
 
     DataSource::RegisterDefaultSniffers();
@@ -470,28 +471,13 @@
 
     mVideoRenderer.clear();
 
-    if (mVideoBuffer) {
-        mVideoBuffer->release();
-        mVideoBuffer = NULL;
-    }
-
     if (mRTSPController != NULL) {
         mRTSPController->disconnect();
         mRTSPController.clear();
     }
 
     if (mVideoSource != NULL) {
-        mVideoSource->stop();
-
-        // The following hack is necessary to ensure that the OMX
-        // component is completely released by the time we may try
-        // to instantiate it again.
-        wp<MediaSource> tmp = mVideoSource;
-        mVideoSource.clear();
-        while (tmp.promote() != NULL) {
-            usleep(1000);
-        }
-        IPCThreadState::self()->flushCommands();
+        shutdownVideoDecoder_l();
     }
 
     mDurationUs = -1;
@@ -510,6 +496,7 @@
     mFileSource.clear();
 
     mBitrate = -1;
+    mLastVideoTimeUs = -1;
 }
 
 void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
@@ -1012,7 +999,7 @@
     Mutex::Autolock autoLock(mLock);
 
     mSurface = surface;
-    mNativeWindow = surface;
+    setNativeWindow_l(surface);
 }
 
 void AwesomePlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
@@ -1020,9 +1007,57 @@
 
     mSurface.clear();
     if (surfaceTexture != NULL) {
-        mNativeWindow = new SurfaceTextureClient(surfaceTexture);
+        setNativeWindow_l(new SurfaceTextureClient(surfaceTexture));
+    }
+}
+
+void AwesomePlayer::shutdownVideoDecoder_l() {
+    if (mVideoBuffer) {
+        mVideoBuffer->release();
+        mVideoBuffer = NULL;
     }
 
+    mVideoSource->stop();
+
+    // The following hack is necessary to ensure that the OMX
+    // component is completely released by the time we may try
+    // to instantiate it again.
+    wp<MediaSource> tmp = mVideoSource;
+    mVideoSource.clear();
+    while (tmp.promote() != NULL) {
+        usleep(1000);
+    }
+    IPCThreadState::self()->flushCommands();
+}
+
+void AwesomePlayer::setNativeWindow_l(const sp<ANativeWindow> &native) {
+    mNativeWindow = native;
+
+    if (mVideoSource == NULL) {
+        return;
+    }
+
+    LOGI("attempting to reconfigure to use new surface");
+
+    bool wasPlaying = (mFlags & PLAYING) != 0;
+
+    pause_l();
+    mVideoRenderer.clear();
+
+    shutdownVideoDecoder_l();
+
+    CHECK_EQ(initVideoDecoder(), (status_t)OK);
+
+    if (mLastVideoTimeUs >= 0) {
+        mSeeking = SEEK;
+        mSeekNotificationSent = true;
+        mSeekTimeUs = mLastVideoTimeUs;
+        mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
+    }
+
+    if (wasPlaying) {
+        play_l();
+    }
 }
 
 void AwesomePlayer::setAudioSink(
@@ -1412,6 +1447,8 @@
     int64_t timeUs;
     CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
 
+    mLastVideoTimeUs = timeUs;
+
     if (mSeeking == SEEK_VIDEO_ONLY) {
         if (mSeekTimeUs > timeUs) {
             LOGI("XXX mSeekTimeUs = %lld us, timeUs = %lld us",
diff --git a/media/libstagefright/MP3Extractor.cpp b/media/libstagefright/MP3Extractor.cpp
index 03ce202..4bdfc6f 100644
--- a/media/libstagefright/MP3Extractor.cpp
+++ b/media/libstagefright/MP3Extractor.cpp
@@ -48,7 +48,7 @@
 bool MP3Extractor::get_mp3_frame_size(
         uint32_t header, size_t *frame_size,
         int *out_sampling_rate, int *out_channels,
-        int *out_bitrate) {
+        int *out_bitrate, int *out_num_samples) {
     *frame_size = 0;
 
     if (out_sampling_rate) {
@@ -63,6 +63,10 @@
         *out_bitrate = 0;
     }
 
+    if (out_num_samples) {
+        *out_num_samples = 1152;
+    }
+
     if ((header & 0xffe00000) != 0xffe00000) {
         return false;
     }
@@ -127,6 +131,10 @@
         }
 
         *frame_size = (12000 * bitrate / sampling_rate + padding) * 4;
+
+        if (out_num_samples) {
+            *out_num_samples = 384;
+        }
     } else {
         // layer II or III
 
@@ -150,10 +158,17 @@
             bitrate = (layer == 2 /* L2 */)
                 ? kBitrateV1L2[bitrate_index - 1]
                 : kBitrateV1L3[bitrate_index - 1];
+
+            if (out_num_samples) {
+                *out_num_samples = 1152;
+            }
         } else {
             // V2 (or 2.5)
 
             bitrate = kBitrateV2[bitrate_index - 1];
+            if (out_num_samples) {
+                *out_num_samples = 576;
+            }
         }
 
         if (out_bitrate) {
@@ -374,6 +389,9 @@
     sp<MP3Seeker> mSeeker;
     MediaBufferGroup *mGroup;
 
+    int64_t mBasisTimeUs;
+    int64_t mSamplesRead;
+
     MP3Source(const MP3Source &);
     MP3Source &operator=(const MP3Source &);
 };
@@ -489,7 +507,9 @@
       mCurrentTimeUs(0),
       mStarted(false),
       mSeeker(seeker),
-      mGroup(NULL) {
+      mGroup(NULL),
+      mBasisTimeUs(0),
+      mSamplesRead(0) {
 }
 
 MP3Source::~MP3Source() {
@@ -509,6 +529,9 @@
     mCurrentPos = mFirstFramePos;
     mCurrentTimeUs = 0;
 
+    mBasisTimeUs = mCurrentTimeUs;
+    mSamplesRead = 0;
+
     mStarted = true;
 
     return OK;
@@ -552,6 +575,9 @@
         } else {
             mCurrentTimeUs = actualSeekTimeUs;
         }
+
+        mBasisTimeUs = mCurrentTimeUs;
+        mSamplesRead = 0;
     }
 
     MediaBuffer *buffer;
@@ -562,6 +588,8 @@
 
     size_t frame_size;
     int bitrate;
+    int num_samples;
+    int sample_rate;
     for (;;) {
         ssize_t n = mDataSource->readAt(mCurrentPos, buffer->data(), 4);
         if (n < 4) {
@@ -575,7 +603,7 @@
 
         if ((header & kMask) == (mFixedHeader & kMask)
             && MP3Extractor::get_mp3_frame_size(
-                header, &frame_size, NULL, NULL, &bitrate)) {
+                header, &frame_size, &sample_rate, NULL, &bitrate, &num_samples)) {
             break;
         }
 
@@ -613,7 +641,9 @@
     buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
 
     mCurrentPos += frame_size;
-    mCurrentTimeUs += frame_size * 8000ll / bitrate;
+
+    mSamplesRead += num_samples;
+    mCurrentTimeUs = mBasisTimeUs + ((mSamplesRead * 1000000) / sample_rate);
 
     *out = buffer;
 
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index 4095fbf..7621f2c 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -146,7 +146,8 @@
 
     int64_t thumbNailTime;
     if (frameTimeUs < 0) {
-        if (!trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)) {
+        if (!trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)
+                || thumbNailTime < 0) {
             thumbNailTime = 0;
         }
         options.setSeekTo(thumbNailTime, mode);
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 7fd7724..8c61064 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -218,6 +218,8 @@
     DrmManagerClient *mDrmManagerClient;
     sp<DecryptHandle> mDecryptHandle;
 
+    int64_t mLastVideoTimeUs;
+
     status_t setDataSource_l(
             const char *uri,
             const KeyedVector<String8, String8> *headers = NULL);
@@ -267,6 +269,9 @@
 
     status_t startAudioPlayer_l();
 
+    void shutdownVideoDecoder_l();
+    void setNativeWindow_l(const sp<ANativeWindow> &native);
+
     AwesomePlayer(const AwesomePlayer &);
     AwesomePlayer &operator=(const AwesomePlayer &);
 };
diff --git a/media/libstagefright/include/MP3Extractor.h b/media/libstagefright/include/MP3Extractor.h
index ef71b8f..cf1146b 100644
--- a/media/libstagefright/include/MP3Extractor.h
+++ b/media/libstagefright/include/MP3Extractor.h
@@ -42,7 +42,7 @@
     static bool get_mp3_frame_size(
             uint32_t header, size_t *frame_size,
             int *out_sampling_rate = NULL, int *out_channels = NULL,
-            int *out_bitrate = NULL);
+            int *out_bitrate = NULL, int *out_num_samples = NULL);
 
 private:
     status_t mInitCheck;
diff --git a/services/audioflinger/AudioResampler.cpp b/services/audioflinger/AudioResampler.cpp
index 5c3b43f..dca795c 100644
--- a/services/audioflinger/AudioResampler.cpp
+++ b/services/audioflinger/AudioResampler.cpp
@@ -26,11 +26,15 @@
 #include "AudioResamplerSinc.h"
 #include "AudioResamplerCubic.h"
 
+#ifdef __arm__
+#include <machine/cpu-features.h>
+#endif
+
 namespace android {
 
-#ifdef __ARM_ARCH_5E__  // optimized asm option
+#ifdef __ARM_HAVE_HALFWORD_MULTIPLY // optimized asm option
     #define ASM_ARM_RESAMP1 // enable asm optimisation for ResamplerOrder1
-#endif // __ARM_ARCH_5E__
+#endif // __ARM_HAVE_HALFWORD_MULTIPLY
 // ----------------------------------------------------------------------------
 
 class AudioResamplerOrder1 : public AudioResampler {