Merge "media: hook up MediaCodec.setSurface" into mnc-dev
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index f4a5bc3..8220a74 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -664,11 +664,11 @@
         if (!mHasSurface) {
             throw new IllegalStateException("codec was not configured for an output surface");
         }
-
-        // TODO implement this
-        throw new IllegalArgumentException("codec does not support this surface");
+        native_setSurface(surface);
     }
 
+    private native void native_setSurface(@NonNull Surface surface);
+
     /**
      * Create a persistent input surface that can be used with codecs that normally have an input
      * surface, such as video encoders. A persistent input can be reused by subsequent
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index a09c5c0..f808c0d1 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -254,6 +254,19 @@
     return mCodec->configure(format, mSurfaceTextureClient, crypto, flags);
 }
 
+status_t JMediaCodec::setSurface(
+        const sp<IGraphicBufferProducer> &bufferProducer) {
+    sp<Surface> client;
+    if (bufferProducer != NULL) {
+        client = new Surface(bufferProducer, true /* controlledByApp */);
+    }
+    status_t err = mCodec->setSurface(client);
+    if (err == OK) {
+        mSurfaceTextureClient = client;
+    }
+    return err;
+}
+
 status_t JMediaCodec::createInputSurface(
         sp<IGraphicBufferProducer>* bufferProducer) {
     return mCodec->createInputSurface(bufferProducer);
@@ -811,6 +824,10 @@
             jniThrowException(env, "java/lang/IllegalStateException", msg);
             return 0;
 
+        case BAD_VALUE:
+            jniThrowException(env, "java/lang/IllegalArgumentException", msg);
+            return 0;
+
         default:
             if (isCryptoError(err)) {
                 throwCryptoException(env, err, msg);
@@ -883,6 +900,35 @@
     throwExceptionAsNecessary(env, err);
 }
 
+static void android_media_MediaCodec_native_setSurface(
+        JNIEnv *env,
+        jobject thiz,
+        jobject jsurface) {
+    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
+
+    if (codec == NULL) {
+        throwExceptionAsNecessary(env, INVALID_OPERATION);
+        return;
+    }
+
+    sp<IGraphicBufferProducer> bufferProducer;
+    if (jsurface != NULL) {
+        sp<Surface> surface(android_view_Surface_getSurface(env, jsurface));
+        if (surface != NULL) {
+            bufferProducer = surface->getIGraphicBufferProducer();
+        } else {
+            jniThrowException(
+                    env,
+                    "java/lang/IllegalArgumentException",
+                    "The surface has been released");
+            return;
+        }
+    }
+
+    status_t err = codec->setSurface(bufferProducer);
+    throwExceptionAsNecessary(env, err);
+}
+
 sp<PersistentSurface> android_media_MediaCodec_getPersistentInputSurface(
         JNIEnv* env, jobject object) {
     sp<PersistentSurface> persistentSurface;
@@ -1692,6 +1738,10 @@
       "Landroid/media/MediaCrypto;I)V",
       (void *)android_media_MediaCodec_native_configure },
 
+    { "native_setSurface",
+      "(Landroid/view/Surface;)V",
+      (void *)android_media_MediaCodec_native_setSurface },
+
     { "createInputSurface", "()Landroid/view/Surface;",
       (void *)android_media_MediaCodec_createInputSurface },
 
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index 4721d2d..bf61f42 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -54,6 +54,9 @@
             const sp<ICrypto> &crypto,
             int flags);
 
+    status_t setSurface(
+            const sp<IGraphicBufferProducer> &surface);
+
     status_t createInputSurface(sp<IGraphicBufferProducer>* bufferProducer);
     status_t usePersistentInputSurface(const sp<PersistentSurface> &surface);