stagefright: abstract GraphicBufferSource to interfaces

Create two interfaces from GraphicBufferSource:

a) IGraphicBufferSource for client (ACodec) to configure the graphic
buffer source. IOMX no longer routes these messages and OMX internal
options are removed.

b) IOMXBufferSource for IOMX to send OMX specific callbacks.

Added an |origTimestamp| argument to emptyGraphicBuffer, and restore
the original PTS inside OMX to avoid going back to GraphicBufferSource
to patch the output PTS. In the longer term, we should consider moving
the max PTS gap entirely into OMX (probably as an extension index).

Define newly introduced interfaces using AIDL to facilitate code
development.

bug: 31399200

Change-Id: Ibaf6ca1a0737ba6ba9f83bedc3b06ef358db36cb
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 0c4c547..59cb28c 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -2,7 +2,14 @@
 
 include $(CLEAR_VARS)
 
+LOCAL_AIDL_INCLUDES := \
+    frameworks/av/media/libmedia/aidl
+
 LOCAL_SRC_FILES:= \
+    aidl/android/IGraphicBufferSource.aidl \
+    aidl/android/IOMXBufferSource.aidl
+
+LOCAL_SRC_FILES += \
     AudioTrack.cpp \
     AudioTrackShared.cpp \
     IAudioFlinger.cpp \
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index 0dedad4..5e6ac36 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -27,6 +27,8 @@
 #include <media/openmax/OMX_IndexExt.h>
 #include <utils/NativeHandle.h>
 
+#include <android/IGraphicBufferSource.h>
+
 namespace android {
 
 enum {
@@ -47,7 +49,6 @@
     CREATE_INPUT_SURFACE,
     CREATE_PERSISTENT_INPUT_SURFACE,
     SET_INPUT_SURFACE,
-    SIGNAL_END_OF_INPUT_STREAM,
     STORE_META_DATA_IN_BUFFERS,
     PREPARE_FOR_ADAPTIVE_PLAYBACK,
     ALLOC_SECURE_BUFFER,
@@ -59,7 +60,6 @@
     GET_EXTENSION_INDEX,
     OBSERVER_ON_MSG,
     GET_GRAPHIC_BUFFER_USAGE,
-    SET_INTERNAL_OPTION,
     UPDATE_GRAPHIC_BUFFER_IN_META,
     CONFIGURE_VIDEO_TUNNEL_MODE,
     UPDATE_NATIVE_HANDLE_IN_META,
@@ -337,7 +337,9 @@
 
     virtual status_t createInputSurface(
             node_id node, OMX_U32 port_index, android_dataspace dataSpace,
-            sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type) {
+            sp<IGraphicBufferProducer> *bufferProducer,
+            sp<IGraphicBufferSource> *bufferSource,
+            MetadataBufferType *type) {
         Parcel data, reply;
         status_t err;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
@@ -363,6 +365,8 @@
 
         *bufferProducer = IGraphicBufferProducer::asInterface(
                 reply.readStrongBinder());
+        *bufferSource = IGraphicBufferSource::asInterface(
+                reply.readStrongBinder());
 
         return err;
     }
@@ -394,7 +398,9 @@
 
     virtual status_t setInputSurface(
             node_id node, OMX_U32 port_index,
-            const sp<IGraphicBufferConsumer> &bufferConsumer, MetadataBufferType *type) {
+            const sp<IGraphicBufferConsumer> &bufferConsumer,
+            sp<IGraphicBufferSource> *bufferSource,
+            MetadataBufferType *type) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
         status_t err;
@@ -415,21 +421,15 @@
             *type = (MetadataBufferType)negotiatedType;
         }
 
-        return reply.readInt32();
-    }
-
-    virtual status_t signalEndOfInputStream(node_id node) {
-        Parcel data, reply;
-        status_t err;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)node);
-        err = remote()->transact(SIGNAL_END_OF_INPUT_STREAM, data, &reply);
+        err = reply.readInt32();
         if (err != OK) {
-            ALOGW("binder transaction failed: %d", err);
             return err;
         }
 
-        return reply.readInt32();
+        *bufferSource = IGraphicBufferSource::asInterface(
+                reply.readStrongBinder());
+
+        return err;
     }
 
     virtual status_t storeMetaDataInBuffers(
@@ -590,8 +590,8 @@
     virtual status_t emptyGraphicBuffer(
             node_id node,
             buffer_id buffer,
-            const sp<GraphicBuffer> &graphicBuffer,
-            OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
+            const sp<GraphicBuffer> &graphicBuffer, OMX_U32 flags,
+            OMX_TICKS timestamp, OMX_TICKS origTimestamp, int fenceFd) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
         data.writeInt32((int32_t)node);
@@ -599,6 +599,7 @@
         data.write(*graphicBuffer);
         data.writeInt32(flags);
         data.writeInt64(timestamp);
+        data.writeInt64(origTimestamp);
         data.writeInt32(fenceFd >= 0);
         if (fenceFd >= 0) {
             data.writeFileDescriptor(fenceFd, true /* takeOwnership */);
@@ -629,24 +630,6 @@
         return err;
     }
 
-    virtual status_t setInternalOption(
-            node_id node,
-            OMX_U32 port_index,
-            InternalOptionType type,
-            const void *optionData,
-            size_t size) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        data.writeInt32((int32_t)node);
-        data.writeInt32(port_index);
-        data.writeInt64(size);
-        data.write(optionData, size);
-        data.writeInt32(type);
-        remote()->transact(SET_INTERNAL_OPTION, data, &reply);
-
-        return reply.readInt32();
-    }
-
     virtual status_t dispatchMessage(const omx_message &msg) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
@@ -767,7 +750,6 @@
         case SET_PARAMETER:
         case GET_CONFIG:
         case SET_CONFIG:
-        case SET_INTERNAL_OPTION:
         {
             CHECK_OMX_INTERFACE(IOMX, data, reply);
 
@@ -781,8 +763,7 @@
             size_t pageSize = 0;
             size_t allocSize = 0;
             bool isUsageBits = (index == (OMX_INDEXTYPE) OMX_IndexParamConsumerUsageBits);
-            if ((isUsageBits && size < 4) ||
-                    (!isUsageBits && code != SET_INTERNAL_OPTION && size < 8)) {
+            if ((isUsageBits && size < 4) || (!isUsageBits && size < 8)) {
                 // we expect the structure to contain at least the size and
                 // version, 8 bytes total
                 ALOGE("b/27207275 (%zu) (%d/%d)", size, int(index), int(code));
@@ -804,8 +785,7 @@
                     } else {
                         err = NOT_ENOUGH_DATA;
                         OMX_U32 declaredSize = *(OMX_U32*)params;
-                        if (code != SET_INTERNAL_OPTION &&
-                                index != (OMX_INDEXTYPE) OMX_IndexParamConsumerUsageBits &&
+                        if (index != (OMX_INDEXTYPE) OMX_IndexParamConsumerUsageBits &&
                                 declaredSize > size) {
                             // the buffer says it's bigger than it actually is
                             ALOGE("b/27207275 (%u/%zu)", declaredSize, size);
@@ -831,15 +811,6 @@
                                     case SET_CONFIG:
                                         err = setConfig(node, index, params, size);
                                         break;
-                                    case SET_INTERNAL_OPTION:
-                                    {
-                                        InternalOptionType type =
-                                            (InternalOptionType)data.readInt32();
-
-                                        err = setInternalOption(node, index, type, params, size);
-                                        break;
-                                    }
-
                                     default:
                                         TRESPASS();
                                 }
@@ -1002,8 +973,10 @@
             android_dataspace dataSpace = (android_dataspace)data.readInt32();
 
             sp<IGraphicBufferProducer> bufferProducer;
+            sp<IGraphicBufferSource> bufferSource;
             MetadataBufferType type = kMetadataBufferTypeInvalid;
-            status_t err = createInputSurface(node, port_index, dataSpace, &bufferProducer, &type);
+            status_t err = createInputSurface(
+                    node, port_index, dataSpace, &bufferProducer, &bufferSource, &type);
 
             if ((err != OK) && (type == kMetadataBufferTypeInvalid)) {
                 android_errorWriteLog(0x534e4554, "26324358");
@@ -1014,6 +987,7 @@
 
             if (err == OK) {
                 reply->writeStrongBinder(IInterface::asBinder(bufferProducer));
+                reply->writeStrongBinder(IInterface::asBinder(bufferSource));
             }
 
             return NO_ERROR;
@@ -1048,13 +1022,14 @@
             sp<IGraphicBufferConsumer> bufferConsumer =
                     interface_cast<IGraphicBufferConsumer>(data.readStrongBinder());
 
+            sp<IGraphicBufferSource> bufferSource;
             MetadataBufferType type = kMetadataBufferTypeInvalid;
 
             status_t err = INVALID_OPERATION;
             if (bufferConsumer == NULL) {
                 ALOGE("b/26392700");
             } else {
-                err = setInputSurface(node, port_index, bufferConsumer, &type);
+                err = setInputSurface(node, port_index, bufferConsumer, &bufferSource, &type);
 
                 if ((err != OK) && (type == kMetadataBufferTypeInvalid)) {
                    android_errorWriteLog(0x534e4554, "26324358");
@@ -1063,18 +1038,9 @@
 
             reply->writeInt32(type);
             reply->writeInt32(err);
-            return NO_ERROR;
-        }
-
-        case SIGNAL_END_OF_INPUT_STREAM:
-        {
-            CHECK_OMX_INTERFACE(IOMX, data, reply);
-
-            node_id node = (node_id)data.readInt32();
-
-            status_t err = signalEndOfInputStream(node);
-            reply->writeInt32(err);
-
+            if (err == OK) {
+                reply->writeStrongBinder(IInterface::asBinder(bufferSource));
+            }
             return NO_ERROR;
         }
 
@@ -1246,10 +1212,12 @@
             data.read(*graphicBuffer);
             OMX_U32 flags = data.readInt32();
             OMX_TICKS timestamp = data.readInt64();
+            OMX_TICKS origTimestamp = data.readInt64();
             bool haveFence = data.readInt32();
             int fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
             reply->writeInt32(emptyGraphicBuffer(
-                    node, buffer, graphicBuffer, flags, timestamp, fenceFd));
+                    node, buffer, graphicBuffer, flags,
+                    timestamp, origTimestamp, fenceFd));
 
             return NO_ERROR;
         }
diff --git a/media/libmedia/aidl/android/IGraphicBufferSource.aidl b/media/libmedia/aidl/android/IGraphicBufferSource.aidl
new file mode 100644
index 0000000..adbb75f
--- /dev/null
+++ b/media/libmedia/aidl/android/IGraphicBufferSource.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android;
+
+/**
+ * Binder interface for controlling a graphic buffer source.
+ *
+ * @hide
+ */
+interface IGraphicBufferSource {
+    void setSuspend(boolean suspend);
+    void setRepeatPreviousFrameDelayUs(long repeatAfterUs);
+    void setMaxTimestampGapUs(long maxGapUs);
+    void setMaxFps(float maxFps);
+    void setTimeLapseConfig(long timePerFrameUs, long timePerCaptureUs);
+    void setStartTimeUs(long startTimeUs);
+    void setColorAspects(int aspects);
+    void setTimeOffsetUs(long timeOffsetsUs);
+    void signalEndOfInputStream();
+}
\ No newline at end of file
diff --git a/media/libmedia/aidl/android/IOMXBufferSource.aidl b/media/libmedia/aidl/android/IOMXBufferSource.aidl
new file mode 100644
index 0000000..a5bf448
--- /dev/null
+++ b/media/libmedia/aidl/android/IOMXBufferSource.aidl
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android;
+
+import android.OMXFenceParcelable;
+
+/**
+ * Binder interface for a buffer source to be used together with an OMX encoder
+ *
+ * @hide
+ */
+interface IOMXBufferSource {
+    /**
+     * This is called when OMX transitions to OMX_StateExecuting, which means
+     * we can start handing it buffers.  If we already have buffers of data
+     * sitting in the BufferQueue, this will send them to the codec.
+     */
+    void onOmxExecuting();
+
+    /**
+     * This is called when OMX transitions to OMX_StateIdle, indicating that
+     * the codec is meant to return all buffers back to the client for them
+     * to be freed. Do NOT submit any more buffers to the component.
+     */
+    void onOmxIdle();
+
+    /**
+     * This is called when OMX transitions to OMX_StateLoaded, indicating that
+     * we are shutting down.
+     */
+    void onOmxLoaded();
+
+    /**
+     * A "codec buffer", i.e. a buffer that can be used to pass data into
+     * the encoder, has been allocated.
+     */
+    void onInputBufferAdded(int bufferID);
+
+    /**
+     * Called from OnEmptyBufferDone. If we have a BQ buffer available,
+     * fill it with a new frame of data; otherwise, just mark it as available.
+     *
+     * fenceParcel contains the fence's fd that the callee should wait on before
+     * using the buffer (or pass on to the user of the buffer, if the user supports
+     * fences). Callee takes ownership of the fence fd even if it fails.
+     */
+    void onInputBufferEmptied(int bufferID, in OMXFenceParcelable fenceParcel);
+}
\ No newline at end of file
diff --git a/media/libmedia/aidl/android/OMXFenceParcelable.aidl b/media/libmedia/aidl/android/OMXFenceParcelable.aidl
new file mode 100644
index 0000000..6d517e8
--- /dev/null
+++ b/media/libmedia/aidl/android/OMXFenceParcelable.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android;
+
+/** @hide */
+parcelable OMXFenceParcelable cpp_header "media/OMXFenceParcelable.h";