mediaplayer: display one frame when seek is called before start.

Bug: 18608164
Change-Id: I83252421278aeeb1c1611138994bfdaf86d7a363
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 96a7adb..c8f289c 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -1140,6 +1140,22 @@
             ALOGV("kWhatSeek seekTimeUs=%lld us, needNotify=%d",
                     (long long)seekTimeUs, needNotify);
 
+            if (!mStarted) {
+                // Seek before the player is started. In order to preview video,
+                // need to start the player and pause it. This branch is called
+                // only once if needed. After the player is started, any seek
+                // operation will go through normal path.
+                // All cases, including audio-only, are handled in the same way
+                // for the sake of simplicity.
+                onStart(seekTimeUs);
+                onPause();
+                mPausedByClient = true;
+                if (needNotify) {
+                    notifyDriverSeekComplete();
+                }
+                break;
+            }
+
             mDeferredActions.push_back(
                     new FlushDecoderAction(FLUSH_CMD_FLUSH /* audio */,
                                            FLUSH_CMD_FLUSH /* video */));
@@ -1233,13 +1249,16 @@
     return OK;
 }
 
-void NuPlayer::onStart() {
+void NuPlayer::onStart(int64_t startPositionUs) {
     mOffloadAudio = false;
     mAudioEOS = false;
     mVideoEOS = false;
     mStarted = true;
 
     mSource->start();
+    if (startPositionUs > 0) {
+        performSeek(startPositionUs);
+    }
 
     uint32_t flags = 0;
 
@@ -1895,11 +1914,15 @@
 void NuPlayer::finishResume() {
     if (mResumePending) {
         mResumePending = false;
-        if (mDriver != NULL) {
-            sp<NuPlayerDriver> driver = mDriver.promote();
-            if (driver != NULL) {
-                driver->notifySeekComplete();
-            }
+        notifyDriverSeekComplete();
+    }
+}
+
+void NuPlayer::notifyDriverSeekComplete() {
+    if (mDriver != NULL) {
+        sp<NuPlayerDriver> driver = mDriver.promote();
+        if (driver != NULL) {
+            driver->notifySeekComplete();
         }
     }
 }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index f417f48..d7aa830 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -233,7 +233,7 @@
     void handleFlushComplete(bool audio, bool isDecoder);
     void finishFlushIfPossible();
 
-    void onStart();
+    void onStart(int64_t startPositionUs = -1);
     void onResume();
     void onPause();
 
@@ -242,6 +242,7 @@
     void flushDecoder(bool audio, bool needShutdown);
 
     void finishResume();
+    void notifyDriverSeekComplete();
 
     void postScanSources();
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 231f2e1..84ae25e 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -397,23 +397,13 @@
     switch (mState) {
         case STATE_PREPARED:
         case STATE_STOPPED_AND_PREPARED:
-        {
-            mStartupSeekTimeUs = seekTimeUs;
-            // pretend that the seek completed. It will actually happen when starting playback.
-            // TODO: actually perform the seek here, so the player is ready to go at the new
-            // location
-            notifySeekComplete_l();
-            break;
-        }
-
-        case STATE_RUNNING:
         case STATE_PAUSED:
+            mStartupSeekTimeUs = seekTimeUs;
+            // fall through.
+        case STATE_RUNNING:
         {
             mAtEOS = false;
             mSeekInProgress = true;
-            if (mState == STATE_PAUSED) {
-               mStartupSeekTimeUs = seekTimeUs;
-            }
             // seeks can take a while, so we essentially paused
             notifyListener_l(MEDIA_PAUSED);
             mPlayer->seekToAsync(seekTimeUs, true /* needNotify */);