IOMX: consolidate createInputSurface APIs
- Create GraphicBufferSource in IOMX regardless of persistency.
- Remove createInputSurface on IOMXNode, only keep setInputSurface
which accepts either a persistent or non-persistent surface.
- Instead of holding a IGraphicBufferConsumer, hold
IGraphicBufferSource across session as the persistent surface.
- Fix up GraphicBufferSource to allow usage across sessions.
GraphicBufferSource itself becomes agnostic to persistency.
- Remove max encoder input buffers profiling code.
bug: 31399200
Change-Id: I15ed52cc64509fd87736372a580abf7b51bf4de7
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
index 68a65f0..3e05532 100644
--- a/include/media/IMediaRecorder.h
+++ b/include/media/IMediaRecorder.h
@@ -28,8 +28,8 @@
}
class ICameraRecordingProxy;
class IMediaRecorderClient;
-class IGraphicBufferConsumer;
class IGraphicBufferProducer;
+struct PersistentSurface;
class IMediaRecorder: public IInterface
{
@@ -60,7 +60,7 @@
virtual status_t init() = 0;
virtual status_t close() = 0;
virtual status_t release() = 0;
- virtual status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface) = 0;
+ virtual status_t setInputSurface(const sp<PersistentSurface>& surface) = 0;
virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() = 0;
};
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index ef01688..311119b 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -19,8 +19,6 @@
#define ANDROID_IOMX_H_
#include <binder/IInterface.h>
-#include <gui/IGraphicBufferProducer.h>
-#include <gui/IGraphicBufferConsumer.h>
#include <ui/GraphicBuffer.h>
#include <utils/List.h>
#include <utils/String8.h>
@@ -34,8 +32,10 @@
namespace android {
+class IGraphicBufferProducer;
class IGraphicBufferSource;
class IMemory;
+class IOMXBufferSource;
class IOMXNode;
class IOMXObserver;
class NativeHandle;
@@ -61,9 +61,9 @@
const char *name, const sp<IOMXObserver> &observer,
sp<IOMXNode> *omxNode) = 0;
- virtual status_t createPersistentInputSurface(
+ virtual status_t createInputSurface(
sp<IGraphicBufferProducer> *bufferProducer,
- sp<IGraphicBufferConsumer> *bufferConsumer) = 0;
+ sp<IGraphicBufferSource> *bufferSource) = 0;
};
class IOMXNode : public IInterface {
@@ -125,21 +125,8 @@
OMX_U32 port_index,
const sp<NativeHandle> &nativeHandle, buffer_id buffer) = 0;
- // This will set *type to resulting metadata buffer type on OMX error (not on binder error) as
- // well as on success.
- virtual status_t createInputSurface(
- OMX_U32 port_index, android_dataspace dataSpace,
- sp<IGraphicBufferProducer> *bufferProducer,
- sp<IGraphicBufferSource> *bufferSource,
- MetadataBufferType *type = NULL) = 0;
-
- // This will set *type to resulting metadata buffer type on OMX error (not on binder error) as
- // well as on success.
virtual status_t setInputSurface(
- OMX_U32 port_index,
- const sp<IGraphicBufferConsumer> &bufferConsumer,
- sp<IGraphicBufferSource> *bufferSource,
- MetadataBufferType *type) = 0;
+ const sp<IOMXBufferSource> &bufferSource) = 0;
// Allocate an opaque buffer as a native handle. If component supports returning native
// handles, those are returned in *native_handle. Otherwise, the allocated buffer is
diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h
index 5195993..59dfd18 100644
--- a/include/media/MediaRecorderBase.h
+++ b/include/media/MediaRecorderBase.h
@@ -25,9 +25,8 @@
namespace android {
class ICameraRecordingProxy;
-class Surface;
-class IGraphicBufferConsumer;
class IGraphicBufferProducer;
+struct PersistentSurface;
struct MediaRecorderBase {
MediaRecorderBase(const String16 &opPackageName)
@@ -59,7 +58,7 @@
virtual status_t reset() = 0;
virtual status_t getMaxAmplitude(int *max) = 0;
virtual status_t dump(int fd, const Vector<String16>& args) const = 0;
- virtual status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface) = 0;
+ virtual status_t setInputSurface(const sp<PersistentSurface>& surface) = 0;
virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() const = 0;
diff --git a/include/media/stagefright/CodecBase.h b/include/media/stagefright/CodecBase.h
index 92a5593..13f82f0 100644
--- a/include/media/stagefright/CodecBase.h
+++ b/include/media/stagefright/CodecBase.h
@@ -36,6 +36,7 @@
class MediaCodecBuffer;
struct PersistentSurface;
+class Surface;
struct CodecBase : public AHandler, /* static */ ColorUtils {
enum {
diff --git a/include/media/stagefright/MediaCodecSource.h b/include/media/stagefright/MediaCodecSource.h
index 18b1955..f9a46a9 100644
--- a/include/media/stagefright/MediaCodecSource.h
+++ b/include/media/stagefright/MediaCodecSource.h
@@ -21,8 +21,7 @@
#include <media/stagefright/foundation/AHandlerReflector.h>
#include <media/stagefright/foundation/Mutexed.h>
#include <media/stagefright/MediaSource.h>
-
-#include <gui/IGraphicBufferConsumer.h>
+#include <media/stagefright/PersistentSurface.h>
namespace android {
@@ -44,7 +43,7 @@
const sp<ALooper> &looper,
const sp<AMessage> &format,
const sp<MediaSource> &source,
- const sp<IGraphicBufferConsumer> &consumer = NULL,
+ const sp<PersistentSurface> &persistentSurface = NULL,
uint32_t flags = 0);
bool isVideo() const { return mIsVideo; }
@@ -88,7 +87,7 @@
const sp<ALooper> &looper,
const sp<AMessage> &outputFormat,
const sp<MediaSource> &source,
- const sp<IGraphicBufferConsumer> &consumer,
+ const sp<PersistentSurface> &persistentSurface,
uint32_t flags = 0);
status_t onStart(MetaData *params);
@@ -121,7 +120,7 @@
int32_t mEncoderDataSpace;
sp<AMessage> mEncoderActivityNotify;
sp<IGraphicBufferProducer> mGraphicBufferProducer;
- sp<IGraphicBufferConsumer> mGraphicBufferConsumer;
+ sp<PersistentSurface> mPersistentSurface;
List<MediaBuffer *> mInputBufferQueue;
List<size_t> mAvailEncoderInputIndices;
List<int64_t> mDecodingTimeQueue; // decoding time (us) for video
diff --git a/include/media/stagefright/PersistentSurface.h b/include/media/stagefright/PersistentSurface.h
index a35b9f1..d8b75a2 100644
--- a/include/media/stagefright/PersistentSurface.h
+++ b/include/media/stagefright/PersistentSurface.h
@@ -19,29 +19,46 @@
#define PERSISTENT_SURFACE_H_
#include <gui/IGraphicBufferProducer.h>
-#include <gui/IGraphicBufferConsumer.h>
+#include <android/IGraphicBufferSource.h>
#include <media/stagefright/foundation/ABase.h>
+#include <binder/Parcel.h>
namespace android {
struct PersistentSurface : public RefBase {
+ PersistentSurface() {}
+
PersistentSurface(
const sp<IGraphicBufferProducer>& bufferProducer,
- const sp<IGraphicBufferConsumer>& bufferConsumer) :
+ const sp<IGraphicBufferSource>& bufferSource) :
mBufferProducer(bufferProducer),
- mBufferConsumer(bufferConsumer) { }
+ mBufferSource(bufferSource) { }
sp<IGraphicBufferProducer> getBufferProducer() const {
return mBufferProducer;
}
- sp<IGraphicBufferConsumer> getBufferConsumer() const {
- return mBufferConsumer;
+ sp<IGraphicBufferSource> getBufferSource() const {
+ return mBufferSource;
+ }
+
+ status_t writeToParcel(Parcel *parcel) const {
+ parcel->writeStrongBinder(IInterface::asBinder(mBufferProducer));
+ parcel->writeStrongBinder(IInterface::asBinder(mBufferSource));
+ return NO_ERROR;
+ }
+
+ status_t readFromParcel(const Parcel *parcel) {
+ mBufferProducer = interface_cast<IGraphicBufferProducer>(
+ parcel->readStrongBinder());
+ mBufferSource = interface_cast<IGraphicBufferSource>(
+ parcel->readStrongBinder());
+ return NO_ERROR;
}
private:
- const sp<IGraphicBufferProducer> mBufferProducer;
- const sp<IGraphicBufferConsumer> mBufferConsumer;
+ sp<IGraphicBufferProducer> mBufferProducer;
+ sp<IGraphicBufferSource> mBufferSource;
DISALLOW_EVIL_CONSTRUCTORS(PersistentSurface);
};
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 08b3af0..0b1bb2b 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -93,9 +93,14 @@
$(TOP)/frameworks/native/include/media/openmax \
$(TOP)/frameworks/av/include/media/ \
$(TOP)/frameworks/av/media/libstagefright \
+ $(TOP)/frameworks/av/media/libmedia/aidl \
$(call include-path-for, audio-effects) \
$(call include-path-for, audio-utils)
+LOCAL_EXPORT_C_INCLUDE_DIRS := \
+ frameworks/av/include/media \
+ frameworks/av/media/libmedia/aidl
+
LOCAL_CFLAGS += -Werror -Wno-error=deprecated-declarations -Wall
LOCAL_SANITIZE := unsigned-integer-overflow signed-integer-overflow
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index a6860e2..5599830 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -29,6 +29,7 @@
#include <media/IMediaRecorder.h>
#include <gui/Surface.h>
#include <gui/IGraphicBufferProducer.h>
+#include <media/stagefright/PersistentSurface.h>
namespace android {
@@ -79,12 +80,12 @@
return reply.readInt32();
}
- status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface)
+ status_t setInputSurface(const sp<PersistentSurface>& surface)
{
ALOGV("setInputSurface(%p)", surface.get());
Parcel data, reply;
data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
- data.writeStrongBinder(IInterface::asBinder(surface));
+ surface->writeToParcel(&data);
remote()->transact(SET_INPUT_SURFACE, data, &reply);
return reply.readInt32();
}
@@ -490,8 +491,8 @@
case SET_INPUT_SURFACE: {
ALOGV("SET_INPUT_SURFACE");
CHECK_INTERFACE(IMediaRecorder, data, reply);
- sp<IGraphicBufferConsumer> surface = interface_cast<IGraphicBufferConsumer>(
- data.readStrongBinder());
+ sp<PersistentSurface> surface = new PersistentSurface();
+ surface->readFromParcel(&data);
reply->writeInt32(setInputSurface(surface));
return NO_ERROR;
} break;
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index 9360777..1901d8c 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -27,7 +27,9 @@
#include <media/openmax/OMX_IndexExt.h>
#include <utils/NativeHandle.h>
+#include <gui/IGraphicBufferProducer.h>
#include <android/IGraphicBufferSource.h>
+#include <android/IOMXBufferSource.h>
namespace android {
@@ -45,7 +47,6 @@
USE_BUFFER,
USE_GRAPHIC_BUFFER,
CREATE_INPUT_SURFACE,
- CREATE_PERSISTENT_INPUT_SURFACE,
SET_INPUT_SURFACE,
STORE_META_DATA_IN_BUFFERS,
PREPARE_FOR_ADAPTIVE_PLAYBACK,
@@ -111,13 +112,13 @@
return err;
}
- virtual status_t createPersistentInputSurface(
+ virtual status_t createInputSurface(
sp<IGraphicBufferProducer> *bufferProducer,
- sp<IGraphicBufferConsumer> *bufferConsumer) {
+ sp<IGraphicBufferSource> *bufferSource) {
Parcel data, reply;
status_t err;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- err = remote()->transact(CREATE_PERSISTENT_INPUT_SURFACE, data, &reply);
+ err = remote()->transact(CREATE_INPUT_SURFACE, data, &reply);
if (err != OK) {
ALOGW("binder transaction failed: %d", err);
return err;
@@ -130,7 +131,7 @@
*bufferProducer = IGraphicBufferProducer::asInterface(
reply.readStrongBinder());
- *bufferConsumer = IGraphicBufferConsumer::asInterface(
+ *bufferSource = IGraphicBufferSource::asInterface(
reply.readStrongBinder());
return err;
@@ -328,72 +329,21 @@
return err;
}
- virtual status_t createInputSurface(
- OMX_U32 port_index, android_dataspace dataSpace,
- sp<IGraphicBufferProducer> *bufferProducer,
- sp<IGraphicBufferSource> *bufferSource,
- MetadataBufferType *type) {
- Parcel data, reply;
- status_t err;
- data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
- data.writeInt32(port_index);
- data.writeInt32(dataSpace);
- err = remote()->transact(CREATE_INPUT_SURFACE, data, &reply);
- if (err != OK) {
- ALOGW("binder transaction failed: %d", err);
- return err;
- }
-
- // read type even if createInputSurface failed
- int negotiatedType = reply.readInt32();
- if (type != NULL) {
- *type = (MetadataBufferType)negotiatedType;
- }
-
- err = reply.readInt32();
- if (err != OK) {
- return err;
- }
-
- *bufferProducer = IGraphicBufferProducer::asInterface(
- reply.readStrongBinder());
- *bufferSource = IGraphicBufferSource::asInterface(
- reply.readStrongBinder());
-
- return err;
- }
-
virtual status_t setInputSurface(
- OMX_U32 port_index,
- const sp<IGraphicBufferConsumer> &bufferConsumer,
- sp<IGraphicBufferSource> *bufferSource,
- MetadataBufferType *type) {
+ const sp<IOMXBufferSource> &bufferSource) {
Parcel data, reply;
data.writeInterfaceToken(IOMXNode::getInterfaceDescriptor());
- status_t err;
- data.writeInt32(port_index);
- data.writeStrongBinder(IInterface::asBinder(bufferConsumer));
- err = remote()->transact(SET_INPUT_SURFACE, data, &reply);
+ data.writeStrongBinder(IInterface::asBinder(bufferSource));
+
+ status_t err = remote()->transact(SET_INPUT_SURFACE, data, &reply);
if (err != OK) {
ALOGW("binder transaction failed: %d", err);
return err;
}
- // read type even if setInputSurface failed
- int negotiatedType = reply.readInt32();
- if (type != NULL) {
- *type = (MetadataBufferType)negotiatedType;
- }
-
err = reply.readInt32();
- if (err != OK) {
- return err;
- }
-
- *bufferSource = IGraphicBufferSource::asInterface(
- reply.readStrongBinder());
return err;
}
@@ -651,20 +601,19 @@
return NO_ERROR;
}
- case CREATE_PERSISTENT_INPUT_SURFACE:
+ case CREATE_INPUT_SURFACE:
{
CHECK_OMX_INTERFACE(IOMX, data, reply);
sp<IGraphicBufferProducer> bufferProducer;
- sp<IGraphicBufferConsumer> bufferConsumer;
- status_t err = createPersistentInputSurface(
- &bufferProducer, &bufferConsumer);
+ sp<IGraphicBufferSource> bufferSource;
+ status_t err = createInputSurface(&bufferProducer, &bufferSource);
reply->writeInt32(err);
if (err == OK) {
reply->writeStrongBinder(IInterface::asBinder(bufferProducer));
- reply->writeStrongBinder(IInterface::asBinder(bufferConsumer));
+ reply->writeStrongBinder(IInterface::asBinder(bufferSource));
}
return NO_ERROR;
@@ -897,62 +846,16 @@
return NO_ERROR;
}
- case CREATE_INPUT_SURFACE:
- {
- CHECK_OMX_INTERFACE(IOMXNode, data, reply);
-
- OMX_U32 port_index = data.readInt32();
- android_dataspace dataSpace = (android_dataspace)data.readInt32();
-
- sp<IGraphicBufferProducer> bufferProducer;
- sp<IGraphicBufferSource> bufferSource;
- MetadataBufferType type = kMetadataBufferTypeInvalid;
- status_t err = createInputSurface(
- port_index, dataSpace, &bufferProducer, &bufferSource, &type);
-
- if ((err != OK) && (type == kMetadataBufferTypeInvalid)) {
- android_errorWriteLog(0x534e4554, "26324358");
- }
-
- reply->writeInt32(type);
- reply->writeInt32(err);
-
- if (err == OK) {
- reply->writeStrongBinder(IInterface::asBinder(bufferProducer));
- reply->writeStrongBinder(IInterface::asBinder(bufferSource));
- }
-
- return NO_ERROR;
- }
-
case SET_INPUT_SURFACE:
{
CHECK_OMX_INTERFACE(IOMXNode, data, reply);
- OMX_U32 port_index = data.readInt32();
+ sp<IOMXBufferSource> bufferSource =
+ interface_cast<IOMXBufferSource>(data.readStrongBinder());
- 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(port_index, bufferConsumer, &bufferSource, &type);
-
- if ((err != OK) && (type == kMetadataBufferTypeInvalid)) {
- android_errorWriteLog(0x534e4554, "26324358");
- }
- }
-
- reply->writeInt32(type);
+ status_t err = setInputSurface(bufferSource);
reply->writeInt32(err);
- if (err == OK) {
- reply->writeStrongBinder(IInterface::asBinder(bufferSource));
- }
+
return NO_ERROR;
}
diff --git a/media/libmedia/aidl/android/IGraphicBufferSource.aidl b/media/libmedia/aidl/android/IGraphicBufferSource.aidl
index adbb75f..e9bf739 100644
--- a/media/libmedia/aidl/android/IGraphicBufferSource.aidl
+++ b/media/libmedia/aidl/android/IGraphicBufferSource.aidl
@@ -16,12 +16,15 @@
package android;
+import android.IOMXNode;
+
/**
* Binder interface for controlling a graphic buffer source.
*
* @hide
*/
interface IGraphicBufferSource {
+ void configure(IOMXNode omxNode, int dataSpace);
void setSuspend(boolean suspend);
void setRepeatPreviousFrameDelayUs(long repeatAfterUs);
void setMaxTimestampGapUs(long maxGapUs);
diff --git a/media/libmedia/aidl/android/IOMXNode.aidl b/media/libmedia/aidl/android/IOMXNode.aidl
new file mode 100644
index 0000000..ec87fd2
--- /dev/null
+++ b/media/libmedia/aidl/android/IOMXNode.aidl
@@ -0,0 +1,22 @@
+/*
+ * 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 */
+interface IOMXNode {
+ // Stub for manual implementation
+}
diff --git a/media/libmedia/aidl/android/IOMXNode.h b/media/libmedia/aidl/android/IOMXNode.h
new file mode 100644
index 0000000..7b17614
--- /dev/null
+++ b/media/libmedia/aidl/android/IOMXNode.h
@@ -0,0 +1,17 @@
+/*
+ * 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.
+ */
+
+#include <media/IOMX.h>
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 59c077a..6eb208c 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -361,7 +361,7 @@
return INVALID_OPERATION;
}
- return mMediaRecorder->setInputSurface(surface->getBufferConsumer());
+ return mMediaRecorder->setInputSurface(surface);
}
status_t MediaRecorder::setVideoFrameRate(int frames_per_second)
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index d011d70..94ceae4 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -52,7 +52,7 @@
return ok;
}
-status_t MediaRecorderClient::setInputSurface(const sp<IGraphicBufferConsumer>& surface)
+status_t MediaRecorderClient::setInputSurface(const sp<PersistentSurface>& surface)
{
ALOGV("setInputSurface");
Mutex::Autolock lock(mLock);
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index eceb653..12656cf 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -25,7 +25,6 @@
class MediaRecorderBase;
class MediaPlayerService;
class ICameraRecordingProxy;
-class IGraphicBufferProducer;
class MediaRecorderClient : public BnMediaRecorder
{
@@ -73,7 +72,7 @@
virtual status_t close();
virtual status_t release();
virtual status_t dump(int fd, const Vector<String16>& args);
- virtual status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface);
+ virtual status_t setInputSurface(const sp<PersistentSurface>& surface);
virtual sp<IGraphicBufferProducer> querySurfaceMediaSource();
private:
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index a748b46..279bc86 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -45,6 +45,7 @@
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/MediaCodecSource.h>
+#include <media/stagefright/PersistentSurface.h>
#include <media/MediaProfiles.h>
#include <camera/CameraParameters.h>
@@ -248,7 +249,7 @@
}
status_t StagefrightRecorder::setInputSurface(
- const sp<IGraphicBufferConsumer>& surface) {
+ const sp<PersistentSurface>& surface) {
mPersistentSurface = surface;
return OK;
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 4dbd039..4c2e65c 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -38,9 +38,6 @@
class MetaData;
struct AudioSource;
class MediaProfiles;
-class IGraphicBufferConsumer;
-class IGraphicBufferProducer;
-class SurfaceMediaSource;
struct ALooper;
struct StagefrightRecorder : public MediaRecorderBase {
@@ -57,7 +54,7 @@
virtual status_t setVideoFrameRate(int frames_per_second);
virtual status_t setCamera(const sp<hardware::ICamera>& camera, const sp<ICameraRecordingProxy>& proxy);
virtual status_t setPreviewSurface(const sp<IGraphicBufferProducer>& surface);
- virtual status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface);
+ virtual status_t setInputSurface(const sp<PersistentSurface>& surface);
virtual status_t setOutputFile(int fd, int64_t offset, int64_t length);
virtual status_t setParameters(const String8 ¶ms);
virtual status_t setListener(const sp<IMediaRecorderClient> &listener);
@@ -78,7 +75,7 @@
sp<hardware::ICamera> mCamera;
sp<ICameraRecordingProxy> mCameraProxy;
sp<IGraphicBufferProducer> mPreviewSurface;
- sp<IGraphicBufferConsumer> mPersistentSurface;
+ sp<PersistentSurface> mPersistentSurface;
sp<IMediaRecorderClient> mListener;
String16 mClientName;
uid_t mClientUid;
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 93d4199..478de35 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -56,8 +56,6 @@
#include "include/SharedMemoryBuffer.h"
#include "omx/OMXUtils.h"
-#include <android/IGraphicBufferSource.h>
-
namespace android {
using binder::Status;
@@ -6559,7 +6557,25 @@
}
status_t ACodec::LoadedState::setupInputSurface() {
- status_t err = OK;
+ if (mCodec->mGraphicBufferSource == NULL) {
+ return BAD_VALUE;
+ }
+
+ android_dataspace dataSpace;
+ status_t err =
+ mCodec->setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(&dataSpace);
+ if (err != OK) {
+ ALOGE("Failed to get default data space");
+ return err;
+ }
+
+ err = statusFromBinderStatus(
+ mCodec->mGraphicBufferSource->configure(mCodec->mOMXNode, dataSpace));
+ if (err != OK) {
+ ALOGE("[%s] Unable to configure for node (err %d)",
+ mCodec->mComponentName.c_str(), err);
+ return err;
+ }
if (mCodec->mRepeatFrameDelayUs > 0ll) {
err = statusFromBinderStatus(
@@ -6655,30 +6671,20 @@
sp<AMessage> notify = mCodec->mNotify->dup();
notify->setInt32("what", CodecBase::kWhatInputSurfaceCreated);
- android_dataspace dataSpace;
- status_t err =
- mCodec->setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(&dataSpace);
- notify->setMessage("input-format", mCodec->mInputFormat);
- notify->setMessage("output-format", mCodec->mOutputFormat);
-
sp<IGraphicBufferProducer> bufferProducer;
- if (err == OK) {
- mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
- err = mCodec->mOMXNode->createInputSurface(
- mCodec->kPortIndexInput, dataSpace,
- &bufferProducer, &mCodec->mGraphicBufferSource,
- &mCodec->mInputMetadataType);
- // framework uses ANW buffers internally instead of gralloc handles
- if (mCodec->mInputMetadataType == kMetadataBufferTypeGrallocSource) {
- mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
- }
- }
+ status_t err = mCodec->mOMX->createInputSurface(
+ &bufferProducer, &mCodec->mGraphicBufferSource);
if (err == OK) {
err = setupInputSurface();
}
if (err == OK) {
+ mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
+
+ notify->setMessage("input-format", mCodec->mInputFormat);
+ notify->setMessage("output-format", mCodec->mOutputFormat);
+
notify->setObject("input-surface",
new BufferProducerWrapper(bufferProducer));
} else {
@@ -6702,32 +6708,16 @@
sp<RefBase> obj;
CHECK(msg->findObject("input-surface", &obj));
sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get());
+ mCodec->mGraphicBufferSource = surface->getBufferSource();
- android_dataspace dataSpace;
- status_t err =
- mCodec->setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(&dataSpace);
- notify->setMessage("input-format", mCodec->mInputFormat);
- notify->setMessage("output-format", mCodec->mOutputFormat);
+ status_t err = setupInputSurface();
if (err == OK) {
mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
- err = mCodec->mOMXNode->setInputSurface(
- mCodec->kPortIndexInput,
- surface->getBufferConsumer(),
- &mCodec->mGraphicBufferSource,
- &mCodec->mInputMetadataType);
- // framework uses ANW buffers internally instead of gralloc handles
- if (mCodec->mInputMetadataType == kMetadataBufferTypeGrallocSource) {
- mCodec->mInputMetadataType = kMetadataBufferTypeANWBuffer;
- }
- }
- if (err == OK) {
- surface->getBufferConsumer()->setDefaultBufferDataSpace(dataSpace);
- err = setupInputSurface();
- }
-
- if (err != OK) {
+ notify->setMessage("input-format", mCodec->mInputFormat);
+ notify->setMessage("output-format", mCodec->mOutputFormat);
+ } else {
// Can't use mCodec->signalError() here -- MediaCodec won't forward
// the error through because it's in the "configured" state. We
// send a kWhatInputSurfaceAccepted with an error value instead.
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index fc9f644..465ebc8 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -213,50 +213,24 @@
// static
sp<PersistentSurface> MediaCodec::CreatePersistentInputSurface() {
OMXClient client;
- CHECK_EQ(client.connect(), (status_t)OK);
+ if (client.connect() != OK) {
+ ALOGE("Failed to connect to OMX to create persistent input surface.");
+ return NULL;
+ }
+
sp<IOMX> omx = client.interface();
- const sp<IMediaCodecList> mediaCodecList = MediaCodecList::getInstance();
- if (mediaCodecList == NULL) {
- ALOGE("Failed to obtain MediaCodecList!");
- return NULL; // if called from Java should raise IOException
- }
-
- AString tmp;
- sp<AMessage> globalSettings = mediaCodecList->getGlobalSettings();
- if (globalSettings == NULL || !globalSettings->findString(
- kMaxEncoderInputBuffers, &tmp)) {
- ALOGE("Failed to get encoder input buffer count!");
- return NULL;
- }
-
- int32_t bufferCount = strtol(tmp.c_str(), NULL, 10);
- if (bufferCount <= 0
- || bufferCount > BufferQueue::MAX_MAX_ACQUIRED_BUFFERS) {
- ALOGE("Encoder input buffer count is invalid!");
- return NULL;
- }
-
sp<IGraphicBufferProducer> bufferProducer;
- sp<IGraphicBufferConsumer> bufferConsumer;
+ sp<IGraphicBufferSource> bufferSource;
- status_t err = omx->createPersistentInputSurface(
- &bufferProducer, &bufferConsumer);
+ status_t err = omx->createInputSurface(&bufferProducer, &bufferSource);
if (err != OK) {
ALOGE("Failed to create persistent input surface.");
return NULL;
}
- err = bufferConsumer->setMaxAcquiredBufferCount(bufferCount);
-
- if (err != NO_ERROR) {
- ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
- bufferCount, err);
- return NULL;
- }
-
- return new PersistentSurface(bufferProducer, bufferConsumer);
+ return new PersistentSurface(bufferProducer, bufferSource);
}
MediaCodec::MediaCodec(const sp<ALooper> &looper, pid_t pid)
@@ -1311,6 +1285,8 @@
status_t err = NO_ERROR;
sp<AMessage> response = new AMessage();
if (!msg->findInt32("err", &err)) {
+ CHECK(msg->findMessage("input-format", &mInputFormat));
+ CHECK(msg->findMessage("output-format", &mOutputFormat));
mHaveInputSurface = true;
} else {
response->setInt32("err", err);
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index 1f869b1..93643c2 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -44,8 +44,6 @@
namespace android {
-const char *kMaxEncoderInputBuffers = "max-video-encoder-input-buffers";
-
static Mutex sInitMutex;
static bool parseBoolean(const char *s) {
diff --git a/media/libstagefright/MediaCodecListOverrides.cpp b/media/libstagefright/MediaCodecListOverrides.cpp
index 33795f3..095fc6a 100644
--- a/media/libstagefright/MediaCodecListOverrides.cpp
+++ b/media/libstagefright/MediaCodecListOverrides.cpp
@@ -127,61 +127,6 @@
return format;
}
-static size_t doProfileEncoderInputBuffers(
- const AString &name, const AString &mime, const sp<MediaCodecInfo::Capabilities> &caps) {
- ALOGV("doProfileEncoderInputBuffers: name %s, mime %s", name.c_str(), mime.c_str());
-
- sp<AMessage> format = getMeasureFormat(true /* isEncoder */, mime, caps);
- if (format == NULL) {
- return 0;
- }
-
- format->setInt32("color-format", OMX_COLOR_FormatAndroidOpaque);
- ALOGV("doProfileEncoderInputBuffers: format %s", format->debugString().c_str());
-
- status_t err = OK;
- sp<ALooper> looper = new ALooper;
- looper->setName("MediaCodec_looper");
- looper->start(
- false /* runOnCallingThread */, false /* canCallJava */, ANDROID_PRIORITY_AUDIO);
-
- sp<MediaCodec> codec = MediaCodec::CreateByComponentName(looper, name.c_str(), &err);
- if (err != OK) {
- ALOGE("Failed to create codec: %s", name.c_str());
- return 0;
- }
-
- err = codec->configure(format, NULL, NULL, MediaCodec::CONFIGURE_FLAG_ENCODE);
- if (err != OK) {
- ALOGE("Failed to configure codec: %s with mime: %s", name.c_str(), mime.c_str());
- codec->release();
- return 0;
- }
-
- sp<IGraphicBufferProducer> bufferProducer;
- err = codec->createInputSurface(&bufferProducer);
- if (err != OK) {
- ALOGE("Failed to create surface: %s with mime: %s", name.c_str(), mime.c_str());
- codec->release();
- return 0;
- }
-
- int minUndequeued = 0;
- err = bufferProducer->query(
- NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeued);
- if (err != OK) {
- ALOGE("Failed to query NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS");
- minUndequeued = 0;
- }
-
- err = codec->release();
- if (err != OK) {
- ALOGW("Failed to release codec: %s with mime: %s", name.c_str(), mime.c_str());
- }
-
- return minUndequeued;
-}
-
static size_t doProfileCodecs(
bool isEncoder, const AString &name, const AString &mime, const sp<MediaCodecInfo::Capabilities> &caps) {
sp<AMessage> format = getMeasureFormat(isEncoder, mime, caps);
@@ -276,7 +221,6 @@
bool forceToMeasure) {
KeyedVector<AString, sp<MediaCodecInfo::Capabilities>> codecsNeedMeasure;
AString supportMultipleSecureCodecs = "true";
- size_t maxEncoderInputBuffers = 0;
for (size_t i = 0; i < infos.size(); ++i) {
const sp<MediaCodecInfo> info = infos[i];
AString name = info->getCodecName();
@@ -319,21 +263,9 @@
supportMultipleSecureCodecs = "false";
}
}
- if (info->isEncoder() && mimes[i].startsWith("video/")) {
- size_t encoderInputBuffers =
- doProfileEncoderInputBuffers(name, mimes[i], caps);
- if (encoderInputBuffers > maxEncoderInputBuffers) {
- maxEncoderInputBuffers = encoderInputBuffers;
- }
- }
}
}
}
- if (maxEncoderInputBuffers > 0) {
- char tmp[32];
- sprintf(tmp, "%zu", maxEncoderInputBuffers);
- global_results->add(kMaxEncoderInputBuffers, tmp);
- }
global_results->add(kPolicySupportsMultipleSecureCodecs, supportMultipleSecureCodecs);
}
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 8391d76..de4d06f 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -20,7 +20,6 @@
#include <inttypes.h>
-#include <gui/IGraphicBufferConsumer.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/Surface.h>
#include <media/ICrypto.h>
@@ -36,7 +35,6 @@
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h>
-#include <media/stagefright/PersistentSurface.h>
#include <media/stagefright/Utils.h>
namespace android {
@@ -326,10 +324,10 @@
const sp<ALooper> &looper,
const sp<AMessage> &format,
const sp<MediaSource> &source,
- const sp<IGraphicBufferConsumer> &consumer,
+ const sp<PersistentSurface> &persistentSurface,
uint32_t flags) {
- sp<MediaCodecSource> mediaSource =
- new MediaCodecSource(looper, format, source, consumer, flags);
+ sp<MediaCodecSource> mediaSource = new MediaCodecSource(
+ looper, format, source, persistentSurface, flags);
if (mediaSource->init() == OK) {
return mediaSource;
@@ -405,7 +403,7 @@
const sp<ALooper> &looper,
const sp<AMessage> &outputFormat,
const sp<MediaSource> &source,
- const sp<IGraphicBufferConsumer> &consumer,
+ const sp<PersistentSurface> &persistentSurface,
uint32_t flags)
: mLooper(looper),
mOutputFormat(outputFormat),
@@ -418,7 +416,7 @@
mSetEncoderFormat(false),
mEncoderFormat(0),
mEncoderDataSpace(0),
- mGraphicBufferConsumer(consumer),
+ mPersistentSurface(persistentSurface),
mInputBufferTimeOffsetUs(0),
mFirstSampleSystemTimeUs(-1ll),
mPausePending(false),
@@ -515,12 +513,11 @@
if (mFlags & FLAG_USE_SURFACE_INPUT) {
CHECK(mIsVideo);
- if (mGraphicBufferConsumer != NULL) {
+ if (mPersistentSurface != NULL) {
// When using persistent surface, we are only interested in the
// consumer, but have to use PersistentSurface as a wrapper to
// pass consumer over messages (similar to BufferProducerWrapper)
- err = mEncoder->setInputSurface(
- new PersistentSurface(NULL, mGraphicBufferConsumer));
+ err = mEncoder->setInputSurface(mPersistentSurface);
} else {
err = mEncoder->createInputSurface(&mGraphicBufferProducer);
}
diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h
index 2e62806..9edd0de 100644
--- a/media/libstagefright/include/OMX.h
+++ b/media/libstagefright/include/OMX.h
@@ -37,9 +37,9 @@
const char *name, const sp<IOMXObserver> &observer,
sp<IOMXNode> *omxNode);
- virtual status_t createPersistentInputSurface(
+ virtual status_t createInputSurface(
sp<IGraphicBufferProducer> *bufferProducer,
- sp<IGraphicBufferConsumer> *bufferConsumer);
+ sp<IGraphicBufferSource> *bufferSource);
virtual void binderDied(const wp<IBinder> &the_late_who);
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index 30d0b75..d911508 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -25,7 +25,6 @@
#include <utils/threads.h>
namespace android {
-class IGraphicBufferSource;
class IOMXBufferSource;
class IOMXObserver;
struct OMXMaster;
@@ -81,21 +80,8 @@
OMX_U32 portIndex, const sp<NativeHandle> &nativeHandle,
OMX::buffer_id buffer);
- status_t createInputSurface(
- OMX_U32 portIndex, android_dataspace dataSpace,
- sp<IGraphicBufferProducer> *bufferProducer,
- sp<IGraphicBufferSource> *bufferSource,
- MetadataBufferType *type);
-
- static status_t createPersistentInputSurface(
- sp<IGraphicBufferProducer> *bufferProducer,
- sp<IGraphicBufferConsumer> *bufferConsumer);
-
status_t setInputSurface(
- OMX_U32 portIndex,
- const sp<IGraphicBufferConsumer> &bufferConsumer,
- sp<IGraphicBufferSource> *bufferSource,
- MetadataBufferType *type);
+ const sp<IOMXBufferSource> &bufferSource);
status_t allocateSecureBuffer(
OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer,
@@ -252,12 +238,6 @@
OMX_U32 portIndex, const sp<GraphicBuffer> &graphicBuffer,
OMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header);
- status_t createGraphicBufferSource(
- OMX_U32 portIndex, android_dataspace dataSpace,
- const sp<IGraphicBufferConsumer> &bufferConsumer,
- sp<IGraphicBufferProducer> *bufferProducer,
- sp<IGraphicBufferSource> *bufferSource,
- MetadataBufferType *type);
sp<IOMXBufferSource> getBufferSource();
void setBufferSource(const sp<IOMXBufferSource> &bufferSource);
// Called when omx_message::FILL_BUFFER_DONE is received. (Currently the
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index 25bc41c..afb8173 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -31,93 +31,22 @@
#include <ui/GraphicBuffer.h>
#include <gui/BufferItem.h>
#include <HardwareAPI.h>
+#include "omx/OMXUtils.h"
+#include <OMX_Component.h>
+#include <OMX_IndexExt.h>
#include <inttypes.h>
#include "FrameDropper.h"
namespace android {
-GraphicBufferSource::PersistentProxyListener::PersistentProxyListener(
- const wp<IGraphicBufferConsumer> &consumer,
- const wp<ConsumerListener>& consumerListener) :
- mConsumerListener(consumerListener),
- mConsumer(consumer) {}
+static const OMX_U32 kPortIndexInput = 0;
-GraphicBufferSource::PersistentProxyListener::~PersistentProxyListener() {}
-
-void GraphicBufferSource::PersistentProxyListener::onFrameAvailable(
- const BufferItem& item) {
- sp<ConsumerListener> listener(mConsumerListener.promote());
- if (listener != NULL) {
- listener->onFrameAvailable(item);
- } else {
- sp<IGraphicBufferConsumer> consumer(mConsumer.promote());
- if (consumer == NULL) {
- return;
- }
- BufferItem bi;
- status_t err = consumer->acquireBuffer(&bi, 0);
- if (err != OK) {
- ALOGE("PersistentProxyListener: acquireBuffer failed (%d)", err);
- return;
- }
-
- err = consumer->detachBuffer(bi.mSlot);
- if (err != OK) {
- ALOGE("PersistentProxyListener: detachBuffer failed (%d)", err);
- return;
- }
-
- err = consumer->attachBuffer(&bi.mSlot, bi.mGraphicBuffer);
- if (err != OK) {
- ALOGE("PersistentProxyListener: attachBuffer failed (%d)", err);
- return;
- }
-
- err = consumer->releaseBuffer(bi.mSlot, 0,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, bi.mFence);
- if (err != OK) {
- ALOGE("PersistentProxyListener: releaseBuffer failed (%d)", err);
- }
- }
-}
-
-void GraphicBufferSource::PersistentProxyListener::onFrameReplaced(
- const BufferItem& item) {
- sp<ConsumerListener> listener(mConsumerListener.promote());
- if (listener != NULL) {
- listener->onFrameReplaced(item);
- }
-}
-
-void GraphicBufferSource::PersistentProxyListener::onBuffersReleased() {
- sp<ConsumerListener> listener(mConsumerListener.promote());
- if (listener != NULL) {
- listener->onBuffersReleased();
- }
-}
-
-void GraphicBufferSource::PersistentProxyListener::onSidebandStreamChanged() {
- sp<ConsumerListener> listener(mConsumerListener.promote());
- if (listener != NULL) {
- listener->onSidebandStreamChanged();
- }
-}
-
-GraphicBufferSource::GraphicBufferSource(
- const sp<IOMXNode> &omxNode,
- uint32_t bufferWidth,
- uint32_t bufferHeight,
- uint32_t bufferCount,
- uint32_t consumerUsage,
- const sp<IGraphicBufferConsumer> &consumer) :
+GraphicBufferSource::GraphicBufferSource() :
mInitCheck(UNKNOWN_ERROR),
- mOMXNode(omxNode),
mExecuting(false),
mSuspended(false),
mLastDataSpace(HAL_DATASPACE_UNKNOWN),
- mIsPersistent(false),
- mConsumer(consumer),
mNumFramesAvailable(0),
mNumBufferAcquired(0),
mEndOfStream(false),
@@ -129,6 +58,7 @@
mRepeatAfterUs(-1ll),
mRepeatLastFrameGeneration(0),
mRepeatLastFrameTimestamp(-1ll),
+ mRepeatLastFrameCount(0),
mLatestBufferId(-1),
mLatestBufferFrameNum(0),
mLatestBufferFence(Fence::NO_FENCE),
@@ -138,48 +68,21 @@
mPrevCaptureUs(-1ll),
mPrevFrameUs(-1ll),
mInputBufferTimeOffsetUs(0ll) {
+ ALOGV("GraphicBufferSource");
- ALOGV("GraphicBufferSource w=%u h=%u c=%u",
- bufferWidth, bufferHeight, bufferCount);
+ String8 name("GraphicBufferSource");
- if (bufferWidth == 0 || bufferHeight == 0) {
- ALOGE("Invalid dimensions %ux%u", bufferWidth, bufferHeight);
- mInitCheck = BAD_VALUE;
- return;
- }
+ BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+ mConsumer->setConsumerName(name);
- if (mConsumer == NULL) {
- String8 name("GraphicBufferSource");
-
- BufferQueue::createBufferQueue(&mProducer, &mConsumer);
- mConsumer->setConsumerName(name);
-
- // use consumer usage bits queried from encoder, but always add HW_VIDEO_ENCODER
- // for backward compatibility.
- consumerUsage |= GRALLOC_USAGE_HW_VIDEO_ENCODER;
- mConsumer->setConsumerUsageBits(consumerUsage);
-
- mInitCheck = mConsumer->setMaxAcquiredBufferCount(bufferCount);
- if (mInitCheck != NO_ERROR) {
- ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
- bufferCount, mInitCheck);
- return;
- }
- } else {
- mIsPersistent = true;
- }
- mConsumer->setDefaultBufferSize(bufferWidth, bufferHeight);
// Note that we can't create an sp<...>(this) in a ctor that will not keep a
// reference once the ctor ends, as that would cause the refcount of 'this'
// dropping to 0 at the end of the ctor. Since all we need is a wp<...>
// that's what we create.
- wp<BufferQueue::ConsumerListener> listener = static_cast<BufferQueue::ConsumerListener*>(this);
- sp<IConsumerListener> proxy;
- if (!mIsPersistent) {
- proxy = new BufferQueue::ProxyConsumerListener(listener);
- } else {
- proxy = new PersistentProxyListener(mConsumer, listener);
- }
+ wp<BufferQueue::ConsumerListener> listener =
+ static_cast<BufferQueue::ConsumerListener*>(this);
+ sp<IConsumerListener> proxy =
+ new BufferQueue::ProxyConsumerListener(listener);
mInitCheck = mConsumer->consumerConnect(proxy, false);
if (mInitCheck != NO_ERROR) {
@@ -194,15 +97,14 @@
}
GraphicBufferSource::~GraphicBufferSource() {
+ ALOGV("~GraphicBufferSource");
if (mLatestBufferId >= 0) {
- releaseBuffer(
- mLatestBufferId, mLatestBufferFrameNum,
- mBufferSlot[mLatestBufferId], mLatestBufferFence);
+ releaseBuffer(mLatestBufferId, mLatestBufferFrameNum, mLatestBufferFence);
}
if (mNumBufferAcquired != 0) {
ALOGW("potential buffer leak (acquired %d)", mNumBufferAcquired);
}
- if (mConsumer != NULL && !mIsPersistent) {
+ if (mConsumer != NULL) {
status_t err = mConsumer->consumerDisconnect();
if (err != NO_ERROR) {
ALOGW("consumerDisconnect failed: %d", err);
@@ -291,15 +193,33 @@
mLooper.clear();
}
- ALOGV("--> loaded; avail=%zu eos=%d eosSent=%d",
- mNumFramesAvailable, mEndOfStream, mEndOfStreamSent);
+ ALOGV("--> loaded; avail=%zu eos=%d eosSent=%d acquired=%d",
+ mNumFramesAvailable, mEndOfStream, mEndOfStreamSent, mNumBufferAcquired);
- // Codec is no longer executing. Discard all codec-related state.
+ // Codec is no longer executing. Releasing all buffers to bq.
+ for (int i = (int)mCodecBuffers.size() - 1; i >= 0; --i) {
+ if (mCodecBuffers[i].mGraphicBuffer != NULL) {
+ int id = mCodecBuffers[i].mSlot;
+ if (id != mLatestBufferId) {
+ ALOGV("releasing buffer for codec: slot=%d, useCount=%d, latest=%d",
+ id, mBufferUseCount[id], mLatestBufferId);
+ sp<Fence> fence = new Fence(-1);
+ releaseBuffer(id, mCodecBuffers[i].mFrameNumber, fence);
+ mBufferUseCount[id] = 0;
+ }
+ }
+ }
+ // Also release the latest buffer
+ if (mLatestBufferId >= 0) {
+ releaseBuffer(mLatestBufferId, mLatestBufferFrameNum, mLatestBufferFence);
+ mBufferUseCount[mLatestBufferId] = 0;
+ mLatestBufferId = -1;
+ }
+
mCodecBuffers.clear();
- // TODO: scan mCodecBuffers to verify that all mGraphicBuffer entries
- // are null; complain if not
-
+ mOMXNode.clear();
mExecuting = false;
+
return Status::ok();
}
@@ -313,7 +233,7 @@
return Status::fromServiceSpecificError(INVALID_OPERATION);
}
- ALOGV("addCodecBuffer id=%u", bufferID);
+ ALOGV("addCodecBuffer: bufferID=%u", bufferID);
CodecBuffer codecBuffer;
codecBuffer.mBufferID = bufferID;
@@ -336,14 +256,14 @@
int cbi = findMatchingCodecBuffer_l(bufferID);
if (cbi < 0) {
// This should never happen.
- ALOGE("codecBufferEmptied: buffer not recognized (id=%u)", bufferID);
+ ALOGE("codecBufferEmptied: buffer not recognized (bufferID=%u)", bufferID);
if (fenceFd >= 0) {
::close(fenceFd);
}
return Status::fromServiceSpecificError(BAD_VALUE);
}
- ALOGV("codecBufferEmptied id=%u", bufferID);
+ ALOGV("codecBufferEmptied: bufferID=%u, cbi=%d", bufferID, cbi);
CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
// header->nFilledLen may not be the original value, so we can't compare
@@ -374,19 +294,19 @@
mBufferSlot[id]->handle == codecBuffer.mGraphicBuffer->handle) {
mBufferUseCount[id]--;
- ALOGV("codecBufferEmptied: slot=%d, cbi=%d, useCount=%d, handle=%p",
- id, cbi, mBufferUseCount[id], mBufferSlot[id]->handle);
-
if (mBufferUseCount[id] < 0) {
ALOGW("mBufferUseCount for bq slot %d < 0 (=%d)", id, mBufferUseCount[id]);
mBufferUseCount[id] = 0;
}
if (id != mLatestBufferId && mBufferUseCount[id] == 0) {
- releaseBuffer(id, codecBuffer.mFrameNumber, mBufferSlot[id], fence);
+ releaseBuffer(id, codecBuffer.mFrameNumber, fence);
}
+ ALOGV("codecBufferEmptied: slot=%d, cbi=%d, useCount=%d, acquired=%d, handle=%p",
+ id, cbi, mBufferUseCount[id], mNumBufferAcquired, mBufferSlot[id]->handle);
} else {
- ALOGV("codecBufferEmptied: no match for emptied buffer in cbi %d",
- cbi);
+ ALOGV("codecBufferEmptied: no match for emptied buffer, "
+ "slot=%d, cbi=%d, useCount=%d, acquired=%d",
+ id, cbi, mBufferUseCount[id], mNumBufferAcquired);
// we will not reuse codec buffer, so there is no need to wait for fence
}
@@ -453,34 +373,19 @@
ALOGV("fillCodecBuffer_l: acquiring buffer, avail=%zu",
mNumFramesAvailable);
BufferItem item;
- status_t err = mConsumer->acquireBuffer(&item, 0);
- if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
- // shouldn't happen
- ALOGW("fillCodecBuffer_l: frame was not available");
- return false;
- } else if (err != OK) {
- // now what? fake end-of-stream?
- ALOGW("fillCodecBuffer_l: acquireBuffer returned err=%d", err);
+ status_t err = acquireBuffer(&item);
+ if (err != OK) {
+ ALOGE("fillCodecBuffer_l: acquireBuffer returned err=%d", err);
return false;
}
- mNumBufferAcquired++;
mNumFramesAvailable--;
- // If this is the first time we're seeing this buffer, add it to our
- // slot table.
- if (item.mGraphicBuffer != NULL) {
- ALOGV("fillCodecBuffer_l: setting mBufferSlot %d", item.mSlot);
- mBufferSlot[item.mSlot] = item.mGraphicBuffer;
- mBufferUseCount[item.mSlot] = 0;
- }
-
if (item.mDataSpace != mLastDataSpace) {
onDataSpaceChanged_l(
item.mDataSpace, (android_pixel_format)mBufferSlot[item.mSlot]->getPixelFormat());
}
-
err = UNKNOWN_ERROR;
// only submit sample if start time is unspecified, or sample
@@ -505,10 +410,18 @@
if (err != OK) {
ALOGV("submitBuffer_l failed, releasing bq slot %d", item.mSlot);
- releaseBuffer(item.mSlot, item.mFrameNumber, item.mGraphicBuffer, item.mFence);
+ releaseBuffer(item.mSlot, item.mFrameNumber, item.mFence);
} else {
- ALOGV("buffer submitted (bq %d, cbi %d)", item.mSlot, cbi);
- setLatestBuffer_l(item, dropped);
+ // Don't set the last buffer id if we're not repeating,
+ // we'll be holding on to the last buffer for nothing.
+ if (mRepeatAfterUs > 0ll) {
+ setLatestBuffer_l(item);
+ }
+ if (!dropped) {
+ ++mBufferUseCount[item.mSlot];
+ }
+ ALOGV("buffer submitted: slot=%d, cbi=%d, useCount=%d, acquired=%d",
+ item.mSlot, cbi, mBufferUseCount[item.mSlot], mNumBufferAcquired);
}
return true;
@@ -577,24 +490,16 @@
return true;
}
-void GraphicBufferSource::setLatestBuffer_l(
- const BufferItem &item, bool dropped) {
- if (mLatestBufferId >= 0) {
- if (mBufferUseCount[mLatestBufferId] == 0) {
- releaseBuffer(mLatestBufferId, mLatestBufferFrameNum,
- mBufferSlot[mLatestBufferId], mLatestBufferFence);
- // mLatestBufferFence will be set to new fence just below
- }
+void GraphicBufferSource::setLatestBuffer_l(const BufferItem &item) {
+ if (mLatestBufferId >= 0 && mBufferUseCount[mLatestBufferId] == 0) {
+ releaseBuffer(mLatestBufferId, mLatestBufferFrameNum, mLatestBufferFence);
+ // mLatestBufferFence will be set to new fence just below
}
mLatestBufferId = item.mSlot;
mLatestBufferFrameNum = item.mFrameNumber;
mRepeatLastFrameTimestamp = item.mTimestamp + mRepeatAfterUs * 1000;
- if (!dropped) {
- ++mBufferUseCount[item.mSlot];
- }
-
ALOGV("setLatestBuffer_l: slot=%d, useCount=%d",
item.mSlot, mBufferUseCount[item.mSlot]);
@@ -709,7 +614,7 @@
return err;
}
- ALOGV("emptyGraphicBuffer succeeded, id=%u buf=%p bufhandle=%p",
+ ALOGV("emptyGraphicBuffer succeeded, bufferID=%u buf=%p bufhandle=%p",
bufferID, buffer->getNativeBuffer(), buffer->handle);
return OK;
}
@@ -740,7 +645,7 @@
if (err != OK) {
ALOGW("emptyDirectBuffer EOS failed: 0x%x", err);
} else {
- ALOGV("submitEndOfInputStream_l: buffer submitted, id=%u cbi=%d",
+ ALOGV("submitEndOfInputStream_l: buffer submitted, bufferID=%u cbi=%d",
bufferID, cbi);
mEndOfStreamSent = true;
}
@@ -766,34 +671,39 @@
return -1;
}
+status_t GraphicBufferSource::acquireBuffer(BufferItem *bi) {
+ status_t err = mConsumer->acquireBuffer(bi, 0);
+ if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
+ // shouldn't happen
+ ALOGW("acquireBuffer: frame was not available");
+ return err;
+ } else if (err != OK) {
+ ALOGW("acquireBuffer: failed with err=%d", err);
+ return err;
+ }
+ // If this is the first time we're seeing this buffer, add it to our
+ // slot table.
+ if (bi->mGraphicBuffer != NULL) {
+ ALOGV("acquireBuffer: setting mBufferSlot %d", bi->mSlot);
+ mBufferSlot[bi->mSlot] = bi->mGraphicBuffer;
+ mBufferUseCount[bi->mSlot] = 0;
+ }
+ mNumBufferAcquired++;
+ return OK;
+}
+
/*
- * Releases an acquired buffer back to the consumer for either persistent
- * or non-persistent surfaces.
+ * Releases an acquired buffer back to the consumer.
*
- * id: buffer slot to release (in persistent case the id might be changed)
+ * id: buffer slot to release
* frameNum: frame number of the frame being released
- * buffer: GraphicBuffer pointer to release (note this must not be & as we
- * will clear the original mBufferSlot in persistent case)
- * Use NOLINT to supress warning on the copy of 'buffer'.
* fence: fence of the frame being released
*/
void GraphicBufferSource::releaseBuffer(
- int &id, uint64_t frameNum,
- const sp<GraphicBuffer> buffer, const sp<Fence> &fence) { // NOLINT
+ int id, uint64_t frameNum, const sp<Fence> &fence) {
ALOGV("releaseBuffer: slot=%d", id);
- if (mIsPersistent) {
- mConsumer->detachBuffer(id);
- mBufferSlot[id] = NULL;
-
- if (mConsumer->attachBuffer(&id, buffer) == OK) {
- mConsumer->releaseBuffer(
- id, 0, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
- }
- } else {
- mConsumer->releaseBuffer(
- id, frameNum, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
- }
- id = -1; // invalidate id
+ mConsumer->releaseBuffer(
+ id, frameNum, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
mNumBufferAcquired--;
}
@@ -804,7 +714,7 @@
ALOGV("onFrameAvailable exec=%d avail=%zu",
mExecuting, mNumFramesAvailable);
- if (mEndOfStream || mSuspended) {
+ if (mOMXNode == NULL || mEndOfStream || mSuspended) {
if (mEndOfStream) {
// This should only be possible if a new buffer was queued after
// EOS was signaled, i.e. the app is misbehaving.
@@ -815,20 +725,11 @@
}
BufferItem item;
- status_t err = mConsumer->acquireBuffer(&item, 0);
+ status_t err = acquireBuffer(&item);
if (err == OK) {
- mNumBufferAcquired++;
-
- // If this is the first time we're seeing this buffer, add it to our
- // slot table.
- if (item.mGraphicBuffer != NULL) {
- ALOGV("onFrameAvailable: setting mBufferSlot %d", item.mSlot);
- mBufferSlot[item.mSlot] = item.mGraphicBuffer;
- mBufferUseCount[item.mSlot] = 0;
- }
-
- releaseBuffer(item.mSlot, item.mFrameNumber,
- item.mGraphicBuffer, item.mFence);
+ releaseBuffer(item.mSlot, item.mFrameNumber, item.mFence);
+ } else {
+ ALOGE("onFrameAvailable: acquireBuffer returned err=%d", err);
}
return;
}
@@ -857,6 +758,18 @@
for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
if ((slotMask & 0x01) != 0) {
+ // Last buffer (if set) is always acquired even if its use count
+ // is 0, because we could have skipped that frame but kept it for
+ // repeating. Otherwise a buffer is only acquired if use count>0.
+ if (mBufferSlot[i] != NULL &&
+ (mBufferUseCount[i] > 0 || mLatestBufferId == i)) {
+ ALOGV("releasing acquired buffer: slot=%d, useCount=%d, latest=%d",
+ i, mBufferUseCount[i], mLatestBufferId);
+ mNumBufferAcquired--;
+ }
+ if (mLatestBufferId == i) {
+ mLatestBufferId = -1;
+ }
mBufferSlot[i] = NULL;
mBufferUseCount[i] = 0;
}
@@ -869,11 +782,99 @@
ALOG_ASSERT(false, "GraphicBufferSource can't consume sideband streams");
}
-void GraphicBufferSource::setDefaultDataSpace(android_dataspace dataSpace) {
- // no need for mutex as we are not yet running
- ALOGD("setting dataspace: %#x", dataSpace);
- mConsumer->setDefaultBufferDataSpace(dataSpace);
- mLastDataSpace = dataSpace;
+Status GraphicBufferSource::configure(
+ const sp<IOMXNode>& omxNode, int32_t dataSpace) {
+ if (omxNode == NULL) {
+ return Status::fromServiceSpecificError(BAD_VALUE);
+ }
+
+ // Do setInputSurface() first, the node will try to enable metadata
+ // mode on input, and does necessary error checking. If this fails,
+ // we can't use this input surface on the node.
+ status_t err = omxNode->setInputSurface(this);
+ if (err != NO_ERROR) {
+ ALOGE("Unable to set input surface: %d", err);
+ return Status::fromServiceSpecificError(err);
+ }
+
+ // use consumer usage bits queried from encoder, but always add
+ // HW_VIDEO_ENCODER for backward compatibility.
+ uint32_t consumerUsage;
+ if (omxNode->getParameter(
+ (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
+ &consumerUsage, sizeof(consumerUsage)) != OK) {
+ consumerUsage = 0;
+ }
+
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = kPortIndexInput;
+
+ err = omxNode->getParameter(
+ OMX_IndexParamPortDefinition, &def, sizeof(def));
+ if (err != NO_ERROR) {
+ ALOGE("Failed to get port definition: %d", err);
+ return Status::fromServiceSpecificError(UNKNOWN_ERROR);
+ }
+
+ // Call setMaxAcquiredBufferCount without lock.
+ // setMaxAcquiredBufferCount could call back to onBuffersReleased
+ // if the buffer count change results in releasing of existing buffers,
+ // which would lead to deadlock.
+ err = mConsumer->setMaxAcquiredBufferCount(def.nBufferCountActual);
+ if (err != NO_ERROR) {
+ ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
+ def.nBufferCountActual, err);
+ return Status::fromServiceSpecificError(err);
+ }
+
+ {
+ Mutex::Autolock autoLock(mMutex);
+ mOMXNode = omxNode;
+
+ err = mConsumer->setDefaultBufferSize(
+ def.format.video.nFrameWidth,
+ def.format.video.nFrameHeight);
+ if (err != NO_ERROR) {
+ ALOGE("Unable to set BQ default buffer size to %ux%u: %d",
+ def.format.video.nFrameWidth,
+ def.format.video.nFrameHeight,
+ err);
+ return Status::fromServiceSpecificError(err);
+ }
+
+ consumerUsage |= GRALLOC_USAGE_HW_VIDEO_ENCODER;
+ mConsumer->setConsumerUsageBits(consumerUsage);
+
+ // Sets the default buffer data space
+ ALOGD("setting dataspace: %#x, acquired=%d", dataSpace, mNumBufferAcquired);
+ mConsumer->setDefaultBufferDataSpace((android_dataspace)dataSpace);
+ mLastDataSpace = (android_dataspace)dataSpace;
+
+ mExecuting = false;
+ mSuspended = false;
+ mEndOfStream = false;
+ mEndOfStreamSent = false;
+ mMaxTimestampGapUs = -1ll;
+ mPrevOriginalTimeUs = -1ll;
+ mPrevModifiedTimeUs = -1ll;
+ mSkipFramesBeforeNs = -1ll;
+ mRepeatAfterUs = -1ll;
+ mRepeatLastFrameGeneration = 0;
+ mRepeatLastFrameTimestamp = -1ll;
+ mRepeatLastFrameCount = 0;
+ mLatestBufferId = -1;
+ mLatestBufferFrameNum = 0;
+ mLatestBufferFence = Fence::NO_FENCE;
+ mRepeatBufferDeferred = false;
+ mTimePerCaptureUs = -1ll;
+ mTimePerFrameUs = -1ll;
+ mPrevCaptureUs = -1ll;
+ mPrevFrameUs = -1ll;
+ mInputBufferTimeOffsetUs = 0;
+ }
+
+ return Status::ok();
}
Status GraphicBufferSource::setSuspend(bool suspend) {
@@ -886,22 +887,16 @@
while (mNumFramesAvailable > 0) {
BufferItem item;
- status_t err = mConsumer->acquireBuffer(&item, 0);
+ status_t err = acquireBuffer(&item);
- if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
- // shouldn't happen.
- ALOGW("suspend: frame was not available");
- break;
- } else if (err != OK) {
- ALOGW("suspend: acquireBuffer returned err=%d", err);
+ if (err != OK) {
+ ALOGE("setSuspend: acquireBuffer returned err=%d", err);
break;
}
- ++mNumBufferAcquired;
--mNumFramesAvailable;
- releaseBuffer(item.mSlot, item.mFrameNumber,
- item.mGraphicBuffer, item.mFence);
+ releaseBuffer(item.mSlot, item.mFrameNumber, item.mFence);
}
return Status::ok();
}
diff --git a/media/libstagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/GraphicBufferSource.h
index 88fab02..045a86a 100644
--- a/media/libstagefright/omx/GraphicBufferSource.h
+++ b/media/libstagefright/omx/GraphicBufferSource.h
@@ -58,14 +58,7 @@
public BnOMXBufferSource,
public BufferQueue::ConsumerListener {
public:
- GraphicBufferSource(
- const sp<IOMXNode> &omxNode,
- uint32_t bufferWidth,
- uint32_t bufferHeight,
- uint32_t bufferCount,
- uint32_t consumerUsage,
- const sp<IGraphicBufferConsumer> &consumer = NULL
- );
+ GraphicBufferSource();
virtual ~GraphicBufferSource();
@@ -81,9 +74,6 @@
return mProducer;
}
- // Sets the default buffer data space
- void setDefaultDataSpace(android_dataspace dataSpace);
-
// 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.
@@ -108,6 +98,10 @@
Status onInputBufferEmptied(
int32_t bufferID, const OMXFenceParcelable& fenceParcel) override;
+ // Configure the buffer source to be used with an OMX node with the default
+ // data space.
+ Status configure(const sp<IOMXNode>& omxNode, int32_t dataSpace) override;
+
// This is called after the last input frame has been submitted. We
// need to submit an empty buffer with the EOS flag set. If we don't
// have a codec buffer ready, we just set the mEndOfStream flag.
@@ -174,30 +168,6 @@
void onSidebandStreamChanged() override;
private:
- // PersistentProxyListener is similar to BufferQueue::ProxyConsumerListener
- // except that it returns (acquire/detach/re-attache/release) buffers
- // in onFrameAvailable() if the actual consumer object is no longer valid.
- //
- // This class is used in persistent input surface case to prevent buffer
- // loss when onFrameAvailable() is received while we don't have a valid
- // consumer around.
- class PersistentProxyListener : public BnConsumerListener {
- public:
- PersistentProxyListener(
- const wp<IGraphicBufferConsumer> &consumer,
- const wp<ConsumerListener>& consumerListener);
- virtual ~PersistentProxyListener();
- virtual void onFrameAvailable(const BufferItem& item) override;
- virtual void onFrameReplaced(const BufferItem& item) override;
- virtual void onBuffersReleased() override;
- virtual void onSidebandStreamChanged() override;
- private:
- // mConsumerListener is a weak reference to the IConsumerListener.
- wp<ConsumerListener> mConsumerListener;
- // mConsumer is a weak reference to the IGraphicBufferConsumer, use
- // a weak ref to avoid circular ref between mConsumer and this class
- wp<IGraphicBufferConsumer> mConsumer;
- };
// Keep track of codec input buffers. They may either be available
// (mGraphicBuffer == NULL) or in use by the codec.
@@ -242,12 +212,13 @@
// doing anything if we don't have a codec buffer available.
void submitEndOfInputStream_l();
- // Release buffer to the consumer
- void releaseBuffer(
- int &id, uint64_t frameNum,
- const sp<GraphicBuffer> buffer, const sp<Fence> &fence);
+ // Acquire buffer from the consumer
+ status_t acquireBuffer(BufferItem *bi);
- void setLatestBuffer_l(const BufferItem &item, bool dropped);
+ // Release buffer to the consumer
+ void releaseBuffer(int id, uint64_t frameNum, const sp<Fence> &fence);
+
+ void setLatestBuffer_l(const BufferItem &item);
bool repeatLatestBuffer_l();
bool getTimestamp(const BufferItem &item, int64_t *timeUs, int64_t *codecTimeUs);
@@ -274,7 +245,6 @@
// Our BufferQueue interfaces. mProducer is passed to the producer through
// getIGraphicBufferProducer, and mConsumer is used internally to retrieve
// the buffers queued by the producer.
- bool mIsPersistent;
sp<IGraphicBufferProducer> mProducer;
sp<IGraphicBufferConsumer> mConsumer;
@@ -340,7 +310,6 @@
int64_t mInputBufferTimeOffsetUs;
- MetadataBufferType mMetadataBufferType;
ColorAspects mColorAspects;
void onMessageReceived(const sp<AMessage> &msg);
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 70b9c17..7907c62 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -27,6 +27,7 @@
#include "../include/OMXNodeInstance.h"
#include <media/stagefright/foundation/ADebug.h>
+#include "GraphicBufferSource.h"
#include "OMXMaster.h"
#include "OMXUtils.h"
@@ -154,11 +155,26 @@
return StatusFromOMXError(err);
}
-status_t OMX::createPersistentInputSurface(
+status_t OMX::createInputSurface(
sp<IGraphicBufferProducer> *bufferProducer,
- sp<IGraphicBufferConsumer> *bufferConsumer) {
- return OMXNodeInstance::createPersistentInputSurface(
- bufferProducer, bufferConsumer);
+ sp<IGraphicBufferSource> *bufferSource) {
+ if (bufferProducer == NULL || bufferSource == NULL) {
+ ALOGE("b/25884056");
+ return BAD_VALUE;
+ }
+
+ sp<GraphicBufferSource> graphicBufferSource = new GraphicBufferSource();
+ status_t err = graphicBufferSource->initCheck();
+ if (err != OK) {
+ ALOGE("Failed to create persistent input surface: %s (%d)",
+ strerror(-err), err);
+ return err;
+ }
+
+ *bufferProducer = graphicBufferSource->getIGraphicBufferProducer();
+ *bufferSource = graphicBufferSource;
+
+ return OK;
}
} // namespace android
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index e45507c..ef18958 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -23,8 +23,6 @@
#include "../include/OMXNodeInstance.h"
#include "OMXMaster.h"
#include "OMXUtils.h"
-#include "GraphicBufferSource.h"
-#include <android/IGraphicBufferSource.h>
#include <android/IOMXBufferSource.h>
#include <OMX_Component.h>
@@ -482,6 +480,7 @@
status_t err = mOwner->freeNode(this);
mDispatcher.clear();
+ mOMXBufferSource.clear();
mHandle = NULL;
CLOG_IF_ERROR(freeNode, err, "");
@@ -1196,35 +1195,23 @@
return OK;
}
-status_t OMXNodeInstance::createGraphicBufferSource(
- OMX_U32 portIndex, android_dataspace dataSpace,
- const sp<IGraphicBufferConsumer> &bufferConsumer,
- sp<IGraphicBufferProducer> *bufferProducer,
- sp<IGraphicBufferSource> *bufferSource,
- MetadataBufferType *type) {
+status_t OMXNodeInstance::setInputSurface(
+ const sp<IOMXBufferSource> &bufferSource) {
+ Mutex::Autolock autolock(mLock);
+
status_t err;
// only allow graphic source on input port, when there are no allocated buffers yet
- if (portIndex != kPortIndexInput) {
- android_errorWriteLog(0x534e4554, "29422020");
- return BAD_VALUE;
- } else if (mNumPortBuffers[portIndex] > 0) {
+ if (mNumPortBuffers[kPortIndexInput] > 0) {
android_errorWriteLog(0x534e4554, "29422020");
return INVALID_OPERATION;
}
if (getBufferSource() != NULL) {
- if (portIndex < NELEM(mMetadataType) && type != NULL) {
- *type = mMetadataType[portIndex];
- }
return ALREADY_EXISTS;
}
- // Input buffers will hold meta-data (ANativeWindowBuffer references).
- if (type != NULL) {
- *type = kMetadataBufferTypeANWBuffer;
- }
- err = storeMetaDataInBuffers_l(portIndex, OMX_TRUE, type);
+ err = storeMetaDataInBuffers_l(kPortIndexInput, OMX_TRUE, NULL);
if (err != OK) {
return err;
}
@@ -1233,13 +1220,13 @@
// codec was configured.
OMX_PARAM_PORTDEFINITIONTYPE def;
InitOMXParams(&def);
- def.nPortIndex = portIndex;
+ def.nPortIndex = kPortIndexInput;
OMX_ERRORTYPE oerr = OMX_GetParameter(
mHandle, OMX_IndexParamPortDefinition, &def);
if (oerr != OMX_ErrorNone) {
OMX_INDEXTYPE index = OMX_IndexParamPortDefinition;
- CLOG_ERROR(getParameter, oerr, "%s(%#x): %s:%u",
- asString(index), index, portString(portIndex), portIndex);
+ CLOG_ERROR(getParameter, oerr, "%s(%#x): %s:%u", asString(index),
+ index, portString(kPortIndexInput), kPortIndexInput);
return UNKNOWN_ERROR;
}
@@ -1250,97 +1237,18 @@
return INVALID_OPERATION;
}
- uint32_t usageBits;
- oerr = OMX_GetParameter(
- mHandle, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits, &usageBits);
- if (oerr != OMX_ErrorNone) {
- usageBits = 0;
- }
-
- sp<GraphicBufferSource> graphicBufferSource = new GraphicBufferSource(
- this,
- def.format.video.nFrameWidth,
- def.format.video.nFrameHeight,
- def.nBufferCountActual,
- usageBits,
- bufferConsumer);
-
- if ((err = graphicBufferSource->initCheck()) != OK) {
- return err;
- }
- setBufferSource(graphicBufferSource);
-
- if (bufferConsumer == NULL) {
- graphicBufferSource->setDefaultDataSpace(dataSpace);
- }
-
- if (bufferProducer != NULL) {
- *bufferProducer = graphicBufferSource->getIGraphicBufferProducer();
- }
-
- *bufferSource = graphicBufferSource;
-
- return OK;
-}
-
-status_t OMXNodeInstance::createInputSurface(
- OMX_U32 portIndex, android_dataspace dataSpace,
- sp<IGraphicBufferProducer> *bufferProducer,
- sp<IGraphicBufferSource> *bufferSource,
- MetadataBufferType *type) {
- if (bufferProducer == NULL) {
- ALOGE("b/25884056");
+ if (def.format.video.nFrameWidth == 0
+ || def.format.video.nFrameHeight == 0) {
+ ALOGE("Invalid video dimension %ux%u",
+ def.format.video.nFrameWidth,
+ def.format.video.nFrameHeight);
return BAD_VALUE;
}
- Mutex::Autolock autolock(mLock);
- return createGraphicBufferSource(
- portIndex, dataSpace, NULL /* bufferConsumer */,
- bufferProducer, bufferSource, type);
-}
-
-//static
-status_t OMXNodeInstance::createPersistentInputSurface(
- sp<IGraphicBufferProducer> *bufferProducer,
- sp<IGraphicBufferConsumer> *bufferConsumer) {
- if (bufferProducer == NULL || bufferConsumer == NULL) {
- ALOGE("b/25884056");
- return BAD_VALUE;
- }
- String8 name("GraphicBufferSource");
-
- sp<IGraphicBufferProducer> producer;
- sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer);
- consumer->setConsumerName(name);
- consumer->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER);
-
- sp<BufferQueue::ProxyConsumerListener> proxy =
- new BufferQueue::ProxyConsumerListener(NULL);
- status_t err = consumer->consumerConnect(proxy, false);
- if (err != NO_ERROR) {
- ALOGE("Error connecting to BufferQueue: %s (%d)",
- strerror(-err), err);
- return err;
- }
-
- *bufferProducer = producer;
- *bufferConsumer = consumer;
-
+ setBufferSource(bufferSource);
return OK;
}
-status_t OMXNodeInstance::setInputSurface(
- OMX_U32 portIndex,
- const sp<IGraphicBufferConsumer> &bufferConsumer,
- sp<IGraphicBufferSource> *bufferSource,
- MetadataBufferType *type) {
- Mutex::Autolock autolock(mLock);
- return createGraphicBufferSource(
- portIndex, android_dataspace::HAL_DATASPACE_UNKNOWN,
- bufferConsumer, NULL, bufferSource, type);
-}
-
status_t OMXNodeInstance::allocateSecureBuffer(
OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer,
void **buffer_data, sp<NativeHandle> *native_handle) {