summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Deymo <deymo@google.com>2016-08-25 23:04:05 +0000
committerAlex Deymo <deymo@google.com>2016-08-25 23:04:05 +0000
commitd075131bcf1ee173db1ee2afff42bb1599e1f41a (patch)
treeba585ca93fbfce6ff92295f01a29b9771910b0c5
parent1c6c51d9a6d53689aee3e6b6f160b15cabdc429f (diff)
downloadcommon-d075131bcf1ee173db1ee2afff42bb1599e1f41a.tar.gz
Revert "Remove outdated brillo_camera example."
This reverts commit 1c6c51d9a6d53689aee3e6b6f160b15cabdc429f. Bug: 31098727 Change-Id: I9704e406dde2055536c68481b2cb1c45e8085762 Test: `make`
-rw-r--r--brillo_camera/Android.mk33
-rw-r--r--brillo_camera/main.cpp233
2 files changed, 266 insertions, 0 deletions
diff --git a/brillo_camera/Android.mk b/brillo_camera/Android.mk
new file mode 100644
index 0000000..950ed33
--- /dev/null
+++ b/brillo_camera/Android.mk
@@ -0,0 +1,33 @@
+# Copyright 2016 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := brillo_camera_client
+LOCAL_CFLAGS := -Wall -Werror
+LOCAL_SHARED_LIBRARIES := \
+ libbinder \
+ libbrillo \
+ libbrillo-binder \
+ libcamera_client \
+ libcamera_metadata \
+ libchrome \
+ libcutils \
+ libgui \
+ libutils
+LOCAL_SRC_FILES := \
+ main.cpp
+include $(BUILD_EXECUTABLE)
diff --git a/brillo_camera/main.cpp b/brillo_camera/main.cpp
new file mode 100644
index 0000000..6d5a3f8
--- /dev/null
+++ b/brillo_camera/main.cpp
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#include <iostream>
+#include <string>
+
+#include <base/at_exit.h>
+#include <base/bind.h>
+#include <base/logging.h>
+#include <binder/IServiceManager.h>
+#include <brillo/binder_watcher.h>
+#include <brillo/message_loops/base_message_loop.h>
+#include <brillo/syslog_logging.h>
+#include <camera/CameraMetadata.h>
+#include <camera/ICameraService.h>
+#include <camera/camera2/CaptureRequest.h>
+#include <camera/camera2/ICameraDeviceCallbacks.h>
+#include <camera/camera2/ICameraDeviceUser.h>
+#include <camera/camera2/OutputConfiguration.h>
+#include <gui/BufferQueue.h>
+#include <gui/BufferQueueConsumer.h>
+#include <gui/BufferQueueCore.h>
+#include <gui/BufferQueueProducer.h>
+#include <gui/CpuConsumer.h>
+#include <gui/Surface.h>
+#include <hardware/camera3.h>
+#include <system/camera_metadata.h>
+#include <utils/String16.h>
+#include <utils/String8.h>
+#include <utils/StrongPointer.h>
+
+using android::BnCameraDeviceCallbacks;
+using android::BufferQueue;
+using android::CameraMetadata;
+using android::CaptureRequest;
+using android::CaptureResultExtras;
+using android::CpuConsumer;
+using android::ICameraDeviceCallbacks;
+using android::ICameraDeviceUser;
+using android::ICameraService;
+using android::IGraphicBufferConsumer;
+using android::IGraphicBufferProducer;
+using android::OK;
+using android::String16;
+using android::Surface;
+using android::sp;
+
+namespace {
+
+// TODO(wiley) This constant should probably come out that client library, but
+// where is not obvious.
+const char kCameraServiceName[] = "media.camera";
+// TODO(wiley) This happens to be a format supported by both gralloc.default and
+// the golfish camera HAL, but I have no idea how to get this into
+// an actual viewable image.
+const int kHalPixelFormat = HAL_PIXEL_FORMAT_RAW16;
+
+class CameraDeviceCallbacks : public BnCameraDeviceCallbacks {
+ public:
+ explicit CameraDeviceCallbacks(brillo::MessageLoop* loop) : loop_(loop) {}
+
+ void onDeviceError(ICameraDeviceCallbacks::CameraErrorCode error_code,
+ const CaptureResultExtras& /* result_extras */) override {
+ LOG(ERROR) << "Received camera error = " << error_code;
+ loop_->BreakLoop();
+ }
+
+ void onDeviceIdle() override {
+ LOG(INFO) << "Camera device is idle";
+ }
+
+ void onCaptureStarted(
+ const CaptureResultExtras& /* result_extras */,
+ int64_t /* timestamp */) override {
+ LOG(INFO) << "Capture started.";
+ }
+
+ void onResultReceived(
+ const CameraMetadata& /* metadata */,
+ const CaptureResultExtras& /* result_extras */) override {
+ LOG(INFO) << "Capture result received";
+ result_received_ = true;
+ loop_->BreakLoop();
+ }
+
+ void onPrepared(int stream_id) override {
+ LOG(INFO) << "Camera is prepared for stream " << stream_id;
+ }
+
+ bool result_received() { return result_received_; }
+
+ private:
+ brillo::MessageLoop* loop_ = nullptr;
+ bool result_received_ = false;
+};
+
+} // namespace
+
+
+int main() {
+ base::AtExitManager at_exit_manager;
+ brillo::InitLog(brillo::kLogToStderr);
+
+ // Create a message loop.
+ brillo::BaseMessageLoop message_loop;
+
+ // Initialize a binder watcher.
+ brillo::BinderWatcher watcher(&message_loop);
+ watcher.Init();
+
+ LOG(INFO) << "Retrieving a binder for the camera service.";
+ sp<ICameraService> camera_service;
+ android::status_t status = android::getService(
+ String16(kCameraServiceName), &camera_service);
+ CHECK(status == OK)
+ << "Failed to get ICameraService binder from service manager!";
+
+ LOG(INFO) << "Asking how many cameras we have.";
+ const int32_t num_cameras = camera_service->getNumberOfCameras(
+ ICameraService::CAMERA_TYPE_ALL);
+ CHECK(num_cameras > 0)
+ << "ICameraService reports no cameras available";
+
+ const int camera_id = 0;
+ LOG(INFO) << "Connecting to camera " << camera_id;
+ sp<CameraDeviceCallbacks> camera_cb =
+ new CameraDeviceCallbacks(&message_loop);
+ sp<ICameraDeviceCallbacks> camera_cb_alias = camera_cb;
+ const String16 client_package_name("brillo");
+ sp<ICameraDeviceUser> camera_device_user;
+ status = camera_service->connectDevice(
+ camera_cb_alias, camera_id, client_package_name,
+ ICameraService::USE_CALLING_UID,
+ camera_device_user);
+ CHECK(status == OK) << "Failed to connect to camera id=" << camera_id
+ << " error=" << status;
+
+ LOG(INFO) << "Obtaining camera info";
+ CameraMetadata camera_metadata;
+ status = camera_device_user->getCameraInfo(&camera_metadata);
+ CHECK(status == OK) << "Failed to get camera info, error=" << status;
+
+ LOG(INFO) << "Calculating smallest stream configuration";
+ camera_metadata_entry streamConfigs =
+ camera_metadata.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
+ int32_t width = std::numeric_limits<int32_t>::max();
+ int32_t height = 1;
+ for (size_t i = 0; i < streamConfigs.count; i += 4) {
+ int32_t fmt = streamConfigs.data.i32[i];
+ int32_t inout = streamConfigs.data.i32[i + 3];
+ if (fmt == ANDROID_SCALER_AVAILABLE_FORMATS_RAW16 &&
+ inout == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT) {
+ int32_t w = streamConfigs.data.i32[i + 1];
+ int32_t h = streamConfigs.data.i32[i + 2];
+
+ if (width * height > w * h) {
+ width = w;
+ height = h;
+ }
+ }
+ }
+ LOG(INFO) << "width = " << width << " height = " << height;
+ CHECK(width != std::numeric_limits<int32_t>::max())
+ << "Unable to configure stream dimensions";
+
+ LOG(INFO) << "Obtaining buffer queue";
+ sp<IGraphicBufferProducer> buffer_producer = nullptr;
+ sp<IGraphicBufferConsumer> buffer_consumer = nullptr;
+ BufferQueue::createBufferQueue(&buffer_producer, &buffer_consumer);
+ CHECK(buffer_producer.get() != nullptr && buffer_consumer.get() != nullptr);
+
+ LOG(INFO) << "Creating buffer consumer";
+ sp<CpuConsumer> consumer = new CpuConsumer(
+ buffer_consumer, 1 /* one frame only */, true /* controlled by app */);
+ consumer->setDefaultBufferSize(width, height);
+ consumer->setDefaultBufferFormat(kHalPixelFormat);
+
+ LOG(INFO) << "Configuring the camera";
+ status = camera_device_user->beginConfigure();
+ CHECK(status == OK) << "Failed calling ICameraDeviceUser::beginConfigure()"
+ << " error = " << status;
+ android::OutputConfiguration output_configuration(
+ buffer_producer, CAMERA3_STREAM_ROTATION_0);
+ status = camera_device_user->createStream(output_configuration);
+ CHECK(status == OK) << "Failed calling ICameraDeviceUser::createStream()"
+ << " error = " << status;
+ status = camera_device_user->endConfigure(false /* isConstrainedHighSpeed */);
+ CHECK(status == OK) << "Failed calling ICameraDeviceUser::endConfigure()"
+ << " error = " << status;
+
+ LOG(INFO) << "Creating capture_request";
+ sp<CaptureRequest> capture_request = new CaptureRequest;
+ status = camera_device_user->createDefaultRequest(
+ CAMERA3_TEMPLATE_STILL_CAPTURE, &capture_request->mMetadata);
+ sp<Surface> surface = new Surface(
+ buffer_producer, true /* controlled by app */);
+ capture_request->mSurfaceList.push_back(surface);
+ capture_request->mIsReprocess = false;
+
+ LOG(INFO) << "Submitting capture request";
+ int64_t last_frame_number = 0;
+ status = camera_device_user->submitRequest(
+ capture_request, false, &last_frame_number);
+ CHECK(status == OK) << "Got error=" << status
+ << " while submitting capture request.";
+
+ LOG(INFO) << "Waiting for the camera to take a picture.";
+ // If we don't hear back from the camera for long enough, just time out.
+ message_loop.PostDelayedTask(
+ base::Bind(&brillo::BaseMessageLoop::BreakLoop,
+ base::Unretained(&message_loop)),
+ base::TimeDelta::FromSeconds(30));
+ message_loop.Run(); // We'll exit on a callback from the camera.
+
+ CHECK(camera_cb->result_received());
+
+ // TODO(wiley) render this image to a file to save somewhere.
+
+ return 0;
+}