Merge "Don't check mFilledBuffers whether it is empty or not when the port reconfiguration is not meant for buffer reallocation"
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 7509239..c2c6715 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -1078,6 +1078,11 @@
         frames = mRemainingFrames;
     }
 
+    int32_t waitCount = -1;
+    if (mUpdatePeriod || (!mMarkerReached && mMarkerPosition) || mLoopCount) {
+        waitCount = 1;
+    }
+
     do {
 
         audioBuffer.frameCount = frames;
@@ -1085,7 +1090,7 @@
         // Calling obtainBuffer() with a wait count of 1
         // limits wait time to WAIT_PERIOD_MS. This prevents from being
         // stuck here not being able to handle timed events (position, markers, loops).
-        status_t err = obtainBuffer(&audioBuffer, 1);
+        status_t err = obtainBuffer(&audioBuffer, waitCount);
         if (err < NO_ERROR) {
             if (err != TIMED_OUT) {
                 LOGE_IF(err != status_t(NO_MORE_BUFFERS), "Error obtaining an audio buffer, giving up.");
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index bd89ad8..50a41ca 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -108,6 +108,7 @@
         Parcel data, reply;
         data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
         data.writeStrongBinder(source->asBinder());
+        remote()->transact(SET_DATA_SOURCE_STREAM, data, &reply);
         return reply.readInt32();
     }
 
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index d41ab1b..ba076f5 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -20,8 +20,8 @@
 
 #include <binder/IPCThreadState.h>
 #include <media/AudioTrack.h>
+#include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/AudioPlayer.h>
-#include <media/stagefright/MediaDebug.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MediaSource.h>
@@ -60,7 +60,7 @@
 }
 
 void AudioPlayer::setSource(const sp<MediaSource> &source) {
-    CHECK_EQ(mSource, NULL);
+    CHECK(mSource == NULL);
     mSource = source;
 }
 
@@ -466,6 +466,8 @@
 }
 
 int64_t AudioPlayer::getRealTimeUsLocked() const {
+    CHECK(mStarted);
+    CHECK_NE(mSampleRate, 0);
     return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
 }
 
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 47224cc..07a46bd 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -1736,7 +1736,9 @@
         modifyFlags(TEXT_RUNNING, SET);
     }
 
-    TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
+    TimeSource *ts =
+        ((mFlags & AUDIO_AT_EOS) || !(mFlags & AUDIOPLAYER_STARTED))
+            ? &mSystemTimeSource : mTimeSource;
 
     if (mFlags & FIRST_FRAME) {
         modifyFlags(FIRST_FRAME, CLEAR);
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index 778c0b5..c74cb5a 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -283,8 +283,15 @@
         return NULL;
     }
 
+    sp<MetaData> fileMeta = mExtractor->getMetaData();
+
+    if (fileMeta == NULL) {
+        LOGV("extractor doesn't publish metadata, failed to initialize?");
+        return NULL;
+    }
+
     int32_t drm = 0;
-    if (mExtractor->getMetaData()->findInt32(kKeyIsDRM, &drm) && drm != 0) {
+    if (fileMeta->findInt32(kKeyIsDRM, &drm) && drm != 0) {
         LOGE("frame grab not allowed.");
         return NULL;
     }
@@ -320,7 +327,7 @@
     const void *data;
     uint32_t type;
     size_t dataSize;
-    if (mExtractor->getMetaData()->findData(kKeyAlbumArt, &type, &data, &dataSize)
+    if (fileMeta->findData(kKeyAlbumArt, &type, &data, &dataSize)
             && mAlbumArt == NULL) {
         mAlbumArt = new MediaAlbumArt;
         mAlbumArt->mSize = dataSize;
@@ -387,6 +394,11 @@
 void StagefrightMetadataRetriever::parseMetaData() {
     sp<MetaData> meta = mExtractor->getMetaData();
 
+    if (meta == NULL) {
+        LOGV("extractor doesn't publish metadata, failed to initialize?");
+        return;
+    }
+
     struct Map {
         int from;
         int to;
diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp
index 50dd804..306f1f6 100644
--- a/media/libstagefright/SurfaceMediaSource.cpp
+++ b/media/libstagefright/SurfaceMediaSource.cpp
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-// #define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
 #define LOG_TAG "SurfaceMediaSource"
 
 #include <media/stagefright/SurfaceMediaSource.h>
@@ -458,6 +458,10 @@
     LOGV("queueBuffer");
 
     Mutex::Autolock lock(mMutex);
+    *outWidth = mDefaultWidth;
+    *outHeight = mDefaultHeight;
+    *outTransform = 0;
+
     if (bufIndex < 0 || bufIndex >= mBufferCount) {
         LOGE("queueBuffer: slot index out of range [0, %d]: %d",
                 mBufferCount, bufIndex);
@@ -518,9 +522,6 @@
     // buffer is available
     onFrameReceivedLocked();
 
-    *outWidth = mDefaultWidth;
-    *outHeight = mDefaultHeight;
-    *outTransform = 0;
 
     return OK;
 }
diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp
index 3ef7b71..ffa3356 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.cpp
+++ b/media/libstagefright/matroska/MatroskaExtractor.cpp
@@ -93,7 +93,7 @@
 
     void advance();
     void reset();
-    void seek(int64_t seekTimeUs);
+    void seek(int64_t seekTimeUs, bool seekToKeyFrame);
 
     const mkvparser::Block *block() const;
     int64_t blockTimeUs() const;
@@ -137,6 +137,7 @@
     sp<MatroskaExtractor> mExtractor;
     size_t mTrackIndex;
     Type mType;
+    bool mIsAudio;
     BlockIterator mBlockIter;
     size_t mNALSizeLen;  // for type AVC
 
@@ -156,6 +157,7 @@
     : mExtractor(extractor),
       mTrackIndex(index),
       mType(OTHER),
+      mIsAudio(false),
       mBlockIter(mExtractor.get(),
                  mExtractor->mTracks.itemAt(index).mTrackNum),
       mNALSizeLen(0) {
@@ -164,6 +166,8 @@
     const char *mime;
     CHECK(meta->findCString(kKeyMIMEType, &mime));
 
+    mIsAudio = !strncasecmp("audio/", mime, 6);
+
     if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
         mType = AVC;
 
@@ -299,7 +303,7 @@
     } while (!eos() && block()->GetTrackNumber() != mTrackNum);
 }
 
-void BlockIterator::seek(int64_t seekTimeUs) {
+void BlockIterator::seek(int64_t seekTimeUs, bool seekToKeyFrame) {
     Mutex::Autolock autoLock(mExtractor->mLock);
 
     mCluster = mExtractor->mSegment->FindCluster(seekTimeUs * 1000ll);
@@ -311,8 +315,10 @@
     }
     while (!eos() && block()->GetTrackNumber() != mTrackNum);
 
-    while (!eos() && !mBlockEntry->GetBlock()->IsKey()) {
-        advance_l();
+    if (seekToKeyFrame) {
+        while (!eos() && !mBlockEntry->GetBlock()->IsKey()) {
+            advance_l();
+        }
     }
 }
 
@@ -396,7 +402,11 @@
     if (options && options->getSeekTo(&seekTimeUs, &mode)
             && !mExtractor->isLiveStreaming()) {
         clearPendingFrames();
-        mBlockIter.seek(seekTimeUs);
+
+        // Apparently keyframe indication in audio tracks is unreliable,
+        // fortunately in all our currently supported audio encodings every
+        // frame is effectively a keyframe.
+        mBlockIter.seek(seekTimeUs, !mIsAudio);
     }
 
 again:
@@ -537,6 +547,13 @@
         return;
     }
 
+#if 0
+    const mkvparser::SegmentInfo *info = mSegment->GetInfo();
+    LOGI("muxing app: %s, writing app: %s",
+         info->GetMuxingAppAsUTF8(),
+         info->GetWritingAppAsUTF8());
+#endif
+
     addTracks();
 }
 
diff --git a/media/libstagefright/tests/SurfaceMediaSource_test.cpp b/media/libstagefright/tests/SurfaceMediaSource_test.cpp
index d663602..d7bb703 100644
--- a/media/libstagefright/tests/SurfaceMediaSource_test.cpp
+++ b/media/libstagefright/tests/SurfaceMediaSource_test.cpp
@@ -156,8 +156,6 @@
             eglDestroySurface(mEglDisplay, mEglSurface);
         }
         if (mEglDisplay != EGL_NO_DISPLAY) {
-            eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
-                    EGL_NO_CONTEXT);
             eglTerminate(mEglDisplay);
         }
         ASSERT_EQ(EGL_SUCCESS, eglGetError());
@@ -461,6 +459,7 @@
 
     // The following call dequeues and queues the buffer
     eglSwapBuffers(mEglDisplay, mEglSurface);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
     glDisable(GL_SCISSOR_TEST);
 }
 
@@ -796,7 +795,12 @@
         LOGV("framesCount = %d", nFramesCount);
     }
 
-    ASSERT_EQ(NO_ERROR, native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_EGL));
+    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
+            EGL_NO_CONTEXT));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    eglDestroySurface(mEglDisplay, mEglSurface);
+    mEglSurface = EGL_NO_SURFACE;
+
     writer.stop();
 }
 // Test to examine whether we can render GL buffers in to the surface
@@ -875,7 +879,12 @@
         LOGV("framesCount = %d", nFramesCount);
     }
 
-    ASSERT_EQ(NO_ERROR, native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_EGL));
+    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
+            EGL_NO_CONTEXT));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    eglDestroySurface(mEglDisplay, mEglSurface);
+    mEglSurface = EGL_NO_SURFACE;
+
     LOGV("Stopping MediaRecorder...");
     CHECK_EQ(OK, mr->stop());
     mr.clear();
@@ -913,7 +922,12 @@
         LOGV("framesCount = %d", nFramesCount);
     }
 
-    ASSERT_EQ(NO_ERROR, native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_EGL));
+    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
+            EGL_NO_CONTEXT));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    eglDestroySurface(mEglDisplay, mEglSurface);
+    mEglSurface = EGL_NO_SURFACE;
+
     LOGV("Stopping MediaRecorder...");
     CHECK_EQ(OK, mr->stop());
     mr.clear();