Merge "audioflinger: fix logcat" into nyc-mr1-dev
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index f4d0acd..4f2517c 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -314,11 +314,12 @@
 
     status_t handleSetSurface(const sp<Surface> &surface);
     status_t setupNativeWindowSizeFormatAndUsage(
-            ANativeWindow *nativeWindow /* nonnull */, int *finalUsage /* nonnull */);
+            ANativeWindow *nativeWindow /* nonnull */, int *finalUsage /* nonnull */,
+            bool reconnect);
 
     status_t configureOutputBuffersFromNativeWindow(
             OMX_U32 *nBufferCount, OMX_U32 *nBufferSize,
-            OMX_U32 *nMinUndequeuedBuffers);
+            OMX_U32 *nMinUndequeuedBuffers, bool preregister);
     status_t allocateOutputMetadataBuffers();
     status_t submitOutputMetadataBuffer();
     void signalSubmitOutputMetadataBufferIfEOS_workaround();
diff --git a/include/media/stagefright/SurfaceUtils.h b/include/media/stagefright/SurfaceUtils.h
index c1a9c0a..13d580c 100644
--- a/include/media/stagefright/SurfaceUtils.h
+++ b/include/media/stagefright/SurfaceUtils.h
@@ -24,9 +24,14 @@
 
 namespace android {
 
+/**
+ * Configures |nativeWindow| for given |width|x|height|, pixel |format|, |rotation| and |usage|.
+ * If |reconnect| is true, reconnects to the native window before hand.
+ * @return first error encountered, or NO_ERROR on success.
+ */
 status_t setNativeWindowSizeFormatAndUsage(
         ANativeWindow *nativeWindow /* nonnull */,
-        int width, int height, int format, int rotation, int usage);
+        int width, int height, int format, int rotation, int usage, bool reconnect);
 status_t pushBlankBuffersToNativeWindow(ANativeWindow *nativeWindow /* nonnull */);
 
 } // namespace android
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index cbc28e3..d97d5b1 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -674,7 +674,10 @@
     }
 
     int usageBits = 0;
-    status_t err = setupNativeWindowSizeFormatAndUsage(nativeWindow, &usageBits);
+    // no need to reconnect as we will not dequeue all buffers
+    status_t err = setupNativeWindowSizeFormatAndUsage(
+            nativeWindow, &usageBits,
+            !storingMetadataInDecodedBuffers() || mLegacyAdaptiveExperiment /* reconnect */);
     if (err != OK) {
         return err;
     }
@@ -948,7 +951,8 @@
 }
 
 status_t ACodec::setupNativeWindowSizeFormatAndUsage(
-        ANativeWindow *nativeWindow /* nonnull */, int *finalUsage /* nonnull */) {
+        ANativeWindow *nativeWindow /* nonnull */, int *finalUsage /* nonnull */,
+        bool reconnect) {
     OMX_PARAM_PORTDEFINITIONTYPE def;
     InitOMXParams(&def);
     def.nPortIndex = kPortIndexOutput;
@@ -986,12 +990,14 @@
             def.format.video.nFrameHeight,
             def.format.video.eColorFormat,
             mRotationDegrees,
-            usage);
+            usage,
+            reconnect);
 }
 
 status_t ACodec::configureOutputBuffersFromNativeWindow(
         OMX_U32 *bufferCount, OMX_U32 *bufferSize,
-        OMX_U32 *minUndequeuedBuffers) {
+        OMX_U32 *minUndequeuedBuffers, bool preregister) {
+
     OMX_PARAM_PORTDEFINITIONTYPE def;
     InitOMXParams(&def);
     def.nPortIndex = kPortIndexOutput;
@@ -1000,7 +1006,8 @@
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
 
     if (err == OK) {
-        err = setupNativeWindowSizeFormatAndUsage(mNativeWindow.get(), &mNativeWindowUsageBits);
+        err = setupNativeWindowSizeFormatAndUsage(
+                mNativeWindow.get(), &mNativeWindowUsageBits, preregister /* reconnect */);
     }
     if (err != OK) {
         mNativeWindowUsageBits = 0;
@@ -1082,7 +1089,7 @@
 status_t ACodec::allocateOutputBuffersFromNativeWindow() {
     OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
     status_t err = configureOutputBuffersFromNativeWindow(
-            &bufferCount, &bufferSize, &minUndequeuedBuffers);
+            &bufferCount, &bufferSize, &minUndequeuedBuffers, true /* preregister */);
     if (err != 0)
         return err;
     mNumUndequeuedBuffers = minUndequeuedBuffers;
@@ -1168,7 +1175,8 @@
 status_t ACodec::allocateOutputMetadataBuffers() {
     OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
     status_t err = configureOutputBuffersFromNativeWindow(
-            &bufferCount, &bufferSize, &minUndequeuedBuffers);
+            &bufferCount, &bufferSize, &minUndequeuedBuffers,
+            mLegacyAdaptiveExperiment /* preregister */);
     if (err != 0)
         return err;
     mNumUndequeuedBuffers = minUndequeuedBuffers;
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index e8cd58a..1cbcaa9 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -1791,9 +1791,8 @@
                         err = BAD_VALUE;
                     } else {
                         err = connectToSurface(surface);
-                        if (err == BAD_VALUE) {
-                            // assuming reconnecting to same surface
-                            // TODO: check if it is the same surface
+                        if (err == ALREADY_EXISTS) {
+                            // reconnecting to same surface
                             err = OK;
                         } else {
                             if (err == OK) {
@@ -2683,11 +2682,14 @@
 status_t MediaCodec::connectToSurface(const sp<Surface> &surface) {
     status_t err = OK;
     if (surface != NULL) {
+        if (mSurface != NULL
+                && surface->getConsumerName() == mSurface->getConsumerName()) {
+            ALOGI("connecting to native window with same name. Assuming no change of surface");
+            return ALREADY_EXISTS;
+        }
+
         err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
-        if (err == BAD_VALUE) {
-            ALOGI("native window already connected. Assuming no change of surface");
-            return err;
-        } else if (err == OK) {
+        if (err == OK) {
             // Require a fresh set of buffers after each connect by using a unique generation
             // number. Rely on the fact that max supported process id by Linux is 2^22.
             // PID is never 0 so we don't have to worry that we use the default generation of 0.
@@ -2709,7 +2711,8 @@
             ALOGE("native_window_api_connect returned an error: %s (%d)", strerror(-err), err);
         }
     }
-    return err;
+    // do not return ALREADY_EXISTS unless surfaces are the same
+    return err == ALREADY_EXISTS ? BAD_VALUE : err;
 }
 
 status_t MediaCodec::disconnectFromSurface() {
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index a62e1a2..377f5fd 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -22,6 +22,7 @@
 #include <utils/Log.h>
 #include <gui/Surface.h>
 
+#include "include/avc_utils.h"
 #include "include/StagefrightMetadataRetriever.h"
 
 #include <media/ICrypto.h>
@@ -237,6 +238,15 @@
     int64_t timeUs;
     size_t retriesLeft = kRetryCount;
     bool done = false;
+    const char *mime;
+    bool success = format->findCString(kKeyMIMEType, &mime);
+    if (!success) {
+        ALOGE("Could not find mime type");
+        return NULL;
+    }
+
+    bool isAvcOrHevc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)
+            || !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC);
 
     do {
         size_t inputIndex = -1;
@@ -276,6 +286,11 @@
                 memcpy(codecBuffer->data(),
                         (const uint8_t*)mediaBuffer->data() + mediaBuffer->range_offset(),
                         mediaBuffer->range_length());
+                if (isAvcOrHevc && IsIDR(codecBuffer)) {
+                    // Only need to decode one IDR frame.
+                    haveMoreInputs = false;
+                    flags |= MediaCodec::BUFFER_FLAG_EOS;
+                }
             }
 
             mediaBuffer->release();
diff --git a/media/libstagefright/SurfaceUtils.cpp b/media/libstagefright/SurfaceUtils.cpp
index 9940822..568837a 100644
--- a/media/libstagefright/SurfaceUtils.cpp
+++ b/media/libstagefright/SurfaceUtils.cpp
@@ -26,8 +26,25 @@
 
 status_t setNativeWindowSizeFormatAndUsage(
         ANativeWindow *nativeWindow /* nonnull */,
-        int width, int height, int format, int rotation, int usage) {
-    status_t err = native_window_set_buffers_dimensions(nativeWindow, width, height);
+        int width, int height, int format, int rotation, int usage, bool reconnect) {
+    status_t err = NO_ERROR;
+
+    // In some cases we need to reconnect so that we can dequeue all buffers
+    if (reconnect) {
+        err = native_window_api_disconnect(nativeWindow, NATIVE_WINDOW_API_MEDIA);
+        if (err != NO_ERROR) {
+            ALOGE("native_window_api_disconnect failed: %s (%d)", strerror(-err), -err);
+            return err;
+        }
+
+        err = native_window_api_connect(nativeWindow, NATIVE_WINDOW_API_MEDIA);
+        if (err != NO_ERROR) {
+            ALOGE("native_window_api_connect failed: %s (%d)", strerror(-err), -err);
+            return err;
+        }
+    }
+
+    err = native_window_set_buffers_dimensions(nativeWindow, width, height);
     if (err != NO_ERROR) {
         ALOGE("native_window_set_buffers_dimensions failed: %s (%d)", strerror(-err), -err);
         return err;
@@ -124,7 +141,8 @@
     }
 
     err = setNativeWindowSizeFormatAndUsage(
-            nativeWindow, 1, 1, HAL_PIXEL_FORMAT_RGBX_8888, 0, GRALLOC_USAGE_SW_WRITE_OFTEN);
+            nativeWindow, 1, 1, HAL_PIXEL_FORMAT_RGBX_8888, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
+            false /* reconnect */);
     if (err != NO_ERROR) {
         goto error;
     }
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
index 4824974..cb39244 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
@@ -124,6 +124,7 @@
     switch (mState) {
         case STATE_IN_RECONFIG:
         case STATE_CONFIGURED:
+        case STATE_ABANDONED:
             // OK
             break;
         default:
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 3aff684..299435a 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -653,9 +653,9 @@
         *buffer = 0;
         ALOGW("%s: the released buffer has already been freed by the buffer queue!", __FUNCTION__);
     } else if (res != OK) {
-        // Other errors are fatal.
+        // Treat other errors as abandonment
         ALOGE("%s: detach next buffer failed: %s (%d).", __FUNCTION__, strerror(-res), res);
-        mState = STATE_ERROR;
+        mState = STATE_ABANDONED;
         return res;
     }