blob: a2059f11d623182a2908e0e35d77336e35ea3bab [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <lib/async-loop/cpp/loop.h>
#include <lib/async/default.h>
#include <lib/fxl/logging.h>
#include "garnet/examples/camera/camera_client/camera_client.h"
using namespace fuchsia::camera::driver;
// This is a stand-in for some actual gralloc type service which would allocate
// the right type of memory for the application and return it as a vmo.
zx_status_t Gralloc(fuchsia::camera::driver::VideoFormat format,
uint32_t num_buffers,
fuchsia::sysmem::BufferCollectionInfo* buffer_collection) {
// In the future, some special alignment might happen here, or special
// memory allocated...
// Simple GetBufferSize. Only valid for simple formats:
size_t buffer_size = format.format.height * format.format.bytes_per_row;
buffer_collection->buffer_count = num_buffers;
buffer_collection->vmo_size = buffer_size;
buffer_collection->format.set_image(std::move(format.format));
zx_status_t status;
for (uint32_t i = 0; i < num_buffers; ++i) {
status = zx::vmo::create(buffer_size, 0, &buffer_collection->vmos[i]);
if (status != ZX_OK) {
FXL_LOG(ERROR) << "Failed to allocate Buffer Collection";
return status;
}
}
return ZX_OK;
}
zx_status_t run_camera() {
async::Loop loop(&kAsyncLoopConfigAttachToThread);
camera::Client client;
zx_status_t status = client.Open(0);
if (status != ZX_OK) {
FXL_LOG(ERROR) << "Couldn't open camera client (status " << status << ")";
return status;
}
std::vector<VideoFormat> formats;
zx_status_t driver_status;
uint32_t total_format_count;
uint32_t format_index = 0;
do {
fidl::VectorPtr<VideoFormat> formats_ptr;
status = client.camera()->GetFormats(format_index, &formats_ptr,
&total_format_count, &driver_status);
if (status != ZX_OK) {
FXL_LOG(ERROR) << "Couldn't get camera formats (status " << status << ")";
return status;
}
const std::vector<VideoFormat>& call_formats = formats_ptr.get();
for (auto&& f : call_formats) {
formats.push_back(f);
}
format_index += call_formats.size();
} while (formats.size() < total_format_count);
printf("Available formats: %d\n", (int)formats.size());
for (int i = 0; i < (int)formats.size(); i++) {
printf(
"format[%d] - width: %d, height: %d, stride: %lu\n",
i, formats[i].format.width, formats[i].format.height,
formats[i].format.bytes_per_row);
}
int frame_counter = 0;
fuchsia::camera::driver::StreamPtr stream;
static constexpr uint16_t kNumberOfBuffers = 8;
fuchsia::sysmem::BufferCollectionInfo buffer_collection;
status = Gralloc(formats[0], kNumberOfBuffers, &buffer_collection);
if (status != ZX_OK) {
FXL_LOG(ERROR) << "Couldn't allocate buffers (status " << status;
return status;
}
status = client.camera()->CreateStream(
std::move(buffer_collection), formats[0].rate,
stream.NewRequest());
if (status != ZX_OK) {
FXL_LOG(ERROR) << "Couldn't set camera format. status: " << status;
return status;
}
stream.events().OnFrameAvailable =
[&stream, &frame_counter](FrameAvailableEvent frame) {
printf("Received FrameNotify Event %d at index: %u\n",
frame_counter++, frame.buffer_id);
stream->ReleaseFrame(frame.buffer_id);
if (frame_counter > 10) {
stream->Stop();
}
};
stream->Start();
printf("all done, waiting for frames...\n");
loop.Run();
FXL_LOG(INFO) << "Camera Test A-OK!";
return ZX_OK;
}
int main(int argc, const char** argv) {
printf("hello camera client\n");
zx_status_t result = run_camera();
return result == ZX_OK ? 0 : -1;
}