Documentation/API update for MediaCodec/MediaExtractor, fixes to MediaCodec.

and MediaExtractor.readSampleData now works with a non-direct byte buffer.

Change-Id: Ifbe5c152d9550c34d3b1d493e12a223eb98e8b4e
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 7f496ca..bccf1f9 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -92,14 +92,12 @@
      *                  "width"         - Integer
      *                  "height"        - Integer
      *                  optional "max-input-size"       - Integer
-     *                  optional "csd-0", "csd-1" ...   - ByteBuffer
      *
      *                Audio formats have the following fields:
      *                  "mime"          - String
      *                  "channel-count" - Integer
      *                  "sample-rate"   - Integer
      *                  optional "max-input-size"       - Integer
-     *                  optional "csd-0", "csd-1" ...   - ByteBuffer
      *
      *                If the format is used to configure an encoder, additional
      *                fields must be included:
@@ -114,7 +112,7 @@
      *
      *  @param surface Specify a surface on which to render the output of this
      *                 decoder.
-     *  @param flags   Specify {@see #CONFIGURE_FLAG_ENCODE} to configure the
+     *  @param flags   Specify {@link #CONFIGURE_FLAG_ENCODE} to configure the
      *                 component as an encoder.
     */
     public void configure(
@@ -155,6 +153,19 @@
 
     /** After filling a range of the input buffer at the specified index
      *  submit it to the component.
+     *
+     *  Many decoders require the actual compressed data stream to be
+     *  preceded by "codec specific data", i.e. setup data used to initialize
+     *  the codec such as PPS/SPS in the case of AVC video or code tables
+     *  in the case of vorbis audio.
+     *  The class MediaExtractor provides codec specific data as part of
+     *  the returned track format in entries named "csd-0", "csd-1" ...
+     *
+     *  These buffers should be submitted using the flag {@link #FLAG_CODECCONFIG}.
+     *
+     *  To indicate that this is the final piece of input data (or rather that
+     *  no more input data follows unless the decoder is subsequently flushed)
+     *  specify the flag {@link FLAG_EOS}.
     */
     public native final void queueInputBuffer(
             int index,
@@ -184,15 +195,25 @@
     public native final void releaseOutputBuffer(int index, boolean render);
 
     /** Call this after dequeueOutputBuffer signals a format change by returning
-     *  {@see #INFO_OUTPUT_FORMAT_CHANGED}
+     *  {@link #INFO_OUTPUT_FORMAT_CHANGED}
      */
     public native final Map<String, Object> getOutputFormat();
 
+    /** Call this after start() returns.
+     */
+    public ByteBuffer[] getInputBuffers() {
+        return getBuffers(true /* input */);
+    }
+
     /** Call this after start() returns and whenever dequeueOutputBuffer
      *  signals an output buffer change by returning
-     *  {@see #INFO_OUTPUT_BUFFERS_CHANGED}
+     *  {@link #INFO_OUTPUT_BUFFERS_CHANGED}
      */
-    public native final ByteBuffer[] getBuffers(boolean input);
+    public ByteBuffer[] getOutputBuffers() {
+        return getBuffers(false /* input */);
+    }
+
+    private native final ByteBuffer[] getBuffers(boolean input);
 
     private static native final void native_init();
 
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index 6a7f2f5..5732c72 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -56,7 +56,7 @@
     public native boolean advance();
 
     // Retrieve the current encoded sample and store it in the byte buffer
-    // starting at the given offset.
+    // starting at the given offset. Returns the sample size.
     public native int readSampleData(ByteBuffer byteBuf, int offset);
 
     // Returns the track index the current sample originates from.
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 71e698f..04d7c22 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -134,7 +134,7 @@
     uint32_t flags;
     status_t err;
     if ((err = mCodec->dequeueOutputBuffer(
-                    index, &size, &offset, &timeUs, &flags, timeoutUs)) != OK) {
+                    index, &offset, &size, &timeUs, &flags, timeoutUs)) != OK) {
         return err;
     }
 
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index 4757adf..0c86fc2 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -101,14 +101,37 @@
 
     void *dst = env->GetDirectBufferAddress(byteBuf);
 
+    jlong dstSize;
+    jbyteArray byteArray = NULL;
+
     if (dst == NULL) {
-        // XXX if dst is NULL also fall back to "array()"
-        return INVALID_OPERATION;
+        jclass byteBufClass = env->FindClass("java/nio/ByteBuffer");
+        CHECK(byteBufClass != NULL);
+
+        jmethodID arrayID =
+            env->GetMethodID(byteBufClass, "array", "()[B");
+        CHECK(arrayID != NULL);
+
+        byteArray =
+            (jbyteArray)env->CallObjectMethod(byteBuf, arrayID);
+
+        if (byteArray == NULL) {
+            return INVALID_OPERATION;
+        }
+
+        jboolean isCopy;
+        dst = env->GetByteArrayElements(byteArray, &isCopy);
+
+        dstSize = env->GetArrayLength(byteArray);
+    } else {
+        dstSize = env->GetDirectBufferCapacity(byteBuf);
     }
 
-    jlong dstSize = env->GetDirectBufferCapacity(byteBuf);
-
     if (dstSize < offset) {
+        if (byteArray != NULL) {
+            env->ReleaseByteArrayElements(byteArray, (jbyte *)dst, 0);
+        }
+
         return -ERANGE;
     }
 
@@ -116,6 +139,10 @@
 
     status_t err = mImpl->readSampleData(buffer);
 
+    if (byteArray != NULL) {
+        env->ReleaseByteArrayElements(byteArray, (jbyte *)dst, 0);
+    }
+
     if (err != OK) {
         return err;
     }