Better seek handling and proper reset of the vorbis decoder after a discontinuity (seek)

Change-Id: I3c76d35da48e0964f7a0fa2816f8573b5e1a9436
related-to-bug: 2674036
QA-impact: low, only affects ogg-vorbis playback through http
diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp
index 699b955..d0d1b14 100644
--- a/media/libstagefright/OggExtractor.cpp
+++ b/media/libstagefright/OggExtractor.cpp
@@ -94,6 +94,8 @@
     size_t mCurrentPageSize;
     size_t mNextLaceIndex;
 
+    off_t mFirstDataOffset;
+
     vorbis_info mVi;
     vorbis_comment mVc;
 
@@ -183,7 +185,8 @@
     : mSource(source),
       mOffset(0),
       mCurrentPageSize(0),
-      mNextLaceIndex(0) {
+      mNextLaceIndex(0),
+      mFirstDataOffset(-1) {
     mCurrentPage.mNumSegments = 0;
 }
 
@@ -222,6 +225,12 @@
 }
 
 status_t MyVorbisExtractor::seekToOffset(off_t offset) {
+    if (mFirstDataOffset >= 0 && offset < mFirstDataOffset) {
+        // Once we know where the actual audio data starts (past the headers)
+        // don't ever seek to anywhere before that.
+        offset = mFirstDataOffset;
+    }
+
     off_t pageOffset;
     status_t err = findNextPage(offset, &pageOffset);
 
@@ -438,6 +447,8 @@
     verifyHeader(packet, 5);
     packet->release();
     packet = NULL;
+
+    mFirstDataOffset = mOffset + mCurrentPageSize;
 }
 
 void MyVorbisExtractor::verifyHeader(
diff --git a/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp b/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp
index 5485f25..df3f16a 100644
--- a/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp
+++ b/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp
@@ -173,18 +173,19 @@
     pack.granulepos = 0;
     pack.packetno = 0;
 
+    int numFrames = 0;
+
     int err = vorbis_dsp_synthesis(mState, &pack, 1);
     if (err != 0) {
         LOGW("vorbis_dsp_synthesis returned %d", err);
-        return 0;
-    }
+    } else {
+        numFrames = vorbis_dsp_pcmout(
+                mState, (int16_t *)out->data(), kMaxNumSamplesPerBuffer);
 
-    int numFrames = vorbis_dsp_pcmout(
-            mState, (int16_t *)out->data(), kMaxNumSamplesPerBuffer);
-
-    if (numFrames < 0) {
-        LOGE("vorbis_dsp_pcmout returned %d", numFrames);
-        return 0;
+        if (numFrames < 0) {
+            LOGE("vorbis_dsp_pcmout returned %d", numFrames);
+            numFrames = 0;
+        }
     }
 
     out->set_range(0, numFrames * sizeof(int16_t) * mNumChannels);
@@ -203,6 +204,7 @@
         CHECK(seekTimeUs >= 0);
 
         mNumFramesOutput = 0;
+        vorbis_dsp_restart(mState);
     } else {
         seekTimeUs = -1;
     }