Merge "audio policy: fix build with USE_LEGACY_AUDIO_POLICY" into lmp-dev
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 28e5c56..d77ddaf 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -217,6 +217,8 @@
 
     bool mCreateInputBuffersSuspended;
 
+    bool mTunneled;
+
     status_t setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode);
     status_t allocateBuffersOnPort(OMX_U32 portIndex);
     status_t freeBuffersOnPort(OMX_U32 portIndex);
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 17190fb..cadd691 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -1172,6 +1172,7 @@
             client.interface(),
             (mVideoEncoder == VIDEO_ENCODER_H263 ? MEDIA_MIMETYPE_VIDEO_H263 :
              mVideoEncoder == VIDEO_ENCODER_MPEG_4_SP ? MEDIA_MIMETYPE_VIDEO_MPEG4 :
+             mVideoEncoder == VIDEO_ENCODER_VP8 ? MEDIA_MIMETYPE_VIDEO_VP8 :
              mVideoEncoder == VIDEO_ENCODER_H264 ? MEDIA_MIMETYPE_VIDEO_AVC : ""),
             false /* decoder */, true /* hwCodec */, &codecs);
     *supportsCameraSourceMetaDataMode = codecs.size() > 0;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 5270efc..1c73995 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -174,6 +174,7 @@
       mNumFramesDropped(0ll),
       mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW),
       mStarted(false) {
+    clearFlushComplete();
 }
 
 NuPlayer::~NuPlayer() {
@@ -333,25 +334,6 @@
     msg->post();
 }
 
-// static
-bool NuPlayer::IsFlushingState(FlushStatus state, bool *needShutdown) {
-    switch (state) {
-        case FLUSHING_DECODER:
-            if (needShutdown != NULL) {
-                *needShutdown = false;
-            }
-            return true;
-
-        case FLUSHING_DECODER_SHUTDOWN:
-            if (needShutdown != NULL) {
-                *needShutdown = true;
-            }
-            return true;
-
-        default:
-            return false;
-    }
-}
 
 void NuPlayer::writeTrackInfo(
         Parcel* reply, const sp<AMessage> format) const {
@@ -773,38 +755,9 @@
 
                 mRenderer->queueEOS(audio, err);
             } else if (what == Decoder::kWhatFlushCompleted) {
-                bool needShutdown;
-
-                if (audio) {
-                    CHECK(IsFlushingState(mFlushingAudio, &needShutdown));
-                    mFlushingAudio = FLUSHED;
-                } else {
-                    CHECK(IsFlushingState(mFlushingVideo, &needShutdown));
-                    mFlushingVideo = FLUSHED;
-
-                    mVideoLateByUs = 0;
-                }
-
                 ALOGV("decoder %s flush completed", audio ? "audio" : "video");
 
-                if (needShutdown) {
-                    ALOGV("initiating %s decoder shutdown",
-                         audio ? "audio" : "video");
-
-                    // Widevine source reads must stop before releasing the video decoder.
-                    if (!audio && mSource != NULL && mSourceFlags & Source::FLAG_SECURE) {
-                        mSource->stop();
-                    }
-
-                    getDecoder(audio)->initiateShutdown();
-
-                    if (audio) {
-                        mFlushingAudio = SHUTTING_DOWN_DECODER;
-                    } else {
-                        mFlushingVideo = SHUTTING_DOWN_DECODER;
-                    }
-                }
-
+                handleFlushComplete(audio, true /* isDecoder */);
                 finishFlushIfPossible();
             } else if (what == Decoder::kWhatOutputFormatChanged) {
                 sp<AMessage> format;
@@ -957,6 +910,8 @@
                 CHECK(msg->findInt32("audio", &audio));
 
                 ALOGV("renderer %s flush completed.", audio ? "audio" : "video");
+                handleFlushComplete(audio, false /* isDecoder */);
+                finishFlushIfPossible();
             } else if (what == Renderer::kWhatVideoRenderingStart) {
                 notifyListener(MEDIA_INFO, MEDIA_INFO_RENDERING_START, 0);
             } else if (what == Renderer::kWhatMediaRenderingStart) {
@@ -1048,9 +1003,9 @@
             } else {
                 ALOGW("resume called when source is gone or not set");
             }
-            // |mAudioDecoder| may have been released due to the pause timeout, so try to re-create
-            // it if needed.
-            if (mFlushingAudio != SHUT_DOWN) {
+            // |mAudioDecoder| may have been released due to the pause timeout, so re-create it if
+            // needed.
+            if (audioDecoderStillNeeded() && mAudioDecoder == NULL) {
                 instantiateDecoder(true /* audio */, &mAudioDecoder);
             }
             if (mRenderer != NULL) {
@@ -1079,6 +1034,55 @@
     }
 }
 
+bool NuPlayer::audioDecoderStillNeeded() {
+    // Audio decoder is no longer needed if it's in shut/shutting down status.
+    return ((mFlushingAudio != SHUT_DOWN) && (mFlushingAudio != SHUTTING_DOWN_DECODER));
+}
+
+void NuPlayer::handleFlushComplete(bool audio, bool isDecoder) {
+    // We wait for both the decoder flush and the renderer flush to complete
+    // before entering either the FLUSHED or the SHUTTING_DOWN_DECODER state.
+
+    mFlushComplete[audio][isDecoder] = true;
+    if (!mFlushComplete[audio][!isDecoder]) {
+        return;
+    }
+
+    FlushStatus *state = audio ? &mFlushingAudio : &mFlushingVideo;
+    switch (*state) {
+        case FLUSHING_DECODER:
+        {
+            *state = FLUSHED;
+
+            if (!audio) {
+                mVideoLateByUs = 0;
+            }
+            break;
+        }
+
+        case FLUSHING_DECODER_SHUTDOWN:
+        {
+            *state = SHUTTING_DOWN_DECODER;
+
+            ALOGV("initiating %s decoder shutdown", audio ? "audio" : "video");
+            if (!audio) {
+                mVideoLateByUs = 0;
+                // Widevine source reads must stop before releasing the video decoder.
+                if (mSource != NULL && mSourceFlags & Source::FLAG_SECURE) {
+                    mSource->stop();
+                }
+            }
+            getDecoder(audio)->initiateShutdown();
+            break;
+        }
+
+        default:
+            // decoder flush completes only occur in a flushing state.
+            LOG_ALWAYS_FATAL_IF(isDecoder, "decoder flush in invalid state %d", *state);
+            break;
+    }
+}
+
 void NuPlayer::finishFlushIfPossible() {
     if (mFlushingAudio != NONE && mFlushingAudio != FLUSHED
             && mFlushingAudio != SHUT_DOWN) {
@@ -1111,6 +1115,8 @@
     mFlushingAudio = NONE;
     mFlushingVideo = NONE;
 
+    clearFlushComplete();
+
     processDeferredActions();
 }
 
@@ -1715,6 +1721,8 @@
     FlushStatus newStatus =
         needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER;
 
+    mFlushComplete[audio][false /* isDecoder */] = false;
+    mFlushComplete[audio][true /* isDecoder */] = false;
     if (audio) {
         ALOGE_IF(mFlushingAudio != NONE,
                 "audio flushDecoder() is called in state %d", mFlushingAudio);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 8fa7269..1b9a756 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -164,6 +164,9 @@
     // notion of time has changed.
     bool mTimeDiscontinuityPending;
 
+    // Status of flush responses from the decoder and renderer.
+    bool mFlushComplete[2][2];
+
     // Used by feedDecoderInputData to aggregate small buffers into
     // one large buffer.
     sp<ABuffer> mPendingAudioAccessUnit;
@@ -187,6 +190,13 @@
         return audio ? mAudioDecoder : mVideoDecoder;
     }
 
+    inline void clearFlushComplete() {
+        mFlushComplete[0][0] = false;
+        mFlushComplete[0][1] = false;
+        mFlushComplete[1][0] = false;
+        mFlushComplete[1][1] = false;
+    }
+
     void openAudioSink(const sp<AMessage> &format, bool offloadOnly);
     void closeAudioSink();
 
@@ -201,14 +211,15 @@
 
     void notifyListener(int msg, int ext1, int ext2, const Parcel *in = NULL);
 
+    void handleFlushComplete(bool audio, bool isDecoder);
     void finishFlushIfPossible();
 
+    bool audioDecoderStillNeeded();
+
     void flushDecoder(
             bool audio, bool needShutdown, const sp<AMessage> &newFormat = NULL);
     void updateDecoderFormatWithoutFlush(bool audio, const sp<AMessage> &format);
 
-    static bool IsFlushingState(FlushStatus state, bool *needShutdown = NULL);
-
     void postScanSources();
 
     void schedulePollDuration();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 1a01d52..c57955d 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -582,7 +582,7 @@
 }
 
 void NuPlayerDriver::notifyResetComplete() {
-    ALOGI("notifyResetComplete(%p)", this);
+    ALOGD("notifyResetComplete(%p)", this);
     Mutex::Autolock autoLock(mLock);
 
     CHECK_EQ(mState, STATE_RESET_IN_PROGRESS);
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index b6ac2a0..b693625 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -421,7 +421,8 @@
       mMaxPtsGapUs(-1ll),
       mTimePerFrameUs(-1ll),
       mTimePerCaptureUs(-1ll),
-      mCreateInputBuffersSuspended(false) {
+      mCreateInputBuffersSuspended(false),
+      mTunneled(false) {
     mUninitializedState = new UninitializedState(this);
     mLoadedState = new LoadedState(this);
     mLoadedToIdleState = new LoadedToIdleState(this);
@@ -697,6 +698,21 @@
         return err;
     }
 
+    // Exits here for tunneled video playback codecs -- i.e. skips native window
+    // buffer allocation step as this is managed by the tunneled OMX omponent
+    // itself and explicitly sets def.nBufferCountActual to 0.
+    if (mTunneled) {
+        ALOGV("Tunneled Playback: skipping native window buffer allocation.");
+        def.nBufferCountActual = 0;
+        err = mOMX->setParameter(
+                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+        *minUndequeuedBuffers = 0;
+        *bufferCount = 0;
+        *bufferSize = 0;
+        return err;
+    }
+
     *minUndequeuedBuffers = 0;
     err = mNativeWindow->query(
             mNativeWindow.get(), NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
@@ -904,6 +920,13 @@
     ANativeWindowBuffer *buf;
     int fenceFd = -1;
     CHECK(mNativeWindow.get() != NULL);
+
+    if (mTunneled) {
+        ALOGW("dequeueBufferFromNativeWindow() should not be called in tunnel"
+              " video playback mode mode!");
+        return NULL;
+    }
+
     if (native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf) != 0) {
         ALOGE("dequeueBuffer failed.");
         return NULL;
@@ -1245,6 +1268,7 @@
         if (msg->findInt32("feature-tunneled-playback", &tunneled) &&
             tunneled != 0) {
             ALOGI("Configuring TUNNELED video playback.");
+            mTunneled = true;
 
             int32_t audioHwSync = 0;
             if (!msg->findInt32("audio-hw-sync", &audioHwSync)) {
@@ -1259,6 +1283,9 @@
 
             inputFormat->setInt32("adaptive-playback", true);
         } else {
+            ALOGV("Configuring CPU controlled video playback.");
+            mTunneled = false;
+
             // Always try to enable dynamic output buffers on native surface
             err = mOMX->storeMetaDataInBuffers(
                     mNode, kPortIndexOutput, OMX_TRUE);
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index 1b6eac4..40925fd 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -654,6 +654,7 @@
             inHeader->nOffset += inBufferUsedLength;
 
             AAC_DECODER_ERROR decoderErr;
+            int numLoops = 0;
             do {
                 if (outputDelayRingBufferSpaceLeft() <
                         (mStreamInfo->frameSize * mStreamInfo->numChannels)) {
@@ -661,20 +662,19 @@
                     break;
                 }
 
-                int numconsumed = mStreamInfo->numTotalBytes + mStreamInfo->numBadBytes;
+                int numConsumed = mStreamInfo->numTotalBytes;
                 decoderErr = aacDecoder_DecodeFrame(mAACDecoder,
                                            tmpOutBuffer,
                                            2048 * MAX_CHANNEL_COUNT,
                                            0 /* flags */);
 
-                numconsumed = (mStreamInfo->numTotalBytes + mStreamInfo->numBadBytes) - numconsumed;
-                if (numconsumed != 0) {
-                    mDecodedSizes.add(numconsumed);
-                }
+                numConsumed = mStreamInfo->numTotalBytes - numConsumed;
+                numLoops++;
 
                 if (decoderErr == AAC_DEC_NOT_ENOUGH_BITS) {
                     break;
                 }
+                mDecodedSizes.add(numConsumed);
 
                 if (decoderErr != AAC_DEC_OK) {
                     ALOGW("aacDecoder_DecodeFrame decoderErr = 0x%4.4x", decoderErr);
@@ -716,6 +716,15 @@
 
                     aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1);
 
+                    // After an error, replace the last entry in mBufferSizes with the sum of the
+                    // last <numLoops> entries from mDecodedSizes to resynchronize the in/out lists.
+                    mBufferSizes.pop();
+                    int n = 0;
+                    for (int i = 0; i < numLoops; i++) {
+                        n += mDecodedSizes.itemAt(mDecodedSizes.size() - numLoops + i);
+                    }
+                    mBufferSizes.add(n);
+
                     // fall through
                 }