Merge "Add support for timestamps into SurfaceTexture."

This commit is contained in:
Eino-Ville Talvala 2011-03-17 15:52:34 -07:00 committed by Android (Google) Code Review
commit edc5ac145b
9 changed files with 131 additions and 17 deletions

View File

@ -62,8 +62,11 @@ public:
// contents of the buffer associated with slot and transfers ownership of
// that slot back to the server. It is not valid to call queueBuffer on a
// slot that is not owned by the client or one for which a buffer associated
// via requestBuffer.
virtual status_t queueBuffer(int slot) = 0;
// via requestBuffer. In addition, a timestamp must be provided by the
// client for this buffer. The timestamp is measured in nanoseconds, and
// must be monotonically increasing. Its other properties (zero point, etc)
// are client-dependent, and should be documented by the client.
virtual status_t queueBuffer(int slot, int64_t timestamp) = 0;
// cancelBuffer indicates that the client does not wish to fill in the
// buffer associated with slot and transfers ownership of the slot back to

View File

@ -66,7 +66,12 @@ public:
// unmodified.
virtual status_t dequeueBuffer(int *buf);
virtual status_t queueBuffer(int buf);
// queueBuffer returns a filled buffer to the SurfaceTexture. In addition, a
// timestamp must be provided for the buffer. The timestamp is in
// nanoseconds, and must be monotonically increasing. Its other semantics
// (zero point, etc) are client-dependent and should be documented by the
// client.
virtual status_t queueBuffer(int buf, int64_t timestamp);
virtual void cancelBuffer(int buf);
virtual status_t setCrop(const Rect& reg);
virtual status_t setTransform(uint32_t transform);
@ -98,6 +103,14 @@ public:
// functions.
void getTransformMatrix(float mtx[16]);
// getTimestamp retrieves the timestamp associated with the texture image
// set by the most recent call to updateTexImage.
//
// The timestamp is in nanoseconds, and is monotonically increasing. Its
// other semantics (zero point, etc) are source-dependent and should be
// documented by the source.
int64_t getTimestamp();
// setFrameAvailableListener sets the listener object that will be notified
// when a new frame becomes available.
void setFrameAvailableListener(const sp<FrameAvailableListener>& l);
@ -172,6 +185,10 @@ private:
// gets set to mLastQueuedTransform each time updateTexImage is called.
uint32_t mCurrentTransform;
// mCurrentTimestamp is the timestamp for the current texture. It
// gets set to mLastQueuedTimestamp each time updateTexImage is called.
int64_t mCurrentTimestamp;
// mLastQueued is the buffer slot index of the most recently enqueued buffer.
// At construction time it is initialized to INVALID_BUFFER_SLOT, and is
// updated each time queueBuffer is called.
@ -187,6 +204,10 @@ private:
// queueBuffer gets called.
uint32_t mLastQueuedTransform;
// mLastQueuedTimestamp is the timestamp for the buffer that was most
// recently queued. This gets set by queueBuffer.
int64_t mLastQueuedTimestamp;
// mNextCrop is the crop rectangle that will be used for the next buffer
// that gets queued. It is set by calling setCrop.
Rect mNextCrop;

View File

@ -63,6 +63,7 @@ private:
int dispatchSetBufferCount(va_list args);
int dispatchSetBuffersGeometry(va_list args);
int dispatchSetBuffersTransform(va_list args);
int dispatchSetBuffersTimestamp(va_list args);
int dispatchSetCrop(va_list args);
int dispatchSetUsage(va_list args);
@ -71,6 +72,7 @@ private:
int setBufferCount(int bufferCount);
int setBuffersGeometry(int w, int h, int format);
int setBuffersTransform(int transform);
int setBuffersTimestamp(int64_t timestamp);
int setCrop(Rect const* rect);
int setUsage(uint32_t reqUsage);
@ -114,6 +116,11 @@ private:
// at the next deuque operation. It is initialized to 0.
uint32_t mReqUsage;
// mTimestamp is the timestamp that will be used for the next buffer queue
// operation. It defaults to NATIVE_WINDOW_TIMESTAMP_AUTO, which means that
// a timestamp is auto-generated when queueBuffer is called.
int64_t mTimestamp;
// mMutex is the mutex used to prevent concurrent access to the member
// variables of SurfaceTexture objects. It must be locked whenever the
// member variables are accessed.

View File

@ -226,7 +226,8 @@ private:
int dispatch_set_buffer_count(va_list args);
int dispatch_set_buffers_geometry(va_list args);
int dispatch_set_buffers_transform(va_list args);
int dispatch_set_buffers_timestamp(va_list args);
void setUsage(uint32_t reqUsage);
int connect(int api);
int disconnect(int api);
@ -234,6 +235,7 @@ private:
int setBufferCount(int bufferCount);
int setBuffersGeometry(int w, int h, int format);
int setBuffersTransform(int transform);
int setBuffersTimestamp(int64_t timestamp);
/*
* private stuff...

View File

@ -57,7 +57,7 @@ typedef struct android_native_base_t
{
/* a magic value defined by the actual EGL native type */
int magic;
/* the sizeof() of the actual EGL native type */
int version;
@ -129,6 +129,7 @@ enum {
NATIVE_WINDOW_SET_BUFFER_COUNT,
NATIVE_WINDOW_SET_BUFFERS_GEOMETRY,
NATIVE_WINDOW_SET_BUFFERS_TRANSFORM,
NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP,
};
/* parameter for NATIVE_WINDOW_[DIS]CONNECT */
@ -157,7 +158,15 @@ enum {
NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT, // SurfaceTextureClient
};
struct ANativeWindow
/* parameter for NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP
*
* Special timestamp value to indicate that timestamps should be auto-generated
* by the native window when queueBuffer is called. This is equal to INT64_MIN,
* defined directly to avoid problems with C99/C++ inclusion of stdint.h.
*/
const int64_t NATIVE_WINDOW_TIMESTAMP_AUTO = (-9223372036854775807LL-1);
struct ANativeWindow
{
#ifdef __cplusplus
ANativeWindow()
@ -262,7 +271,8 @@ struct ANativeWindow
* NATIVE_WINDOW_SET_BUFFER_COUNT
* NATIVE_WINDOW_SET_BUFFERS_GEOMETRY
* NATIVE_WINDOW_SET_BUFFERS_TRANSFORM
*
* NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP
*
*/
int (*perform)(struct ANativeWindow* window,
@ -389,6 +399,22 @@ static inline int native_window_set_buffers_transform(
transform);
}
/*
* native_window_set_buffers_timestamp(..., int64_t timestamp)
* All buffers queued after this call will be associated with the timestamp
* parameter specified. If the timestamp is set to NATIVE_WINDOW_TIMESTAMP_AUTO
* (the default), timestamps will be generated automatically when queueBuffer is
* called. The timestamp is measured in nanoseconds, and must be monotonically
* increasing.
*/
static inline int native_window_set_buffers_timestamp(
ANativeWindow* window,
int64_t timestamp)
{
return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP,
timestamp);
}
// ---------------------------------------------------------------------------
/* FIXME: this is legacy for pixmaps */

View File

@ -88,10 +88,11 @@ public:
return result;
}
virtual status_t queueBuffer(int buf) {
virtual status_t queueBuffer(int buf, int64_t timestamp) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
data.writeInt32(buf);
data.writeInt64(timestamp);
remote()->transact(QUEUE_BUFFER, data, &reply);
status_t result = reply.readInt32();
return result;
@ -174,7 +175,8 @@ status_t BnSurfaceTexture::onTransact(
case QUEUE_BUFFER: {
CHECK_INTERFACE(ISurfaceTexture, data, reply);
int buf = data.readInt32();
status_t result = queueBuffer(buf);
int64_t timestamp = data.readInt64();
status_t result = queueBuffer(buf, timestamp);
reply->writeInt32(result);
return NO_ERROR;
} break;
@ -196,7 +198,6 @@ status_t BnSurfaceTexture::onTransact(
return NO_ERROR;
} break;
case SET_TRANSFORM: {
Rect reg;
CHECK_INTERFACE(ISurfaceTexture, data, reply);
uint32_t transform = data.readInt32();
status_t result = setTransform(transform);

View File

@ -76,9 +76,15 @@ static float mtxRot270[16] = {
static void mtxMul(float out[16], const float a[16], const float b[16]);
SurfaceTexture::SurfaceTexture(GLuint tex) :
mBufferCount(MIN_BUFFER_SLOTS), mCurrentTexture(INVALID_BUFFER_SLOT),
mCurrentTransform(0), mLastQueued(INVALID_BUFFER_SLOT),
mLastQueuedTransform(0), mNextTransform(0), mTexName(tex) {
mBufferCount(MIN_BUFFER_SLOTS),
mCurrentTexture(INVALID_BUFFER_SLOT),
mCurrentTransform(0),
mCurrentTimestamp(0),
mLastQueued(INVALID_BUFFER_SLOT),
mLastQueuedTransform(0),
mLastQueuedTimestamp(0),
mNextTransform(0),
mTexName(tex) {
LOGV("SurfaceTexture::SurfaceTexture");
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
@ -153,7 +159,7 @@ status_t SurfaceTexture::dequeueBuffer(int *buf) {
return OK;
}
status_t SurfaceTexture::queueBuffer(int buf) {
status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp) {
LOGV("SurfaceTexture::queueBuffer");
Mutex::Autolock lock(mMutex);
if (buf < 0 || mBufferCount <= buf) {
@ -172,6 +178,7 @@ status_t SurfaceTexture::queueBuffer(int buf) {
mLastQueued = buf;
mLastQueuedCrop = mNextCrop;
mLastQueuedTransform = mNextTransform;
mLastQueuedTimestamp = timestamp;
if (mFrameAvailableListener != 0) {
mFrameAvailableListener->onFrameAvailable();
}
@ -246,12 +253,13 @@ status_t SurfaceTexture::updateTexImage() {
mCurrentTextureBuf = mSlots[mCurrentTexture].mGraphicBuffer;
mCurrentCrop = mLastQueuedCrop;
mCurrentTransform = mLastQueuedTransform;
mCurrentTimestamp = mLastQueuedTimestamp;
}
return OK;
}
void SurfaceTexture::getTransformMatrix(float mtx[16]) {
LOGV("SurfaceTexture::updateTexImage");
LOGV("SurfaceTexture::getTransformMatrix");
Mutex::Autolock lock(mMutex);
float xform[16];
@ -342,6 +350,12 @@ void SurfaceTexture::getTransformMatrix(float mtx[16]) {
mtxMul(mtx, mtxFlipV, mtxBeforeFlipV);
}
nsecs_t SurfaceTexture::getTimestamp() {
LOGV("SurfaceTexture::getTimestamp");
Mutex::Autolock lock(mMutex);
return mCurrentTimestamp;
}
void SurfaceTexture::setFrameAvailableListener(
const sp<FrameAvailableListener>& l) {
LOGV("SurfaceTexture::setFrameAvailableListener");

View File

@ -26,7 +26,8 @@ namespace android {
SurfaceTextureClient::SurfaceTextureClient(
const sp<ISurfaceTexture>& surfaceTexture):
mSurfaceTexture(surfaceTexture), mAllocator(0), mReqWidth(1),
mReqHeight(1), mReqFormat(DEFAULT_FORMAT), mReqUsage(0), mMutex() {
mReqHeight(1), mReqFormat(DEFAULT_FORMAT), mReqUsage(0),
mTimestamp(NATIVE_WINDOW_TIMESTAMP_AUTO), mMutex() {
// Initialize the ANativeWindow function pointers.
ANativeWindow::setSwapInterval = setSwapInterval;
ANativeWindow::dequeueBuffer = dequeueBuffer;
@ -135,9 +136,17 @@ int SurfaceTextureClient::lockBuffer(android_native_buffer_t* buffer) {
int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) {
LOGV("SurfaceTextureClient::queueBuffer");
Mutex::Autolock lock(mMutex);
int64_t timestamp;
if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) {
timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
LOGV("SurfaceTextureClient::queueBuffer making up timestamp: %.2f ms",
timestamp / 1000000.f);
} else {
timestamp = mTimestamp;
}
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
if (mSlots[i]->handle == buffer->handle) {
return mSurfaceTexture->queueBuffer(i);
return mSurfaceTexture->queueBuffer(i, timestamp);
}
}
LOGE("queueBuffer: unknown buffer queued");
@ -196,6 +205,9 @@ int SurfaceTextureClient::perform(int operation, va_list args)
case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
res = dispatchSetBuffersTransform(args);
break;
case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
res = dispatchSetBuffersTimestamp(args);
break;
default:
res = NAME_NOT_FOUND;
break;
@ -240,6 +252,11 @@ int SurfaceTextureClient::dispatchSetBuffersTransform(va_list args) {
return setBuffersTransform(transform);
}
int SurfaceTextureClient::dispatchSetBuffersTimestamp(va_list args) {
int64_t timestamp = va_arg(args, int64_t);
return setBuffersTimestamp(timestamp);
}
int SurfaceTextureClient::connect(int api) {
LOGV("SurfaceTextureClient::connect");
// XXX: Implement this!
@ -323,6 +340,14 @@ int SurfaceTextureClient::setBuffersTransform(int transform)
return err;
}
int SurfaceTextureClient::setBuffersTimestamp(int64_t timestamp)
{
LOGV("SurfaceTextureClient::setBuffersTimestamp");
Mutex::Autolock lock(mMutex);
mTimestamp = timestamp;
return NO_ERROR;
}
void SurfaceTextureClient::freeAllBuffers() {
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
mSlots[i] = 0;

View File

@ -753,6 +753,9 @@ int Surface::perform(int operation, va_list args)
case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
res = dispatch_set_buffers_transform( args );
break;
case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
res = dispatch_set_buffers_timestamp( args );
break;
default:
res = NAME_NOT_FOUND;
break;
@ -792,6 +795,11 @@ int Surface::dispatch_set_buffers_transform(va_list args) {
return setBuffersTransform(transform);
}
int Surface::dispatch_set_buffers_timestamp(va_list args) {
int64_t timestamp = va_arg(args, int64_t);
return setBuffersTimestamp(timestamp);
}
void Surface::setUsage(uint32_t reqUsage)
{
Mutex::Autolock _l(mSurfaceLock);
@ -910,6 +918,13 @@ int Surface::setBuffersTransform(int transform)
return NO_ERROR;
}
int Surface::setBuffersTimestamp(int64_t timestamp)
{
// Surface doesn't really have anything meaningful to do with timestamps
// so they'll just be dropped here.
return NO_ERROR;
}
// ----------------------------------------------------------------------------
int Surface::getConnectedApi() const