summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camera/ProCamera.cpp68
-rw-r--r--camera/tests/ProCameraTests.cpp112
-rw-r--r--include/camera/ProCamera.h41
3 files changed, 220 insertions, 1 deletions
diff --git a/camera/ProCamera.cpp b/camera/ProCamera.cpp
index 8164188..26e4de9 100644
--- a/camera/ProCamera.cpp
+++ b/camera/ProCamera.cpp
@@ -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
diff --git a/camera/tests/ProCameraTests.cpp b/camera/tests/ProCameraTests.cpp
index adc3c75..d632b7e 100644
--- a/camera/tests/ProCameraTests.cpp
+++ b/camera/tests/ProCameraTests.cpp
@@ -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());
+}
+
}
}
}
diff --git a/include/camera/ProCamera.h b/include/camera/ProCamera.h
index 2dd01e3..7191b07 100644
--- a/include/camera/ProCamera.h
+++ b/include/camera/ProCamera.h
@@ -114,8 +114,49 @@ public:
* 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.
+ * Errors: BAD_VALUE if unknown stream ID.
+ */
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: