Add sideband streams to BufferQueue and related classes
Sideband streams are essentially a device-specific buffer queue that
bypasses the BufferQueue system. They can be used for situations with
hard real-time requirements like high-quality TV and video playback
with A/V sync. A handle to the stream is provided by the source HAL,
and attached to a BufferQueue. The sink HAL can read buffers via the
stream handle rather than acquiring individual buffers from the
BufferQueue.
Change-Id: Ib3f262eddfc520f4bbe3d9b91753ed7dd09d3a9b
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index af857fd..8584dc9 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -93,6 +93,10 @@
return mProducer->disconnect(api);
}
+status_t BufferQueue::setSidebandStream(const sp<NativeHandle>& stream) {
+ return mProducer->setSidebandStream(stream);
+}
+
status_t BufferQueue::acquireBuffer(BufferItem* buffer, nsecs_t presentWhen) {
return mConsumer->acquireBuffer(buffer, presentWhen);
}
@@ -148,8 +152,19 @@
return mConsumer->setTransformHint(hint);
}
+sp<NativeHandle> BufferQueue::getSidebandStream() const {
+ return mConsumer->getSidebandStream();
+}
+
void BufferQueue::dump(String8& result, const char* prefix) const {
mConsumer->dump(result, prefix);
}
+void BufferQueue::ProxyConsumerListener::onSidebandStreamChanged() {
+ sp<ConsumerListener> listener(mConsumerListener.promote());
+ if (listener != NULL) {
+ listener->onSidebandStreamChanged();
+ }
+}
+
}; // namespace android
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index dc7aa15..e34f716 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -395,6 +395,10 @@
return NO_ERROR;
}
+sp<NativeHandle> BufferQueueConsumer::getSidebandStream() const {
+ return mCore->mSidebandStream;
+}
+
void BufferQueueConsumer::dump(String8& result, const char* prefix) const {
mCore->dump(result, prefix);
}
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 0e9de88..0ff7b80 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -674,6 +674,7 @@
}
mCore->mConnectedProducerToken = NULL;
mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
+ mCore->mSidebandStream.clear();
mCore->mDequeueCondition.broadcast();
listener = mCore->mConsumerListener;
} else {
@@ -697,6 +698,12 @@
return status;
}
+status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) {
+ Mutex::Autolock _l(mCore->mMutex);
+ mCore->mSidebandStream = stream;
+ return NO_ERROR;
+}
+
void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
// If we're here, it means that a producer we were connected to died.
// We're guaranteed that we are still connected to it because we remove
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index c5900aa..b6adc54 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -130,6 +130,9 @@
}
}
+void ConsumerBase::onSidebandStreamChanged() {
+}
+
void ConsumerBase::abandon() {
CB_LOGV("abandon");
Mutex::Autolock lock(mMutex);
diff --git a/libs/gui/IConsumerListener.cpp b/libs/gui/IConsumerListener.cpp
index 5304462..4ccf0ac 100644
--- a/libs/gui/IConsumerListener.cpp
+++ b/libs/gui/IConsumerListener.cpp
@@ -28,7 +28,8 @@
enum {
ON_FRAME_AVAILABLE = IBinder::FIRST_CALL_TRANSACTION,
- ON_BUFFER_RELEASED
+ ON_BUFFER_RELEASED,
+ ON_SIDEBAND_STREAM_CHANGED,
};
class BpConsumerListener : public BpInterface<IConsumerListener>
@@ -49,6 +50,12 @@
data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor());
remote()->transact(ON_BUFFER_RELEASED, data, &reply, IBinder::FLAG_ONEWAY);
}
+
+ virtual void onSidebandStreamChanged() {
+ Parcel data, reply;
+ data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor());
+ remote()->transact(ON_SIDEBAND_STREAM_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
+ }
};
IMPLEMENT_META_INTERFACE(ConsumerListener, "android.gui.IConsumerListener");
@@ -67,6 +74,10 @@
CHECK_INTERFACE(IConsumerListener, data, reply);
onBuffersReleased();
return NO_ERROR;
+ case ON_SIDEBAND_STREAM_CHANGED:
+ CHECK_INTERFACE(IConsumerListener, data, reply);
+ onSidebandStreamChanged();
+ return NO_ERROR;
}
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp
index 876c895..c97d15b 100644
--- a/libs/gui/IGraphicBufferConsumer.cpp
+++ b/libs/gui/IGraphicBufferConsumer.cpp
@@ -24,6 +24,7 @@
#include <sys/types.h>
#include <utils/Errors.h>
+#include <utils/NativeHandle.h>
#include <binder/Parcel.h>
#include <binder/IInterface.h>
@@ -195,6 +196,7 @@
SET_DEFAULT_BUFFER_FORMAT,
SET_CONSUMER_USAGE_BITS,
SET_TRANSFORM_HINT,
+ GET_SIDEBAND_STREAM,
DUMP,
};
@@ -354,6 +356,20 @@
return reply.readInt32();
}
+ virtual sp<NativeHandle> getSidebandStream() const {
+ Parcel data, reply;
+ status_t err;
+ data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
+ if ((err = remote()->transact(GET_SIDEBAND_STREAM, data, &reply)) != NO_ERROR) {
+ return NULL;
+ }
+ sp<NativeHandle> stream;
+ if (reply.readInt32()) {
+ stream = NativeHandle::create(reply.readNativeHandle());
+ }
+ return stream;
+ }
+
virtual void dump(String8& result, const char* prefix) const {
Parcel data, reply;
data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 0f461e5..efbe878 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -18,9 +18,10 @@
#include <sys/types.h>
#include <utils/Errors.h>
+#include <utils/NativeHandle.h>
#include <utils/RefBase.h>
-#include <utils/Vector.h>
#include <utils/Timers.h>
+#include <utils/Vector.h>
#include <binder/Parcel.h>
#include <binder/IInterface.h>
@@ -39,6 +40,7 @@
QUERY,
CONNECT,
DISCONNECT,
+ SET_SIDEBAND_STREAM,
};
class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
@@ -169,6 +171,22 @@
result = reply.readInt32();
return result;
}
+
+ virtual status_t setSidebandStream(const sp<NativeHandle>& stream) {
+ Parcel data, reply;
+ status_t result;
+ data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
+ if (stream.get()) {
+ data.writeInt32(true);
+ data.writeNativeHandle(stream->handle());
+ } else {
+ data.writeInt32(false);
+ }
+ if ((result = remote()->transact(SET_SIDEBAND_STREAM, data, &reply)) == NO_ERROR) {
+ result = reply.readInt32();
+ }
+ return result;
+ }
};
IMPLEMENT_META_INTERFACE(GraphicBufferProducer, "android.gui.IGraphicBufferProducer");
@@ -263,6 +281,16 @@
reply->writeInt32(res);
return NO_ERROR;
} break;
+ case SET_SIDEBAND_STREAM: {
+ CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+ sp<NativeHandle> stream;
+ if (data.readInt32()) {
+ stream = NativeHandle::create(data.readNativeHandle());
+ }
+ status_t result = setSidebandStream(stream);
+ reply->writeInt32(result);
+ return NO_ERROR;
+ } break;
}
return BBinder::onTransact(code, data, reply, flags);
}