diff options
| author | 2010-12-20 11:27:26 -0800 | |
|---|---|---|
| committer | 2011-01-06 13:20:47 -0800 | |
| commit | 8ba32fade11abb73f3fd47ea0953c9528eb5b91f (patch) | |
| tree | 4934397842dec6ad482d1e6bc93782840b5433eb /libs/gui/SurfaceTextureClient.cpp | |
| parent | 495633406580685dfaa41979bbae47fc5f77fefe (diff) | |
Add the SurfaceTexture C++ implementation.
This change adds the C++ implementation of SurfaceTexture and related
classes. The goal of this is for a SurfaceTexture to be passed to
camera service or Stagefright in place of a Surface to allow camera
preview or decoded video frames to be streamed to an OpenGL ES texture
that an application can use.
Change-Id: I55c83a7017f1ecb81c9c9e3252cbd118b914296c
Diffstat (limited to 'libs/gui/SurfaceTextureClient.cpp')
| -rw-r--r-- | libs/gui/SurfaceTextureClient.cpp | 285 | 
1 files changed, 285 insertions, 0 deletions
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp new file mode 100644 index 0000000000..8a5914460b --- /dev/null +++ b/libs/gui/SurfaceTextureClient.cpp @@ -0,0 +1,285 @@ +/* + * Copyright (C) 2010 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. + */ + +#define LOG_TAG "SurfaceTextureClient" + +#include <gui/SurfaceTextureClient.h> + +#include <utils/Log.h> + +namespace android { + +SurfaceTextureClient::SurfaceTextureClient( +        const sp<ISurfaceTexture>& surfaceTexture): +        mSurfaceTexture(surfaceTexture), mReqWidth(1), mReqHeight(1), +        mReqFormat(DEFAULT_FORMAT), mReqUsage(0), mMutex() { +    // Initialize the ANativeWindow function pointers. +    ANativeWindow::setSwapInterval  = setSwapInterval; +    ANativeWindow::dequeueBuffer    = dequeueBuffer; +    ANativeWindow::cancelBuffer     = cancelBuffer; +    ANativeWindow::lockBuffer       = lockBuffer; +    ANativeWindow::queueBuffer      = queueBuffer; +    ANativeWindow::query            = query; +    ANativeWindow::perform          = perform; +} + +int SurfaceTextureClient::setSwapInterval(ANativeWindow* window, int interval) { +    SurfaceTextureClient* c = getSelf(window); +    return c->setSwapInterval(interval); +} + +int SurfaceTextureClient::dequeueBuffer(ANativeWindow* window, +        android_native_buffer_t** buffer) { +    SurfaceTextureClient* c = getSelf(window); +    return c->dequeueBuffer(buffer); +} + +int SurfaceTextureClient::cancelBuffer(ANativeWindow* window, +        android_native_buffer_t* buffer) { +    SurfaceTextureClient* c = getSelf(window); +    return c->cancelBuffer(buffer); +} + +int SurfaceTextureClient::lockBuffer(ANativeWindow* window, +        android_native_buffer_t* buffer) { +    SurfaceTextureClient* c = getSelf(window); +    return c->lockBuffer(buffer); +} + +int SurfaceTextureClient::queueBuffer(ANativeWindow* window, +        android_native_buffer_t* buffer) { +    SurfaceTextureClient* c = getSelf(window); +    return c->queueBuffer(buffer); +} + +int SurfaceTextureClient::query(ANativeWindow* window, int what, int* value) { +    SurfaceTextureClient* c = getSelf(window); +    return c->query(what, value); +} + +int SurfaceTextureClient::perform(ANativeWindow* window, int operation, ...) { +    va_list args; +    va_start(args, operation); +    SurfaceTextureClient* c = getSelf(window); +    return c->perform(operation, args); +} + +int SurfaceTextureClient::setSwapInterval(int interval) { +    return INVALID_OPERATION; +} + +int SurfaceTextureClient::dequeueBuffer(android_native_buffer_t** buffer) { +    Mutex::Autolock lock(mMutex); +    int buf = -1; +    status_t err = mSurfaceTexture->dequeueBuffer(&buf); +    if (err < 0) { +        return err; +    } +    sp<GraphicBuffer>& gbuf(mSlots[buf]); +    if (gbuf == 0 || gbuf->getWidth() != mReqWidth || +        gbuf->getHeight() != mReqHeight || +        uint32_t(gbuf->getPixelFormat()) != mReqFormat || +        (gbuf->getUsage() & mReqUsage) != mReqUsage) { +        gbuf = mSurfaceTexture->requestBuffer(buf, mReqWidth, mReqHeight, +                mReqFormat, mReqUsage); +        if (gbuf == 0) { +            return NO_MEMORY; +        } +    } +    *buffer = gbuf.get(); +    return OK; +} + +int SurfaceTextureClient::cancelBuffer(android_native_buffer_t* buffer) { +    Mutex::Autolock lock(mMutex); +    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { +        if (mSlots[i].get() == buffer) { +            mSurfaceTexture->cancelBuffer(i); +            return OK; +        } +    } +    return BAD_VALUE; +} + +int SurfaceTextureClient::lockBuffer(android_native_buffer_t* buffer) { +    Mutex::Autolock lock(mMutex); +    return OK; +} + +int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) { +    Mutex::Autolock lock(mMutex); +    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { +        if (mSlots[i].get() == GraphicBuffer::getSelf(buffer)) { +            return mSurfaceTexture->queueBuffer(i); +        } +    } +    LOGE("queueBuffer: unknown buffer queued"); +    return BAD_VALUE; +} + +int SurfaceTextureClient::query(int what, int* value) { +    Mutex::Autolock lock(mMutex); +    // XXX: Implement this! +    return INVALID_OPERATION; +} + +int SurfaceTextureClient::perform(int operation, va_list args) +{ +    int res = NO_ERROR; +    switch (operation) { +    case NATIVE_WINDOW_CONNECT: +        res = dispatchConnect(args); +        break; +    case NATIVE_WINDOW_DISCONNECT: +        res = dispatchDisconnect(args); +        break; +    case NATIVE_WINDOW_SET_USAGE: +        res = dispatchSetUsage(args); +        break; +    case NATIVE_WINDOW_SET_CROP: +        res = dispatchSetCrop(args); +        break; +    case NATIVE_WINDOW_SET_BUFFER_COUNT: +        res = dispatchSetBufferCount(args); +        break; +    case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY: +        res = dispatchSetBuffersGeometry(args); +        break; +    case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM: +        res = dispatchSetBuffersTransform(args); +        break; +    default: +        res = NAME_NOT_FOUND; +        break; +    } +    return res; +} + +int SurfaceTextureClient::dispatchConnect(va_list args) { +    int api = va_arg(args, int); +    return connect(api); +} + +int SurfaceTextureClient::dispatchDisconnect(va_list args) { +    int api = va_arg(args, int); +    return disconnect(api); +} + +int SurfaceTextureClient::dispatchSetUsage(va_list args) { +    int usage = va_arg(args, int); +    return setUsage(usage); +} + +int SurfaceTextureClient::dispatchSetCrop(va_list args) { +    android_native_rect_t const* rect = va_arg(args, android_native_rect_t*); +    return setCrop(reinterpret_cast<Rect const*>(rect)); +} + +int SurfaceTextureClient::dispatchSetBufferCount(va_list args) { +    size_t bufferCount = va_arg(args, size_t); +    return setBufferCount(bufferCount); +} + +int SurfaceTextureClient::dispatchSetBuffersGeometry(va_list args) { +    int w = va_arg(args, int); +    int h = va_arg(args, int); +    int f = va_arg(args, int); +    return setBuffersGeometry(w, h, f); +} + +int SurfaceTextureClient::dispatchSetBuffersTransform(va_list args) { +    int transform = va_arg(args, int); +    return setBuffersTransform(transform); +} + +int SurfaceTextureClient::connect(int api) { +    // XXX: Implement this! +    return INVALID_OPERATION; +} + +int SurfaceTextureClient::disconnect(int api) { +    // XXX: Implement this! +    return INVALID_OPERATION; +} + +int SurfaceTextureClient::setUsage(uint32_t reqUsage) +{ +    Mutex::Autolock lock(mMutex); +    mReqUsage = reqUsage; +    return OK; +} + +int SurfaceTextureClient::setCrop(Rect const* rect) +{ +    Mutex::Autolock lock(mMutex); + +    // empty/invalid rects are not allowed +    if (rect->isEmpty()) +        return BAD_VALUE; + +    status_t err = mSurfaceTexture->setCrop(*rect); +    LOGE_IF(err, "ISurfaceTexture::setCrop(...) returned %s", +            strerror(-err)); + +    return err; +} + +int SurfaceTextureClient::setBufferCount(int bufferCount) +{ +    Mutex::Autolock lock(mMutex); + +    status_t err = mSurfaceTexture->setBufferCount(bufferCount); +    LOGE_IF(err, "ISurfaceTexture::setBufferCount(%d) returned %s", +            bufferCount, strerror(-err)); + +    if (err == NO_ERROR) { +        freeAllBuffers(); +    } + +    return err; +} + +int SurfaceTextureClient::setBuffersGeometry(int w, int h, int format) +{ +    Mutex::Autolock lock(mMutex); + +    if (w<0 || h<0 || format<0) +        return BAD_VALUE; + +    if ((w && !h) || (!w && h)) +        return BAD_VALUE; + +    mReqWidth = w; +    mReqHeight = h; +    mReqFormat = format; + +    return NO_ERROR; +} + +int SurfaceTextureClient::setBuffersTransform(int transform) +{ +    Mutex::Autolock lock(mMutex); +    status_t err = mSurfaceTexture->setTransform(transform); +    return err; +} + +void SurfaceTextureClient::freeAllBuffers() { +    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) { +        mSlots[i] = 0; +    } +} + +}; // namespace android  |