Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9476926b authored by Igor Murashkin's avatar Igor Murashkin
Browse files

Camera: ProCamera - add createStream stub and unit test for it

Change-Id: Ic05130e63f4f2c0c3278ba348b192992169f105f
parent 90fce97b
Loading
Loading
Loading
Loading
+68 −0
Original line number Diff line number Diff line
@@ -261,4 +261,72 @@ status_t ProCamera::cancelStream(int streamId)
    return c->cancelStream(streamId);
}

status_t ProCamera::createStream(int width, int height, int format,
                          const sp<ANativeWindow>& window,
                          /*out*/
                          int* streamId)
{
    *streamId = -1;

    ALOGV("%s: createStreamW %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
                                                                       format);

    if (window == 0) {
        return BAD_VALUE;
    }

    // TODO: actually implement this in IProCamera
    return INVALID_OPERATION;
}

status_t ProCamera::createStream(int width, int height, int format,
                          const sp<IGraphicBufferProducer>& bufferProducer,
                          /*out*/
                          int* streamId) {

    ALOGV("%s: createStreamT %dx%d (fmt=0x%x)", __FUNCTION__, width, height,
                                                                       format);

    sp<IBinder> binder;
    sp<ANativeWindow> window;

    if (bufferProducer != 0) {
        binder = bufferProducer->asBinder();
        window = new Surface(bufferProducer);

        status_t stat = createStream(width, height, format, window, streamId);

        ALOGV("%s: createStreamT END (%d), StreamID = %d", __FUNCTION__, stat,
                                                                    *streamId);
    }
    else {
        *streamId = -1;
        return BAD_VALUE;
    }

    return BAD_VALUE;
}

int ProCamera::getNumberOfCameras() {
    ALOGE("%s: not implemented yet", __FUNCTION__);
    return 1;
}

camera_metadata* ProCamera::getCameraInfo(int cameraId) {
    ALOGE("%s: not implemented yet", __FUNCTION__);

    ALOGV("%s: cameraId = %d", __FUNCTION__, cameraId);
    return NULL;
}

status_t ProCamera::createDefaultRequest(int templateId,
                                             camera_metadata** request) const {
    ALOGE("%s: not implemented yet", __FUNCTION__);

    ALOGV("%s: templateId = %d", __FUNCTION__, templateId);

    *request = NULL;
    return INVALID_OPERATION;
}

}; // namespace android
+111 −1
Original line number Diff line number Diff line
@@ -26,6 +26,12 @@
#include <utils/Mutex.h>
#include <utils/Condition.h>

#include <gui/SurfaceComposerClient.h>
#include <gui/Surface.h>

#include <system/camera_metadata.h>
#include <hardware/camera2.h> // for CAMERA2_TEMPLATE_PREVIEW only

namespace android {
namespace camera2 {
namespace tests {
@@ -34,7 +40,8 @@ namespace client {
#define CAMERA_ID 0
#define TEST_DEBUGGING 0

#define TEST_LISTENER_TIMEOUT 2000000000 // 2 second listener timeout
#define TEST_LISTENER_TIMEOUT 1000000000 // 1 second listener timeout
#define TEST_FORMAT HAL_PIXEL_FORMAT_RGBA_8888 //TODO: YUY2 instead

#if TEST_DEBUGGING
#define dout std::cerr
@@ -206,6 +213,40 @@ protected:

    static sp<Thread> mTestThread;

    int mDisplaySecs;
    sp<SurfaceComposerClient> mComposerClient;
    sp<SurfaceControl> mSurfaceControl;

    int getSurfaceWidth() {
        return 512;
    }
    int getSurfaceHeight() {
        return 512;
    }

    void createOnScreenSurface(sp<Surface>& surface) {
        mComposerClient = new SurfaceComposerClient;
        ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());

        mSurfaceControl = mComposerClient->createSurface(
                String8("ProCameraTest StreamingImage Surface"),
                getSurfaceWidth(), getSurfaceHeight(),
                PIXEL_FORMAT_RGB_888, 0);

        ASSERT_TRUE(mSurfaceControl != NULL);
        ASSERT_TRUE(mSurfaceControl->isValid());

        SurfaceComposerClient::openGlobalTransaction();
        ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF));
        ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
        SurfaceComposerClient::closeGlobalTransaction();

        sp<ANativeWindow> window = mSurfaceControl->getSurface();
        surface = mSurfaceControl->getSurface();

        ASSERT_NE((void*)NULL, surface.get());
    }

};

sp<Thread> ProCameraTest::mTestThread;
@@ -260,6 +301,75 @@ TEST_F(ProCameraTest, LockingAsynchronous) {
    EXPECT_FALSE(mCamera->hasExclusiveLock());
}

// Stream directly to the screen.
TEST_F(ProCameraTest, StreamingImage) {
    if (HasFatalFailure()) {
        return;
    }
    char* displaySecsEnv = getenv("TEST_DISPLAY_SECS");
    if (displaySecsEnv != NULL) {
        mDisplaySecs = atoi(displaySecsEnv);
        if (mDisplaySecs < 0) {
            mDisplaySecs = 0;
        }
    } else {
        mDisplaySecs = 0;
    }

    sp<Surface> surface;
    sp<ANativeWindow> window;
    if (mDisplaySecs > 0) {
        createOnScreenSurface(/*out*/surface);
        window = surface;
    }
    int streamId = -1;
    EXPECT_OK(mCamera->createStream(/*width*/640, /*height*/480, TEST_FORMAT,
              window, &streamId));
    EXPECT_NE(-1, streamId);

    EXPECT_OK(mCamera->exclusiveTryLock());
    /* iterate in a loop submitting requests every frame.
     *  what kind of requests doesnt really matter, just whatever.
     */

    // it would probably be better to use CameraMetadata from camera service.
    camera_metadata_t *request = NULL;
    EXPECT_OK(mCamera->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
              /*out*/&request));
    EXPECT_NE((void*)NULL, request);

    /* FIXME: dont need this later, at which point the above should become an
       ASSERT_NE*/
    if(request == NULL) request = allocate_camera_metadata(10, 100);

    // set the output streams to just this stream ID

    // wow what a verbose API.
    // i would give a loaf of bread for
    //   metadata->updateOrInsert(keys.request.output.streams, streamId);
    camera_metadata_entry_t entry;
    uint32_t tag = static_cast<uint32_t>(ANDROID_REQUEST_OUTPUT_STREAMS);
    int find = find_camera_metadata_entry(request, tag, &entry);
    if (find == -ENOENT) {
        ASSERT_OK(add_camera_metadata_entry(request, tag, &streamId,
                  /*data_count*/1));
    } else {
        ASSERT_OK(update_camera_metadata_entry(request, entry.index, &streamId,
                  /*data_count*/1, &entry));
    }

    EXPECT_OK(mCamera->submitRequest(request, /*streaming*/true));

    sleep(mDisplaySecs);
    //should the window be empty until the buffer is flipped?
    //  that would certainly make sense


    free_camera_metadata(request);
    EXPECT_OK(mCamera->cancelStream(streamId));
    EXPECT_OK(mCamera->exclusiveUnlock());
}

}
}
}
+41 −0
Original line number Diff line number Diff line
@@ -109,6 +109,16 @@ public:
     * Lock free. Service maintains counter of streams.
     */
    status_t requestStream(int streamId);
    /**
     * Ask for a stream to be disabled.
     * Lock free. Service maintains counter of streams.
     * Errors: BAD_VALUE if unknown stream ID.
     */
// TODO: remove requestStream, its useless.

// TODO: rename cancelStream to deleteStream
// can probably do it with a grep/sed

    /**
      * Ask for a stream to be disabled.
      * Lock free. Service maintains counter of streams.
@@ -116,6 +126,37 @@ public:
      */
    status_t cancelStream(int streamId);

    /**
      * Create a new HW stream, whose sink will be the window.
      * Lock free. Service maintains counter of streams.
      * Errors: -EBUSY if too many streams created
      */
    status_t createStream(int width, int height, int format,
                          const sp<ANativeWindow>& window,
                          /*out*/
                          int* streamId);

    /**
      * Create a new HW stream, whose sink will be the SurfaceTexture.
      * Lock free. Service maintains counter of streams.
      * Errors: -EBUSY if too many streams created
      */
    status_t createStream(int width, int height, int format,
                          const sp<IGraphicBufferProducer>& bufferProducer,
                          /*out*/
                          int* streamId);

    // Create a request object from a template.
    status_t createDefaultRequest(int templateId,
                                 /*out*/
                                  camera_metadata** request) const;

    // Get number of cameras
    static int getNumberOfCameras();

    // Get static camera metadata
    static camera_metadata* getCameraInfo(int cameraId);

    sp<IProCameraUser>         remote();

protected: