Merge "Revert "Extend EVS interfaces and data types""
This commit is contained in:
commit
851a9ce685
20 changed files with 413 additions and 2229 deletions
|
@ -10,15 +10,13 @@ hidl_interface {
|
|||
"types.hal",
|
||||
"IEvsCamera.hal",
|
||||
"IEvsCameraStream.hal",
|
||||
"IEvsEnumerator.hal",
|
||||
],
|
||||
interfaces: [
|
||||
"android.hardware.automotive.evs@1.0",
|
||||
"android.hardware.camera.device@3.2",
|
||||
"android.hardware.graphics.common@1.0",
|
||||
"android.hardware.graphics.common@1.1",
|
||||
"android.hardware.graphics.common@1.2",
|
||||
"android.hidl.base@1.0",
|
||||
],
|
||||
gen_java: false,
|
||||
gen_java: true,
|
||||
}
|
||||
|
|
|
@ -25,14 +25,6 @@ import IEvsCameraStream;
|
|||
* Represents a single camera and is the primary interface for capturing images.
|
||||
*/
|
||||
interface IEvsCamera extends @1.0::IEvsCamera {
|
||||
/**
|
||||
* Returns the description of this camera.
|
||||
*
|
||||
* @return info The description of this camera. This must be the same value as
|
||||
* reported by EvsEnumerator::getCameraList_1_1().
|
||||
*/
|
||||
getCameraInfo_1_1() generates (CameraDesc info);
|
||||
|
||||
/**
|
||||
* Requests to pause EVS camera stream events.
|
||||
*
|
||||
|
@ -108,27 +100,7 @@ interface IEvsCamera extends @1.0::IEvsCamera {
|
|||
unsetMaster() generates (EvsResult result);
|
||||
|
||||
/**
|
||||
* Retrieves a list of parameters this camera supports.
|
||||
*
|
||||
* @return params A list of CameraParam that this camera supports.
|
||||
*/
|
||||
getParameterList() generates (vec<CameraParam> params);
|
||||
|
||||
/**
|
||||
* Requests a valid value range of a camera parameter
|
||||
*
|
||||
* @param id The identifier of camera parameter, CameraParam enum.
|
||||
*
|
||||
* @return min The lower bound of valid parameter value range.
|
||||
* @return max The upper bound of valid parameter value range.
|
||||
* @return step The resolution of values in valid range.
|
||||
*/
|
||||
getIntParameterRange(CameraParam id)
|
||||
generates (int32_t min, int32_t max, int32_t step);
|
||||
|
||||
/**
|
||||
* Requests to set a camera parameter. Only a request from the master
|
||||
* client will be processed successfully.
|
||||
* Requests to set a camera parameter.
|
||||
*
|
||||
* @param id The identifier of camera parameter, CameraParam enum.
|
||||
* value A desired parameter value.
|
||||
|
@ -142,7 +114,7 @@ interface IEvsCamera extends @1.0::IEvsCamera {
|
|||
* from what the client gives if, for example, the
|
||||
* driver does not support a target parameter.
|
||||
*/
|
||||
setIntParameter(CameraParam id, int32_t value)
|
||||
setParameter(CameraParam id, int32_t value)
|
||||
generates (EvsResult result, int32_t effectiveValue);
|
||||
|
||||
/**
|
||||
|
@ -154,5 +126,5 @@ interface IEvsCamera extends @1.0::IEvsCamera {
|
|||
* not supported.
|
||||
* value A value of requested camera parameter.
|
||||
*/
|
||||
getIntParameter(CameraParam id) generates(EvsResult result, int32_t value);
|
||||
getParameter(CameraParam id) generates(EvsResult result, int32_t value);
|
||||
};
|
||||
|
|
|
@ -17,32 +17,15 @@
|
|||
package android.hardware.automotive.evs@1.1;
|
||||
|
||||
import @1.0::IEvsCameraStream;
|
||||
import @1.1::BufferDesc;
|
||||
import @1.1::EvsEvent;
|
||||
|
||||
/**
|
||||
* Implemented on client side to receive asynchronous streaming event deliveries.
|
||||
*/
|
||||
interface IEvsCameraStream extends @1.0::IEvsCameraStream {
|
||||
|
||||
/**
|
||||
* Receives calls from the HAL each time a video frame is ready for inspection.
|
||||
* Buffer handles received by this method must be returned via calls to
|
||||
* IEvsCamera::doneWithFrame_1_1(). When the video stream is stopped via a call
|
||||
* to IEvsCamera::stopVideoStream(), this callback may continue to happen for
|
||||
* some time as the pipeline drains. Each frame must still be returned.
|
||||
* When the last frame in the stream has been delivered, STREAM_STOPPED
|
||||
* event must be delivered. No further frame deliveries may happen
|
||||
* thereafter.
|
||||
*
|
||||
* @param buffer a buffer descriptor of a delivered image frame.
|
||||
*/
|
||||
oneway deliverFrame_1_1(BufferDesc buffer);
|
||||
|
||||
/**
|
||||
* Receives calls from the HAL each time an event happens.
|
||||
*
|
||||
* @param event EVS event with possible event information.
|
||||
*/
|
||||
oneway notify(EvsEvent event);
|
||||
oneway notifyEvent(EvsEvent event);
|
||||
};
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 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.
|
||||
*/
|
||||
|
||||
package android.hardware.automotive.evs@1.1;
|
||||
|
||||
import IEvsCamera;
|
||||
import @1.0::IEvsEnumerator;
|
||||
import @1.0::EvsResult;
|
||||
import android.hardware.camera.device@3.2::Stream;
|
||||
|
||||
/**
|
||||
* Provides the mechanism for EVS camera discovery
|
||||
*/
|
||||
interface IEvsEnumerator extends @1.0::IEvsEnumerator {
|
||||
/**
|
||||
* Returns a list of all EVS cameras available to the system
|
||||
*
|
||||
* @return cameras A list of cameras availale for EVS service.
|
||||
*/
|
||||
getCameraList_1_1() generates (vec<CameraDesc> cameras);
|
||||
|
||||
/**
|
||||
* Gets the IEvsCamera associated with a cameraId from a CameraDesc
|
||||
*
|
||||
* Given a camera's unique cameraId from CameraDesc, returns the
|
||||
* IEvsCamera interface associated with the specified camera. When
|
||||
* done using the camera, the caller may release it by calling closeCamera().
|
||||
*
|
||||
* @param cameraId A unique identifier of the camera.
|
||||
* @param streamCfg A stream configuration the client wants to use.
|
||||
* @return evsCamera EvsCamera object associated with a given cameraId.
|
||||
* Returned object would be null if a camera device does
|
||||
* not support a given stream configuration or is already
|
||||
* configured differently by another client.
|
||||
*/
|
||||
openCamera_1_1(string cameraId, Stream streamCfg) generates (IEvsCamera evsCamera);
|
||||
};
|
|
@ -7,41 +7,25 @@ cc_binary {
|
|||
"service.cpp",
|
||||
"EvsCamera.cpp",
|
||||
"EvsEnumerator.cpp",
|
||||
"EvsDisplay.cpp",
|
||||
"ConfigManager.cpp",
|
||||
"ConfigManagerUtil.cpp",
|
||||
"EvsDisplay.cpp"
|
||||
],
|
||||
init_rc: ["android.hardware.automotive.evs@1.1-service.rc"],
|
||||
|
||||
shared_libs: [
|
||||
"android.hardware.automotive.evs@1.0",
|
||||
"android.hardware.automotive.evs@1.1",
|
||||
"android.hardware.camera.device@3.2",
|
||||
"libbase",
|
||||
"libbinder",
|
||||
"liblog",
|
||||
"libcutils",
|
||||
"libhardware",
|
||||
"libhidlbase",
|
||||
"liblog",
|
||||
"libui",
|
||||
"libutils",
|
||||
"libcamera_metadata",
|
||||
"libtinyxml2",
|
||||
],
|
||||
|
||||
cflags: [
|
||||
"-O0",
|
||||
"-g",
|
||||
],
|
||||
|
||||
required: [
|
||||
"evs_default_configuration.xml",
|
||||
],
|
||||
}
|
||||
|
||||
prebuilt_etc {
|
||||
name: "evs_default_configuration.xml",
|
||||
|
||||
src: "resources/evs_default_configuration.xml",
|
||||
sub_dir: "automotive/evs",
|
||||
}
|
||||
|
|
|
@ -1,487 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 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 <sstream>
|
||||
#include <fstream>
|
||||
#include <thread>
|
||||
|
||||
#include <hardware/gralloc.h>
|
||||
#include <utils/SystemClock.h>
|
||||
#include <android/hardware/camera/device/3.2/ICameraDevice.h>
|
||||
|
||||
#include "ConfigManager.h"
|
||||
|
||||
using ::android::hardware::camera::device::V3_2::StreamRotation;
|
||||
|
||||
|
||||
ConfigManager::~ConfigManager() {
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
|
||||
void ConfigManager::readCameraInfo(const XMLElement * const aCameraElem) {
|
||||
if (aCameraElem == nullptr) {
|
||||
ALOGW("XML file does not have required camera element");
|
||||
return;
|
||||
}
|
||||
|
||||
const XMLElement *curElem = aCameraElem->FirstChildElement();
|
||||
while (curElem != nullptr) {
|
||||
if (!strcmp(curElem->Name(), "group")) {
|
||||
/* camera group identifier */
|
||||
const char *group_id = curElem->FindAttribute("group_id")->Value();
|
||||
|
||||
/* create CameraGroup */
|
||||
unique_ptr<ConfigManager::CameraGroup> aCameraGroup(new ConfigManager::CameraGroup());
|
||||
|
||||
/* add a camera device to its group */
|
||||
addCameraDevices(curElem->FindAttribute("device_id")->Value(), aCameraGroup);
|
||||
|
||||
/* a list of camera stream configurations */
|
||||
const XMLElement *childElem =
|
||||
curElem->FirstChildElement("caps")->FirstChildElement("stream");
|
||||
while (childElem != nullptr) {
|
||||
/* read 5 attributes */
|
||||
const XMLAttribute *idAttr = childElem->FindAttribute("id");
|
||||
const XMLAttribute *widthAttr = childElem->FindAttribute("width");
|
||||
const XMLAttribute *heightAttr = childElem->FindAttribute("height");
|
||||
const XMLAttribute *fmtAttr = childElem->FindAttribute("format");
|
||||
const XMLAttribute *fpsAttr = childElem->FindAttribute("framerate");
|
||||
|
||||
const int32_t id = stoi(idAttr->Value());
|
||||
int32_t framerate = 0;
|
||||
if (fpsAttr != nullptr) {
|
||||
framerate = stoi(fpsAttr->Value());
|
||||
}
|
||||
|
||||
int32_t pixFormat;
|
||||
if (ConfigManagerUtil::convertToPixelFormat(fmtAttr->Value(),
|
||||
pixFormat)) {
|
||||
RawStreamConfiguration cfg = {
|
||||
id,
|
||||
stoi(widthAttr->Value()),
|
||||
stoi(heightAttr->Value()),
|
||||
pixFormat,
|
||||
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
|
||||
framerate
|
||||
};
|
||||
aCameraGroup->streamConfigurations[id] = cfg;
|
||||
}
|
||||
|
||||
childElem = childElem->NextSiblingElement("stream");
|
||||
}
|
||||
|
||||
/* camera group synchronization */
|
||||
const char *sync = curElem->FindAttribute("synchronized")->Value();
|
||||
aCameraGroup->synchronized =
|
||||
static_cast<bool>(strcmp(sync, "false"));
|
||||
|
||||
/* add a group to hash map */
|
||||
mCameraGroups[group_id] = std::move(aCameraGroup);
|
||||
} else if (!strcmp(curElem->Name(), "device")) {
|
||||
/* camera unique identifier */
|
||||
const char *id = curElem->FindAttribute("id")->Value();
|
||||
|
||||
/* camera mount location */
|
||||
const char *pos = curElem->FindAttribute("position")->Value();
|
||||
|
||||
/* store read camera module information */
|
||||
mCameraInfo[id] = readCameraDeviceInfo(curElem);
|
||||
|
||||
/* assign a camera device to a position group */
|
||||
mCameraPosition[pos].emplace(id);
|
||||
} else {
|
||||
/* ignore other device types */
|
||||
ALOGD("Unknown element %s is ignored", curElem->Name());
|
||||
}
|
||||
|
||||
curElem = curElem->NextSiblingElement();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unique_ptr<ConfigManager::CameraInfo>
|
||||
ConfigManager::readCameraDeviceInfo(const XMLElement *aDeviceElem) {
|
||||
if (aDeviceElem == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* create a CameraInfo to be filled */
|
||||
unique_ptr<ConfigManager::CameraInfo> aCamera(new ConfigManager::CameraInfo());
|
||||
|
||||
/* size information to allocate camera_metadata_t */
|
||||
size_t totalEntries = 0;
|
||||
size_t totalDataSize = 0;
|
||||
|
||||
/* read device capabilities */
|
||||
totalEntries +=
|
||||
readCameraCapabilities(aDeviceElem->FirstChildElement("caps"),
|
||||
aCamera,
|
||||
totalDataSize);
|
||||
|
||||
|
||||
/* read camera metadata */
|
||||
totalEntries +=
|
||||
readCameraMetadata(aDeviceElem->FirstChildElement("characteristics"),
|
||||
aCamera,
|
||||
totalDataSize);
|
||||
|
||||
/* construct camera_metadata_t */
|
||||
if (!constructCameraMetadata(aCamera, totalEntries, totalDataSize)) {
|
||||
ALOGW("Either failed to allocate memory or "
|
||||
"allocated memory was not large enough");
|
||||
}
|
||||
|
||||
return aCamera;
|
||||
}
|
||||
|
||||
|
||||
size_t ConfigManager::readCameraCapabilities(const XMLElement * const aCapElem,
|
||||
unique_ptr<ConfigManager::CameraInfo> &aCamera,
|
||||
size_t &dataSize) {
|
||||
if (aCapElem == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
string token;
|
||||
const XMLElement *curElem = nullptr;
|
||||
|
||||
/* a list of supported camera parameters/controls */
|
||||
curElem = aCapElem->FirstChildElement("supported_controls");
|
||||
if (curElem != nullptr) {
|
||||
const XMLElement *ctrlElem = curElem->FirstChildElement("control");
|
||||
while (ctrlElem != nullptr) {
|
||||
const char *nameAttr = ctrlElem->FindAttribute("name")->Value();;
|
||||
const int32_t minVal = stoi(ctrlElem->FindAttribute("min")->Value());
|
||||
const int32_t maxVal = stoi(ctrlElem->FindAttribute("max")->Value());
|
||||
|
||||
int32_t stepVal = 1;
|
||||
const XMLAttribute *stepAttr = ctrlElem->FindAttribute("step");
|
||||
if (stepAttr != nullptr) {
|
||||
stepVal = stoi(stepAttr->Value());
|
||||
}
|
||||
|
||||
CameraParam aParam;
|
||||
if (ConfigManagerUtil::convertToEvsCameraParam(nameAttr,
|
||||
aParam)) {
|
||||
aCamera->controls.emplace(
|
||||
aParam,
|
||||
make_tuple(minVal, maxVal, stepVal)
|
||||
);
|
||||
}
|
||||
|
||||
ctrlElem = ctrlElem->NextSiblingElement("control");
|
||||
}
|
||||
}
|
||||
|
||||
/* a list of camera stream configurations */
|
||||
curElem = aCapElem->FirstChildElement("stream");
|
||||
while (curElem != nullptr) {
|
||||
/* read 5 attributes */
|
||||
const XMLAttribute *idAttr = curElem->FindAttribute("id");
|
||||
const XMLAttribute *widthAttr = curElem->FindAttribute("width");
|
||||
const XMLAttribute *heightAttr = curElem->FindAttribute("height");
|
||||
const XMLAttribute *fmtAttr = curElem->FindAttribute("format");
|
||||
const XMLAttribute *fpsAttr = curElem->FindAttribute("framerate");
|
||||
|
||||
const int32_t id = stoi(idAttr->Value());
|
||||
int32_t framerate = 0;
|
||||
if (fpsAttr != nullptr) {
|
||||
framerate = stoi(fpsAttr->Value());
|
||||
}
|
||||
|
||||
int32_t pixFormat;
|
||||
if (ConfigManagerUtil::convertToPixelFormat(fmtAttr->Value(),
|
||||
pixFormat)) {
|
||||
RawStreamConfiguration cfg = {
|
||||
id,
|
||||
stoi(widthAttr->Value()),
|
||||
stoi(heightAttr->Value()),
|
||||
pixFormat,
|
||||
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
|
||||
framerate
|
||||
};
|
||||
aCamera->streamConfigurations[id] = cfg;
|
||||
}
|
||||
|
||||
curElem = curElem->NextSiblingElement("stream");
|
||||
}
|
||||
|
||||
dataSize = calculate_camera_metadata_entry_data_size(
|
||||
get_camera_metadata_tag_type(
|
||||
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS
|
||||
),
|
||||
aCamera->streamConfigurations.size() * kStreamCfgSz
|
||||
);
|
||||
|
||||
/* a single camera metadata entry contains multiple stream configurations */
|
||||
return dataSize > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
size_t ConfigManager::readCameraMetadata(const XMLElement * const aParamElem,
|
||||
unique_ptr<ConfigManager::CameraInfo> &aCamera,
|
||||
size_t &dataSize) {
|
||||
if (aParamElem == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const XMLElement *curElem = aParamElem->FirstChildElement("parameter");
|
||||
size_t numEntries = 0;
|
||||
camera_metadata_tag_t tag;
|
||||
while (curElem != nullptr) {
|
||||
if (!ConfigManagerUtil::convertToMetadataTag(curElem->FindAttribute("name")->Value(),
|
||||
tag)) {
|
||||
switch(tag) {
|
||||
case ANDROID_LENS_DISTORTION:
|
||||
case ANDROID_LENS_POSE_ROTATION:
|
||||
case ANDROID_LENS_POSE_TRANSLATION:
|
||||
case ANDROID_LENS_INTRINSIC_CALIBRATION: {
|
||||
/* float[] */
|
||||
size_t count = 0;
|
||||
void *data = ConfigManagerUtil::convertFloatArray(
|
||||
curElem->FindAttribute("size")->Value(),
|
||||
curElem->FindAttribute("value")->Value(),
|
||||
count
|
||||
);
|
||||
|
||||
aCamera->cameraMetadata[tag] =
|
||||
make_pair(make_unique<void *>(data), count);
|
||||
|
||||
++numEntries;
|
||||
dataSize += calculate_camera_metadata_entry_data_size(
|
||||
get_camera_metadata_tag_type(tag), count
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
ALOGW("Parameter %s is not supported",
|
||||
curElem->FindAttribute("name")->Value());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
curElem = curElem->NextSiblingElement("parameter");
|
||||
}
|
||||
|
||||
return numEntries;
|
||||
}
|
||||
|
||||
|
||||
bool ConfigManager::constructCameraMetadata(unique_ptr<CameraInfo> &aCamera,
|
||||
const size_t totalEntries,
|
||||
const size_t totalDataSize) {
|
||||
if (!aCamera->allocate(totalEntries, totalDataSize)) {
|
||||
ALOGE("Failed to allocate memory for camera metadata");
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t numStreamConfigs = aCamera->streamConfigurations.size();
|
||||
unique_ptr<int32_t[]> data(new int32_t[kStreamCfgSz * numStreamConfigs]);
|
||||
int32_t *ptr = data.get();
|
||||
for (auto &cfg : aCamera->streamConfigurations) {
|
||||
for (auto i = 0; i < kStreamCfgSz; ++i) {
|
||||
*ptr++ = cfg.second[i];
|
||||
}
|
||||
}
|
||||
int32_t err = add_camera_metadata_entry(aCamera->characteristics,
|
||||
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
|
||||
data.get(),
|
||||
numStreamConfigs * kStreamCfgSz);
|
||||
|
||||
if (err) {
|
||||
ALOGE("Failed to add stream configurations to metadata, ignored");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool success = true;
|
||||
for (auto &[tag, entry] : aCamera->cameraMetadata) {
|
||||
/* try to add new camera metadata entry */
|
||||
int32_t err = add_camera_metadata_entry(aCamera->characteristics,
|
||||
tag,
|
||||
entry.first.get(),
|
||||
entry.second);
|
||||
if (err) {
|
||||
ALOGE("Failed to add an entry with a tag 0x%X", tag);
|
||||
|
||||
/* may exceed preallocated capacity */
|
||||
ALOGE("Camera metadata has %ld / %ld entries and %ld / %ld bytes are filled",
|
||||
get_camera_metadata_entry_count(aCamera->characteristics),
|
||||
get_camera_metadata_entry_capacity(aCamera->characteristics),
|
||||
get_camera_metadata_data_count(aCamera->characteristics),
|
||||
get_camera_metadata_data_capacity(aCamera->characteristics));
|
||||
ALOGE("\tCurrent metadata entry requires %ld bytes",
|
||||
calculate_camera_metadata_entry_data_size(tag, entry.second));
|
||||
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
ALOGV("Camera metadata has %ld / %ld entries and %ld / %ld bytes are filled",
|
||||
get_camera_metadata_entry_count(aCamera->characteristics),
|
||||
get_camera_metadata_entry_capacity(aCamera->characteristics),
|
||||
get_camera_metadata_data_count(aCamera->characteristics),
|
||||
get_camera_metadata_data_capacity(aCamera->characteristics));
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
void ConfigManager::readSystemInfo(const XMLElement * const aSysElem) {
|
||||
if (aSysElem == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Please note that this function assumes that a given system XML element
|
||||
* and its child elements follow DTD. If it does not, it will cause a
|
||||
* segmentation fault due to the failure of finding expected attributes.
|
||||
*/
|
||||
|
||||
/* read number of cameras available in the system */
|
||||
const XMLElement *xmlElem = aSysElem->FirstChildElement("num_cameras");
|
||||
if (xmlElem != nullptr) {
|
||||
mSystemInfo.numCameras =
|
||||
stoi(xmlElem->FindAttribute("value")->Value());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ConfigManager::readDisplayInfo(const XMLElement * const aDisplayElem) {
|
||||
if (aDisplayElem == nullptr) {
|
||||
ALOGW("XML file does not have required camera element");
|
||||
return;
|
||||
}
|
||||
|
||||
const XMLElement *curDev = aDisplayElem->FirstChildElement("device");
|
||||
while (curDev != nullptr) {
|
||||
const char *id = curDev->FindAttribute("id")->Value();
|
||||
//const char *pos = curDev->FirstAttribute("position")->Value();
|
||||
|
||||
unique_ptr<DisplayInfo> dpy(new DisplayInfo());
|
||||
if (dpy == nullptr) {
|
||||
ALOGE("Failed to allocate memory for DisplayInfo");
|
||||
return;
|
||||
}
|
||||
|
||||
const XMLElement *cap = curDev->FirstChildElement("caps");
|
||||
if (cap != nullptr) {
|
||||
const XMLElement *curStream = cap->FirstChildElement("stream");
|
||||
while (curStream != nullptr) {
|
||||
/* read 4 attributes */
|
||||
const XMLAttribute *idAttr = curStream->FindAttribute("id");
|
||||
const XMLAttribute *widthAttr = curStream->FindAttribute("width");
|
||||
const XMLAttribute *heightAttr = curStream->FindAttribute("height");
|
||||
const XMLAttribute *fmtAttr = curStream->FindAttribute("format");
|
||||
|
||||
const int32_t id = stoi(idAttr->Value());
|
||||
int32_t pixFormat;
|
||||
if (ConfigManagerUtil::convertToPixelFormat(fmtAttr->Value(),
|
||||
pixFormat)) {
|
||||
RawStreamConfiguration cfg = {
|
||||
id,
|
||||
stoi(widthAttr->Value()),
|
||||
stoi(heightAttr->Value()),
|
||||
pixFormat,
|
||||
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT,
|
||||
0 // unused
|
||||
};
|
||||
dpy->streamConfigurations[id] = cfg;
|
||||
}
|
||||
|
||||
curStream = curStream->NextSiblingElement("stream");
|
||||
}
|
||||
}
|
||||
|
||||
mDisplayInfo[id] = std::move(dpy);
|
||||
curDev = curDev->NextSiblingElement("device");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool ConfigManager::readConfigDataFromXML() noexcept {
|
||||
XMLDocument xmlDoc;
|
||||
|
||||
const int64_t parsingStart = android::elapsedRealtimeNano();
|
||||
|
||||
/* load and parse a configuration file */
|
||||
xmlDoc.LoadFile(mConfigFilePath);
|
||||
if (xmlDoc.ErrorID() != XML_SUCCESS) {
|
||||
ALOGE("Failed to load and/or parse a configuration file, %s", xmlDoc.ErrorStr());
|
||||
return false;
|
||||
}
|
||||
|
||||
/* retrieve the root element */
|
||||
const XMLElement *rootElem = xmlDoc.RootElement();
|
||||
if (strcmp(rootElem->Name(), "configuration")) {
|
||||
ALOGE("A configuration file is not in the required format. "
|
||||
"See /etc/automotive/evs/evs_configuration.dtd");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* parse camera information; this needs to be done before reading system
|
||||
* information
|
||||
*/
|
||||
readCameraInfo(rootElem->FirstChildElement("camera"));
|
||||
|
||||
/* parse system information */
|
||||
readSystemInfo(rootElem->FirstChildElement("system"));
|
||||
|
||||
/* parse display information */
|
||||
readDisplayInfo(rootElem->FirstChildElement("display"));
|
||||
|
||||
const int64_t parsingEnd = android::elapsedRealtimeNano();
|
||||
ALOGI("Parsing configuration file takes %lf (ms)",
|
||||
(double)(parsingEnd - parsingStart) / 1000000.0);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ConfigManager::addCameraDevices(const char *devices,
|
||||
unique_ptr<CameraGroup> &aGroup) {
|
||||
stringstream device_list(devices);
|
||||
string token;
|
||||
while (getline(device_list, token, ',')) {
|
||||
aGroup->devices.emplace(token);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<ConfigManager> ConfigManager::Create(const char *path) {
|
||||
unique_ptr<ConfigManager> cfgMgr(new ConfigManager(path));
|
||||
|
||||
/*
|
||||
* Read a configuration from XML file
|
||||
*
|
||||
* If this is too slow, ConfigManager::readConfigDataFromBinary() and
|
||||
* ConfigManager::writeConfigDataToBinary()can serialize CameraInfo object
|
||||
* to the filesystem and construct CameraInfo instead; this was
|
||||
* evaluated as 10x faster.
|
||||
*/
|
||||
if (!cfgMgr->readConfigDataFromXML()) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return cfgMgr;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,336 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 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.
|
||||
*/
|
||||
#ifndef CONFIG_MANAGER_H
|
||||
#define CONFIG_MANAGER_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <tinyxml2.h>
|
||||
|
||||
#include <system/camera_metadata.h>
|
||||
#include <log/log.h>
|
||||
#include <android/hardware/automotive/evs/1.1/types.h>
|
||||
|
||||
#include "ConfigManagerUtil.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace tinyxml2;
|
||||
|
||||
using ::android::hardware::hidl_vec;
|
||||
using ::android::hardware::camera::device::V3_2::Stream;
|
||||
using ::android::hardware::automotive::evs::V1_1::CameraParam;
|
||||
|
||||
/*
|
||||
* Plese note that this is different from what is defined in
|
||||
* libhardware/modules/camera/3_4/metadata/types.h; this has one additional
|
||||
* field to store a framerate.
|
||||
*/
|
||||
const size_t kStreamCfgSz = 6;
|
||||
typedef std::array<int32_t, kStreamCfgSz> RawStreamConfiguration;
|
||||
|
||||
class ConfigManager {
|
||||
public:
|
||||
static std::unique_ptr<ConfigManager> Create(const char *path = "");
|
||||
ConfigManager(const ConfigManager&) = delete;
|
||||
ConfigManager& operator=(const ConfigManager&) = delete;
|
||||
|
||||
virtual ~ConfigManager();
|
||||
|
||||
/* Camera device's capabilities and metadata */
|
||||
class CameraInfo {
|
||||
public:
|
||||
CameraInfo() :
|
||||
characteristics(nullptr) {
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
virtual ~CameraInfo() {
|
||||
free_camera_metadata(characteristics);
|
||||
}
|
||||
|
||||
/* Allocate memory for camera_metadata_t */
|
||||
bool allocate(size_t entry_cap, size_t data_cap) {
|
||||
if (characteristics != nullptr) {
|
||||
ALOGE("Camera metadata is already allocated");
|
||||
return false;
|
||||
}
|
||||
|
||||
characteristics = allocate_camera_metadata(entry_cap, data_cap);
|
||||
return characteristics != nullptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* List of supported controls that the master client can program.
|
||||
* Paraemters are stored with its valid range
|
||||
*/
|
||||
unordered_map<CameraParam,
|
||||
tuple<int32_t, int32_t, int32_t>> controls;
|
||||
|
||||
/* List of supported frame rates */
|
||||
unordered_set<int32_t> frameRates;
|
||||
|
||||
/*
|
||||
* List of supported output stream configurations; each array stores
|
||||
* format, width, height, and direction values in the order.
|
||||
*/
|
||||
unordered_map<int32_t, RawStreamConfiguration> streamConfigurations;
|
||||
|
||||
/*
|
||||
* Internal storage for camera metadata. Each entry holds a pointer to
|
||||
* data and number of elements
|
||||
*/
|
||||
unordered_map<camera_metadata_tag_t,
|
||||
pair<unique_ptr<void *>, size_t>> cameraMetadata;
|
||||
|
||||
/* Camera module characteristics */
|
||||
camera_metadata_t *characteristics;
|
||||
};
|
||||
|
||||
class CameraGroup {
|
||||
public:
|
||||
CameraGroup() {}
|
||||
|
||||
/* ID of member camera devices */
|
||||
unordered_set<string> devices;
|
||||
|
||||
/* The capture operation of member camera devices are synchronized */
|
||||
bool synchronized = false;
|
||||
|
||||
/*
|
||||
* List of stream configurations that are supposed by all camera devices
|
||||
* in this group.
|
||||
*/
|
||||
unordered_map<int32_t, RawStreamConfiguration> streamConfigurations;
|
||||
};
|
||||
|
||||
class SystemInfo {
|
||||
public:
|
||||
/* number of available cameras */
|
||||
int32_t numCameras = 0;
|
||||
};
|
||||
|
||||
class DisplayInfo {
|
||||
public:
|
||||
/*
|
||||
* List of supported input stream configurations; each array stores
|
||||
* format, width, height, and direction values in the order.
|
||||
*/
|
||||
unordered_map<int32_t, RawStreamConfiguration> streamConfigurations;
|
||||
};
|
||||
|
||||
/*
|
||||
* Return system information
|
||||
*
|
||||
* @return SystemInfo
|
||||
* Constant reference of SystemInfo.
|
||||
*/
|
||||
const SystemInfo &getSystemInfo() {
|
||||
return mSystemInfo;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a list of cameras
|
||||
*
|
||||
* This function assumes that it is not being called frequently.
|
||||
*
|
||||
* @return vector<string>
|
||||
* A vector that contains unique camera device identifiers.
|
||||
*/
|
||||
vector<string> getCameraList() {
|
||||
vector<string> aList;
|
||||
for (auto &v : mCameraInfo) {
|
||||
aList.emplace_back(v.first);
|
||||
}
|
||||
|
||||
return aList;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return a list of cameras
|
||||
*
|
||||
* @return CameraGroup
|
||||
* A pointer to a camera group identified by a given id.
|
||||
*/
|
||||
unique_ptr<CameraGroup>& getCameraGroup(const string& gid) {
|
||||
return mCameraGroups[gid];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return a camera metadata
|
||||
*
|
||||
* @param cameraId
|
||||
* Unique camera node identifier in string
|
||||
*
|
||||
* @return unique_ptr<CameraInfo>
|
||||
* A pointer to CameraInfo that is associated with a given camera
|
||||
* ID. This returns a null pointer if this does not recognize a
|
||||
* given camera identifier.
|
||||
*/
|
||||
unique_ptr<CameraInfo>& getCameraInfo(const string cameraId) noexcept {
|
||||
return mCameraInfo[cameraId];
|
||||
}
|
||||
|
||||
private:
|
||||
/* Constructors */
|
||||
ConfigManager(const char *xmlPath) :
|
||||
mConfigFilePath(xmlPath) {
|
||||
}
|
||||
|
||||
/* System configuration */
|
||||
SystemInfo mSystemInfo;
|
||||
|
||||
/* Internal data structure for camera device information */
|
||||
unordered_map<string, unique_ptr<CameraInfo>> mCameraInfo;
|
||||
|
||||
/* Internal data structure for camera device information */
|
||||
unordered_map<string, unique_ptr<DisplayInfo>> mDisplayInfo;
|
||||
|
||||
/* Camera groups are stored in <groud id, CameraGroup> hash map */
|
||||
unordered_map<string, unique_ptr<CameraGroup>> mCameraGroups;
|
||||
|
||||
/*
|
||||
* Camera positions are stored in <position, camera id set> hash map.
|
||||
* The position must be one of front, rear, left, and right.
|
||||
*/
|
||||
unordered_map<string, unordered_set<string>> mCameraPosition;
|
||||
|
||||
/* A path to XML configuration file */
|
||||
const char *mConfigFilePath;
|
||||
|
||||
/*
|
||||
* Parse a given EVS configuration file and store the information
|
||||
* internally.
|
||||
*
|
||||
* @return bool
|
||||
* True if it completes parsing a file successfully.
|
||||
*/
|
||||
bool readConfigDataFromXML() noexcept;
|
||||
|
||||
/*
|
||||
* read the information of the vehicle
|
||||
*
|
||||
* @param aSysElem
|
||||
* A pointer to "system" XML element.
|
||||
*/
|
||||
void readSystemInfo(const XMLElement * const aSysElem);
|
||||
|
||||
/*
|
||||
* read the information of camera devices
|
||||
*
|
||||
* @param aCameraElem
|
||||
* A pointer to "camera" XML element that may contain multiple
|
||||
* "device" elements.
|
||||
*/
|
||||
void readCameraInfo(const XMLElement * const aCameraElem);
|
||||
|
||||
/*
|
||||
* read display device information
|
||||
*
|
||||
* @param aDisplayElem
|
||||
* A pointer to "display" XML element that may contain multiple
|
||||
* "device" elements.
|
||||
*/
|
||||
void readDisplayInfo(const XMLElement * const aDisplayElem);
|
||||
|
||||
/*
|
||||
* read camera device information
|
||||
*
|
||||
* @param aDeviceElem
|
||||
* A pointer to "device" XML element that contains camera module
|
||||
* capability info and its characteristics.
|
||||
*
|
||||
* @return unique_ptr<CameraInfo>
|
||||
* A pointer to CameraInfo class that contains camera module
|
||||
* capability and characteristics. Please note that this transfers
|
||||
* the ownership of created CameraInfo to the caller.
|
||||
*/
|
||||
unique_ptr<CameraInfo> readCameraDeviceInfo(const XMLElement *aDeviceElem);
|
||||
|
||||
/*
|
||||
* read camera metadata
|
||||
*
|
||||
* @param aCapElem
|
||||
* A pointer to "cap" XML element.
|
||||
* @param aCamera
|
||||
* A pointer to CameraInfo that is being filled by this method.
|
||||
* @param dataSize
|
||||
* Required size of memory to store camera metadata found in this
|
||||
* method. This is calculated in this method and returned to the
|
||||
* caller for camera_metadata allocation.
|
||||
*
|
||||
* @return size_t
|
||||
* Number of camera metadata entries
|
||||
*/
|
||||
size_t readCameraCapabilities(const XMLElement * const aCapElem,
|
||||
unique_ptr<CameraInfo> &aCamera,
|
||||
size_t &dataSize);
|
||||
|
||||
/*
|
||||
* read camera metadata
|
||||
*
|
||||
* @param aParamElem
|
||||
* A pointer to "characteristics" XML element.
|
||||
* @param aCamera
|
||||
* A pointer to CameraInfo that is being filled by this method.
|
||||
* @param dataSize
|
||||
* Required size of memory to store camera metadata found in this
|
||||
* method.
|
||||
*
|
||||
* @return size_t
|
||||
* Number of camera metadata entries
|
||||
*/
|
||||
size_t readCameraMetadata(const XMLElement * const aParamElem,
|
||||
unique_ptr<CameraInfo> &aCamera,
|
||||
size_t &dataSize);
|
||||
|
||||
/*
|
||||
* construct camera_metadata_t from camera capabilities and metadata
|
||||
*
|
||||
* @param aCamera
|
||||
* A pointer to CameraInfo that is being filled by this method.
|
||||
* @param totalEntries
|
||||
* Number of camera metadata entries to be added.
|
||||
* @param totalDataSize
|
||||
* Sum of sizes of camera metadata entries to be added.
|
||||
*
|
||||
* @return bool
|
||||
* False if either it fails to allocate memory for camera metadata
|
||||
* or its size is not large enough to add all found camera metadata
|
||||
* entries.
|
||||
*/
|
||||
bool constructCameraMetadata(unique_ptr<CameraInfo> &aCamera,
|
||||
const size_t totalEntries,
|
||||
const size_t totalDataSize);
|
||||
|
||||
/*
|
||||
* parse a comma-separated list of camera devices and add them to
|
||||
* CameraGroup.
|
||||
*
|
||||
* @param devices
|
||||
* A comma-separated list of camera device identifiers.
|
||||
* @param aGroup
|
||||
* Camera group which cameras will be added to.
|
||||
*/
|
||||
void addCameraDevices(const char *devices,
|
||||
unique_ptr<CameraGroup> &aGroup);
|
||||
};
|
||||
#endif // CONFIG_MANAGER_H
|
||||
|
|
@ -1,131 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 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 "ConfigManagerUtil.h"
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
#include <log/log.h>
|
||||
#include <system/graphics-base-v1.0.h>
|
||||
|
||||
|
||||
bool ConfigManagerUtil::convertToEvsCameraParam(const string &id,
|
||||
CameraParam &camParam) {
|
||||
string trimmed = ConfigManagerUtil::trimString(id);
|
||||
bool success = true;
|
||||
|
||||
if (!trimmed.compare("BRIGHTNESS")) {
|
||||
camParam = CameraParam::BRIGHTNESS;
|
||||
} else if (!trimmed.compare("CONTRAST")) {
|
||||
camParam = CameraParam::CONTRAST;
|
||||
} else if (!trimmed.compare("AUTOGAIN")) {
|
||||
camParam = CameraParam::AUTOGAIN;
|
||||
} else if (!trimmed.compare("GAIN")) {
|
||||
camParam = CameraParam::GAIN;
|
||||
} else if (!trimmed.compare("AUTO_WHITE_BALANCE")) {
|
||||
camParam = CameraParam::AUTO_WHITE_BALANCE;
|
||||
} else if (!trimmed.compare("WHITE_BALANCE_TEMPERATURE")) {
|
||||
camParam = CameraParam::WHITE_BALANCE_TEMPERATURE;
|
||||
} else if (!trimmed.compare("SHARPNESS")) {
|
||||
camParam = CameraParam::SHARPNESS;
|
||||
} else if (!trimmed.compare("AUTO_EXPOSURE")) {
|
||||
camParam = CameraParam::AUTO_EXPOSURE;
|
||||
} else if (!trimmed.compare("ABSOLUTE_EXPOSURE")) {
|
||||
camParam = CameraParam::ABSOLUTE_EXPOSURE;
|
||||
} else if (!trimmed.compare("ABSOLUTE_FOCUS")) {
|
||||
camParam = CameraParam::ABSOLUTE_FOCUS;
|
||||
} else if (!trimmed.compare("AUTO_FOCUS")) {
|
||||
camParam = CameraParam::AUTO_FOCUS;
|
||||
} else if (!trimmed.compare("ABSOLUTE_ZOOM")) {
|
||||
camParam = CameraParam::ABSOLUTE_ZOOM;
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
bool ConfigManagerUtil::convertToPixelFormat(const string &format,
|
||||
int32_t &pixFormat) {
|
||||
string trimmed = ConfigManagerUtil::trimString(format);
|
||||
bool success = true;
|
||||
|
||||
if (!trimmed.compare("RGBA_8888")) {
|
||||
pixFormat = HAL_PIXEL_FORMAT_RGBA_8888;
|
||||
} else if (!trimmed.compare("YCRCB_420_SP")) {
|
||||
pixFormat = HAL_PIXEL_FORMAT_YCRCB_420_SP;
|
||||
} else if (!trimmed.compare("YCBCR_422_I")) {
|
||||
pixFormat = HAL_PIXEL_FORMAT_YCBCR_422_I;
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
bool ConfigManagerUtil::convertToMetadataTag(const char *name,
|
||||
camera_metadata_tag &aTag) {
|
||||
if (!strcmp(name, "LENS_DISTORTION")) {
|
||||
aTag = ANDROID_LENS_DISTORTION;
|
||||
} else if (!strcmp(name, "LENS_INTRINSIC_CALIBRATION")) {
|
||||
aTag = ANDROID_LENS_INTRINSIC_CALIBRATION;
|
||||
} else if (!strcmp(name, "LENS_POSE_ROTATION")) {
|
||||
aTag = ANDROID_LENS_POSE_ROTATION;
|
||||
} else if (!strcmp(name, "LENS_POSE_TRANSLATION")) {
|
||||
aTag = ANDROID_LENS_POSE_TRANSLATION;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
float *ConfigManagerUtil::convertFloatArray(const char *sz, const char *vals,
|
||||
size_t &count, const char delimiter) {
|
||||
string size_string(sz);
|
||||
string value_string(vals);
|
||||
|
||||
count = stoi(size_string);
|
||||
float *result = new float[count];
|
||||
stringstream values(value_string);
|
||||
|
||||
int32_t idx = 0;
|
||||
string token;
|
||||
while (getline(values, token, delimiter)) {
|
||||
result[idx++] = stof(token);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
string ConfigManagerUtil::trimString(const string &src, const string &ws) {
|
||||
const auto s = src.find_first_not_of(ws);
|
||||
if (s == string::npos) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const auto e = src.find_last_not_of(ws);
|
||||
const auto r = e - s + 1;
|
||||
|
||||
return src.substr(s, r);
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 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.
|
||||
*/
|
||||
#ifndef CONFIG_MANAGER_UTIL_H
|
||||
#define CONFIG_MANAGER_UTIL_H
|
||||
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <system/camera_metadata.h>
|
||||
#include <android/hardware/automotive/evs/1.1/types.h>
|
||||
|
||||
using namespace std;
|
||||
using ::android::hardware::automotive::evs::V1_1::CameraParam;
|
||||
|
||||
|
||||
class ConfigManagerUtil {
|
||||
public:
|
||||
/**
|
||||
* Convert a given string into V4L2_CID_*
|
||||
*/
|
||||
static bool convertToEvsCameraParam(const string &id,
|
||||
CameraParam &camParam);
|
||||
/**
|
||||
* Convert a given string into android.hardware.graphics.common.PixelFormat
|
||||
*/
|
||||
static bool convertToPixelFormat(const string &format,
|
||||
int32_t &pixelFormat);
|
||||
/**
|
||||
* Convert a given string into corresponding camera metadata data tag defined in
|
||||
* system/media/camera/include/system/camera_metadta_tags.h
|
||||
*/
|
||||
static bool convertToMetadataTag(const char *name,
|
||||
camera_metadata_tag &aTag);
|
||||
/**
|
||||
* Convert a given string into a floating value array
|
||||
*/
|
||||
static float *convertFloatArray(const char *sz,
|
||||
const char *vals,
|
||||
size_t &count,
|
||||
const char delimiter = ',');
|
||||
/**
|
||||
* Trim a string
|
||||
*/
|
||||
static string trimString(const string &src,
|
||||
const string &ws = " \n\r\t\f\v");
|
||||
};
|
||||
|
||||
#endif // CONFIG_MANAGER_UTIL_H
|
||||
|
|
@ -40,21 +40,28 @@ const char EvsCamera::kCameraName_Backup[] = "backup";
|
|||
const unsigned MAX_BUFFERS_IN_FLIGHT = 100;
|
||||
|
||||
|
||||
EvsCamera::EvsCamera(const char *id,
|
||||
unique_ptr<ConfigManager::CameraInfo> &camInfo) :
|
||||
EvsCamera::EvsCamera(const char *id) :
|
||||
mFramesAllowed(0),
|
||||
mFramesInUse(0),
|
||||
mStreamState(STOPPED),
|
||||
mCameraInfo(camInfo) {
|
||||
mStreamState(STOPPED) {
|
||||
|
||||
ALOGD("EvsCamera instantiated");
|
||||
|
||||
/* set a camera id */
|
||||
mDescription.v1.cameraId = id;
|
||||
mDescription.cameraId = id;
|
||||
|
||||
/* set camera metadata */
|
||||
mDescription.metadata.setToExternal((uint8_t *)camInfo->characteristics,
|
||||
get_camera_metadata_size(camInfo->characteristics));
|
||||
// Set up dummy data for testing
|
||||
if (mDescription.cameraId == kCameraName_Backup) {
|
||||
mWidth = 640; // full NTSC/VGA
|
||||
mHeight = 480; // full NTSC/VGA
|
||||
mDescription.vendorFlags = 0xFFFFFFFF; // Arbitrary value
|
||||
} else {
|
||||
mWidth = 320; // 1/2 NTSC/VGA
|
||||
mHeight = 240; // 1/2 NTSC/VGA
|
||||
}
|
||||
|
||||
mFormat = HAL_PIXEL_FORMAT_RGBA_8888;
|
||||
mUsage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_CAMERA_WRITE |
|
||||
GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_RARELY;
|
||||
}
|
||||
|
||||
|
||||
|
@ -102,7 +109,7 @@ Return<void> EvsCamera::getCameraInfo(getCameraInfo_cb _hidl_cb) {
|
|||
ALOGD("getCameraInfo");
|
||||
|
||||
// Send back our self description
|
||||
_hidl_cb(mDescription.v1);
|
||||
_hidl_cb(mDescription);
|
||||
return Void();
|
||||
}
|
||||
|
||||
|
@ -187,7 +194,7 @@ Return<void> EvsCamera::stopVideoStream() {
|
|||
|
||||
// Block outside the mutex until the "stop" flag has been acknowledged
|
||||
// We won't send any more frames, but the client might still get some already in flight
|
||||
ALOGD("Waiting for stream thread to end...");
|
||||
ALOGD("Waiting for stream thread to end..");
|
||||
lock.unlock();
|
||||
mCaptureThread.join();
|
||||
lock.lock();
|
||||
|
@ -231,15 +238,6 @@ Return<EvsResult> EvsCamera::setExtendedInfo(uint32_t /*opaqueIdentifier*/, int3
|
|||
|
||||
|
||||
// Methods from ::android::hardware::automotive::evs::V1_1::IEvsCamera follow.
|
||||
Return<void> EvsCamera::getCameraInfo_1_1(getCameraInfo_1_1_cb _hidl_cb) {
|
||||
ALOGD("getCameraInfo_1_1");
|
||||
|
||||
// Send back our self description
|
||||
_hidl_cb(mDescription);
|
||||
return Void();
|
||||
}
|
||||
|
||||
|
||||
Return<EvsResult> EvsCamera::doneWithFrame_1_1(const BufferDesc_1_1& bufDesc) {
|
||||
std::lock_guard <std::mutex> lock(mAccessLock);
|
||||
returnBuffer(bufDesc.bufferId, bufDesc.buffer.nativeHandle);
|
||||
|
@ -280,29 +278,8 @@ Return<EvsResult> EvsCamera::unsetMaster() {
|
|||
}
|
||||
|
||||
|
||||
Return<void> EvsCamera::getParameterList(getParameterList_cb _hidl_cb) {
|
||||
hidl_vec<CameraParam> hidlCtrls;
|
||||
hidlCtrls.resize(mCameraInfo->controls.size());
|
||||
unsigned idx = 0;
|
||||
for (auto& [cid, cfg] : mCameraInfo->controls) {
|
||||
hidlCtrls[idx++] = cid;
|
||||
}
|
||||
|
||||
_hidl_cb(hidlCtrls);
|
||||
return Void();
|
||||
}
|
||||
|
||||
|
||||
Return<void> EvsCamera::getIntParameterRange(CameraParam id,
|
||||
getIntParameterRange_cb _hidl_cb) {
|
||||
auto range = mCameraInfo->controls[id];
|
||||
_hidl_cb(get<0>(range), get<1>(range), get<2>(range));
|
||||
return Void();
|
||||
}
|
||||
|
||||
|
||||
Return<void> EvsCamera::setIntParameter(CameraParam id, int32_t value,
|
||||
setIntParameter_cb _hidl_cb) {
|
||||
Return<void> EvsCamera::setParameter(CameraParam id, int32_t value,
|
||||
setParameter_cb _hidl_cb) {
|
||||
// Default implementation does not support this.
|
||||
(void)id;
|
||||
(void)value;
|
||||
|
@ -311,8 +288,7 @@ Return<void> EvsCamera::setIntParameter(CameraParam id, int32_t value,
|
|||
}
|
||||
|
||||
|
||||
Return<void> EvsCamera::getIntParameter(CameraParam id,
|
||||
getIntParameter_cb _hidl_cb) {
|
||||
Return<void> EvsCamera::getParameter(CameraParam id, getParameter_cb _hidl_cb) {
|
||||
// Default implementation does not support this.
|
||||
(void)id;
|
||||
_hidl_cb(EvsResult::INVALID_ARG, 0);
|
||||
|
@ -495,7 +471,9 @@ void EvsCamera::generateFrames() {
|
|||
fillTestFrame(newBuffer);
|
||||
|
||||
// Issue the (asynchronous) callback to the client -- can't be holding the lock
|
||||
auto result = mStream->deliverFrame_1_1(newBuffer);
|
||||
EvsEvent event;
|
||||
event.buffer(newBuffer);
|
||||
auto result = mStream->notifyEvent(event);
|
||||
if (result.isOk()) {
|
||||
ALOGD("Delivered %p as id %d",
|
||||
newBuffer.buffer.nativeHandle.getNativeHandle(), newBuffer.bufferId);
|
||||
|
@ -528,8 +506,10 @@ void EvsCamera::generateFrames() {
|
|||
|
||||
// If we've been asked to stop, send an event to signal the actual end of stream
|
||||
EvsEvent event;
|
||||
event.aType = EvsEventType::STREAM_STOPPED;
|
||||
auto result = mStream->notify(event);
|
||||
InfoEventDesc desc = {};
|
||||
desc.aType = InfoEventType::STREAM_STOPPED;
|
||||
event.info(desc);
|
||||
auto result = mStream->notifyEvent(event);
|
||||
if (!result.isOk()) {
|
||||
ALOGE("Error delivering end of stream marker");
|
||||
}
|
||||
|
@ -636,38 +616,6 @@ void EvsCamera::returnBuffer(const uint32_t bufferId, const buffer_handle_t memH
|
|||
}
|
||||
|
||||
|
||||
sp<EvsCamera> EvsCamera::Create(const char *deviceName) {
|
||||
unique_ptr<ConfigManager::CameraInfo> nullCamInfo = nullptr;
|
||||
|
||||
return Create(deviceName, nullCamInfo);
|
||||
}
|
||||
|
||||
|
||||
sp<EvsCamera> EvsCamera::Create(const char *deviceName,
|
||||
unique_ptr<ConfigManager::CameraInfo> &camInfo,
|
||||
const Stream *streamCfg) {
|
||||
sp<EvsCamera> evsCamera = new EvsCamera(deviceName, camInfo);
|
||||
if (evsCamera == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* default implementation does not use a given configuration */
|
||||
(void)streamCfg;
|
||||
|
||||
/* Use the first resolution from the list for the testing */
|
||||
auto it = camInfo->streamConfigurations.begin();
|
||||
evsCamera->mWidth = it->second[1];
|
||||
evsCamera->mHeight = it->second[2];
|
||||
evsCamera->mDescription.v1.vendorFlags = 0xFFFFFFFF; // Arbitrary test value
|
||||
|
||||
evsCamera->mFormat = HAL_PIXEL_FORMAT_RGBA_8888;
|
||||
evsCamera->mUsage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_CAMERA_WRITE |
|
||||
GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_RARELY;
|
||||
|
||||
return evsCamera;
|
||||
}
|
||||
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_0
|
||||
} // namespace evs
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
|
||||
#include <thread>
|
||||
|
||||
#include "ConfigManager.h"
|
||||
|
||||
using BufferDesc_1_0 = ::android::hardware::automotive::evs::V1_0::BufferDesc;
|
||||
using BufferDesc_1_1 = ::android::hardware::automotive::evs::V1_1::BufferDesc;
|
||||
using IEvsCameraStream_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsCameraStream;
|
||||
|
@ -61,28 +59,18 @@ public:
|
|||
Return<EvsResult> setExtendedInfo(uint32_t opaqueIdentifier, int32_t opaqueValue) override;
|
||||
|
||||
// Methods from ::android::hardware::automotive::evs::V1_1::IEvsCamera follow.
|
||||
Return<void> getCameraInfo_1_1(getCameraInfo_1_1_cb _hidl_cb) override;
|
||||
Return<EvsResult> pauseVideoStream() override;
|
||||
Return<EvsResult> resumeVideoStream() override;
|
||||
Return<EvsResult> doneWithFrame_1_1(const BufferDesc_1_1& buffer) override;
|
||||
Return<EvsResult> setMaster() override;
|
||||
Return<EvsResult> forceMaster(const sp<IEvsDisplay>& display) override;
|
||||
Return<EvsResult> unsetMaster() override;
|
||||
Return<void> getParameterList(getParameterList_cb _hidl_cb) override;
|
||||
Return<void> getIntParameterRange(CameraParam id,
|
||||
getIntParameterRange_cb _hidl_cb) override;
|
||||
Return<void> setIntParameter(CameraParam id, int32_t value,
|
||||
setIntParameter_cb _hidl_cb) override;
|
||||
Return<void> getIntParameter(CameraParam id,
|
||||
getIntParameter_cb _hidl_cb) override;
|
||||
|
||||
static sp<EvsCamera> Create(const char *deviceName);
|
||||
static sp<EvsCamera> Create(const char *deviceName,
|
||||
unique_ptr<ConfigManager::CameraInfo> &camInfo,
|
||||
const Stream *streamCfg = nullptr);
|
||||
EvsCamera(const EvsCamera&) = delete;
|
||||
EvsCamera& operator=(const EvsCamera&) = delete;
|
||||
Return<void> setParameter(CameraParam id, int32_t value,
|
||||
setParameter_cb _hidl_cb) override;
|
||||
Return<void> getParameter(CameraParam id, getParameter_cb _hidl_cb) override;
|
||||
|
||||
// Implementation details
|
||||
EvsCamera(const char *id);
|
||||
virtual ~EvsCamera() override;
|
||||
void forceShutdown(); // This gets called if another caller "steals" ownership of the camera
|
||||
|
||||
|
@ -91,10 +79,7 @@ public:
|
|||
static const char kCameraName_Backup[];
|
||||
|
||||
private:
|
||||
EvsCamera(const char *id,
|
||||
unique_ptr<ConfigManager::CameraInfo> &camInfo);
|
||||
// These three functions are expected to be called while mAccessLock is held
|
||||
//
|
||||
bool setAvailableFrames_Locked(unsigned bufferCount);
|
||||
unsigned increaseAvailableFrames_Locked(unsigned numToAdd);
|
||||
unsigned decreaseAvailableFrames_Locked(unsigned numToRemove);
|
||||
|
@ -139,9 +124,6 @@ private:
|
|||
|
||||
// Synchronization necessary to deconflict mCaptureThread from the main service thread
|
||||
std::mutex mAccessLock;
|
||||
|
||||
// Static camera module information
|
||||
unique_ptr<ConfigManager::CameraInfo> &mCameraInfo;
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
|
|
|
@ -33,7 +33,6 @@ namespace implementation {
|
|||
// constructs a new instance for each client.
|
||||
std::list<EvsEnumerator::CameraRecord> EvsEnumerator::sCameraList;
|
||||
wp<EvsDisplay> EvsEnumerator::sActiveDisplay;
|
||||
unique_ptr<ConfigManager> EvsEnumerator::sConfigManager;
|
||||
|
||||
|
||||
EvsEnumerator::EvsEnumerator() {
|
||||
|
@ -41,11 +40,9 @@ EvsEnumerator::EvsEnumerator() {
|
|||
|
||||
// Add sample camera data to our list of cameras
|
||||
// In a real driver, this would be expected to can the available hardware
|
||||
sConfigManager =
|
||||
ConfigManager::Create("/etc/automotive/evs/evs_sample_configuration.xml");
|
||||
for (auto v : sConfigManager->getCameraList()) {
|
||||
sCameraList.emplace_back(v.c_str());
|
||||
}
|
||||
sCameraList.emplace_back(EvsCamera::kCameraName_Backup);
|
||||
sCameraList.emplace_back("LaneView");
|
||||
sCameraList.emplace_back("right turn");
|
||||
}
|
||||
|
||||
|
||||
|
@ -60,7 +57,7 @@ Return<void> EvsEnumerator::getCameraList(getCameraList_cb _hidl_cb) {
|
|||
std::vector<CameraDesc_1_0> descriptions;
|
||||
descriptions.reserve(numCameras);
|
||||
for (const auto& cam : sCameraList) {
|
||||
descriptions.push_back( cam.desc.v1 );
|
||||
descriptions.push_back( cam.desc );
|
||||
}
|
||||
|
||||
// Encapsulate our camera descriptions in the HIDL vec type
|
||||
|
@ -81,7 +78,7 @@ Return<sp<IEvsCamera_1_0>> EvsEnumerator::openCamera(const hidl_string& cameraId
|
|||
// Find the named camera
|
||||
CameraRecord *pRecord = nullptr;
|
||||
for (auto &&cam : sCameraList) {
|
||||
if (cam.desc.v1.cameraId == cameraId) {
|
||||
if (cam.desc.cameraId == cameraId) {
|
||||
// Found a match!
|
||||
pRecord = &cam;
|
||||
break;
|
||||
|
@ -102,12 +99,7 @@ Return<sp<IEvsCamera_1_0>> EvsEnumerator::openCamera(const hidl_string& cameraId
|
|||
}
|
||||
|
||||
// Construct a camera instance for the caller
|
||||
if (sConfigManager == nullptr) {
|
||||
pActiveCamera = EvsCamera::Create(cameraId.c_str());
|
||||
} else {
|
||||
pActiveCamera = EvsCamera::Create(cameraId.c_str(),
|
||||
sConfigManager->getCameraInfo(cameraId));
|
||||
}
|
||||
pActiveCamera = new EvsCamera(cameraId.c_str());
|
||||
pRecord->activeInstance = pActiveCamera;
|
||||
if (pActiveCamera == nullptr) {
|
||||
ALOGE("Failed to allocate new EvsCamera object for %s\n", cameraId.c_str());
|
||||
|
@ -128,15 +120,15 @@ Return<void> EvsEnumerator::closeCamera(const ::android::sp<IEvsCamera_1_0>& pCa
|
|||
|
||||
// Get the camera id so we can find it in our list
|
||||
std::string cameraId;
|
||||
pCamera_1_1->getCameraInfo_1_1([&cameraId](CameraDesc desc) {
|
||||
cameraId = desc.v1.cameraId;
|
||||
pCamera_1_1->getCameraInfo([&cameraId](CameraDesc desc) {
|
||||
cameraId = desc.cameraId;
|
||||
}
|
||||
);
|
||||
|
||||
// Find the named camera
|
||||
CameraRecord *pRecord = nullptr;
|
||||
for (auto &&cam : sCameraList) {
|
||||
if (cam.desc.v1.cameraId == cameraId) {
|
||||
if (cam.desc.cameraId == cameraId) {
|
||||
// Found a match!
|
||||
pRecord = &cam;
|
||||
break;
|
||||
|
@ -217,89 +209,6 @@ Return<DisplayState> EvsEnumerator::getDisplayState() {
|
|||
}
|
||||
|
||||
|
||||
// Methods from ::android::hardware::automotive::evs::V1_1::IEvsEnumerator follow.
|
||||
Return<void> EvsEnumerator::getCameraList_1_1(getCameraList_1_1_cb _hidl_cb) {
|
||||
ALOGD("getCameraList");
|
||||
|
||||
const unsigned numCameras = sCameraList.size();
|
||||
|
||||
// Build up a packed array of CameraDesc for return
|
||||
// NOTE: Only has to live until the callback returns
|
||||
std::vector<CameraDesc_1_1> descriptions;
|
||||
descriptions.reserve(numCameras);
|
||||
for (const auto& cam : sCameraList) {
|
||||
descriptions.push_back( cam.desc );
|
||||
}
|
||||
|
||||
// Encapsulate our camera descriptions in the HIDL vec type
|
||||
hidl_vec<CameraDesc_1_1> hidlCameras(descriptions);
|
||||
|
||||
// Send back the results
|
||||
ALOGD("reporting %zu cameras available", hidlCameras.size());
|
||||
_hidl_cb(hidlCameras);
|
||||
|
||||
// HIDL convention says we return Void if we sent our result back via callback
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<sp<IEvsCamera_1_1>>
|
||||
EvsEnumerator::openCamera_1_1(const hidl_string& cameraId,
|
||||
const Stream& streamCfg) {
|
||||
// Find the named camera
|
||||
CameraRecord *pRecord = nullptr;
|
||||
for (auto &&cam : sCameraList) {
|
||||
if (cam.desc.v1.cameraId == cameraId) {
|
||||
// Found a match!
|
||||
pRecord = &cam;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Is this a recognized camera id?
|
||||
if (!pRecord) {
|
||||
ALOGE("Requested camera %s not found", cameraId.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Has this camera already been instantiated by another caller?
|
||||
sp<EvsCamera> pActiveCamera = pRecord->activeInstance.promote();
|
||||
if (pActiveCamera != nullptr) {
|
||||
ALOGW("Killing previous camera because of new caller");
|
||||
closeCamera(pActiveCamera);
|
||||
}
|
||||
|
||||
// Construct a camera instance for the caller
|
||||
if (sConfigManager == nullptr) {
|
||||
pActiveCamera = EvsCamera::Create(cameraId.c_str());
|
||||
} else {
|
||||
pActiveCamera = EvsCamera::Create(cameraId.c_str(),
|
||||
sConfigManager->getCameraInfo(cameraId),
|
||||
&streamCfg);
|
||||
}
|
||||
|
||||
pRecord->activeInstance = pActiveCamera;
|
||||
if (pActiveCamera == nullptr) {
|
||||
ALOGE("Failed to allocate new EvsCamera object for %s\n", cameraId.c_str());
|
||||
}
|
||||
|
||||
return pActiveCamera;
|
||||
}
|
||||
|
||||
|
||||
EvsEnumerator::CameraRecord* EvsEnumerator::findCameraById(const std::string& cameraId) {
|
||||
// Find the named camera
|
||||
CameraRecord *pRecord = nullptr;
|
||||
for (auto &&cam : sCameraList) {
|
||||
if (cam.desc.v1.cameraId == cameraId) {
|
||||
// Found a match!
|
||||
pRecord = &cam;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pRecord;
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V1_1
|
||||
} // namespace evs
|
||||
|
|
|
@ -17,20 +17,18 @@
|
|||
#ifndef ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_EVSCAMERAENUMERATOR_H
|
||||
#define ANDROID_HARDWARE_AUTOMOTIVE_EVS_V1_1_EVSCAMERAENUMERATOR_H
|
||||
|
||||
#include <android/hardware/automotive/evs/1.1/IEvsEnumerator.h>
|
||||
#include <android/hardware/automotive/evs/1.0/IEvsEnumerator.h>
|
||||
#include <android/hardware/automotive/evs/1.1/IEvsCamera.h>
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "ConfigManager.h"
|
||||
|
||||
using ::android::hardware::automotive::evs::V1_0::EvsResult;
|
||||
using ::android::hardware::automotive::evs::V1_0::IEvsDisplay;
|
||||
using ::android::hardware::automotive::evs::V1_0::DisplayState;
|
||||
using ::android::hardware::automotive::evs::V1_0::IEvsEnumerator;
|
||||
using IEvsCamera_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsCamera;
|
||||
using IEvsCamera_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsCamera;
|
||||
using CameraDesc_1_0 = ::android::hardware::automotive::evs::V1_0::CameraDesc;
|
||||
using CameraDesc_1_1 = ::android::hardware::automotive::evs::V1_1::CameraDesc;
|
||||
|
||||
|
||||
namespace android {
|
||||
|
@ -55,11 +53,6 @@ public:
|
|||
Return<void> closeDisplay(const ::android::sp<IEvsDisplay>& display) override;
|
||||
Return<DisplayState> getDisplayState() override;
|
||||
|
||||
// Methods from ::android::hardware::automotive::evs::V1_1::IEvsEnumerator follow.
|
||||
Return<void> getCameraList_1_1(getCameraList_1_1_cb _hidl_cb) override;
|
||||
Return<sp<IEvsCamera_1_1>> openCamera_1_1(const hidl_string& cameraId,
|
||||
const Stream& streamCfg) override;
|
||||
|
||||
// Implementation details
|
||||
EvsEnumerator();
|
||||
|
||||
|
@ -68,20 +61,14 @@ private:
|
|||
// That is to say, this is effectively a singleton despite the fact that HIDL
|
||||
// constructs a new instance for each client.
|
||||
struct CameraRecord {
|
||||
CameraDesc_1_1 desc;
|
||||
CameraDesc_1_0 desc;
|
||||
wp<EvsCamera> activeInstance;
|
||||
|
||||
CameraRecord(const char *cameraId) : desc() { desc.v1.cameraId = cameraId; }
|
||||
CameraRecord(const char *cameraId) : desc() { desc.cameraId = cameraId; }
|
||||
};
|
||||
static std::list<CameraRecord> sCameraList;
|
||||
|
||||
static CameraRecord* findCameraById(const std::string& cameraId);
|
||||
|
||||
static std::list<CameraRecord> sCameraList;
|
||||
|
||||
// Weak pointer. Object destructs if client dies.
|
||||
static wp<EvsDisplay> sActiveDisplay;
|
||||
|
||||
static unique_ptr<ConfigManager> sConfigManager;
|
||||
static wp<EvsDisplay> sActiveDisplay; // Weak pointer. Object destructs if client dies.
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<!-- Copyright (C) 2019 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.
|
||||
-->
|
||||
|
||||
<!-- Exterior View System Example Configuration
|
||||
|
||||
Android Automotive axes are used to define coordinates.
|
||||
See https://source.android.com/devices/sensors/sensor-types#auto_axes
|
||||
|
||||
Use evs_configuration.dtd with xmllint tool, to validate XML configuration file
|
||||
-->
|
||||
|
||||
<configuration>
|
||||
<!-- system configuration -->
|
||||
<system>
|
||||
<!-- number of cameras available to EVS -->
|
||||
<num_cameras value='1'/>
|
||||
</system>
|
||||
|
||||
<!-- camera device information -->
|
||||
<camera>
|
||||
<!-- camera device starts -->
|
||||
<device id='/dev/video1' position='rear'>
|
||||
<caps>
|
||||
<!-- list of supported controls -->
|
||||
<supported_controls>
|
||||
<control name='BRIGHTNESS' min='0' max='255'/>
|
||||
<control name='CONTRAST' min='0' max='255'/>
|
||||
</supported_controls>
|
||||
|
||||
<stream id='0' width='640' height='360' format='RGBA_8888' framerate='30'/>
|
||||
</caps>
|
||||
|
||||
<!-- list of parameters -->
|
||||
<characteristics>
|
||||
<!-- Camera intrinsic calibration matrix. See
|
||||
https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#LENS_INTRINSIC_CALIBRATION
|
||||
-->
|
||||
<parameter
|
||||
name='LENS_INTRINSIC_CALIBRATION'
|
||||
type='float'
|
||||
size='5'
|
||||
value='0.0,0.0,0.0,0.0,0.0'
|
||||
/>
|
||||
</characteristics>
|
||||
</device>
|
||||
</camera>
|
||||
<display>
|
||||
<device id='display0' position='driver'>
|
||||
<caps>
|
||||
<!-- list of supported inpu stream configurations -->
|
||||
<stream id='0' width='1280' height='720' format='RGBA_8888' framerate='30'/>
|
||||
</caps>
|
||||
</device>
|
||||
</display>
|
||||
</configuration>
|
||||
|
|
@ -33,7 +33,7 @@ using android::hardware::configureRpcThreadpool;
|
|||
using android::hardware::joinRpcThreadpool;
|
||||
|
||||
// Generated HIDL files
|
||||
using android::hardware::automotive::evs::V1_1::IEvsEnumerator;
|
||||
using android::hardware::automotive::evs::V1_0::IEvsEnumerator;
|
||||
using android::hardware::automotive::evs::V1_0::IEvsDisplay;
|
||||
|
||||
// The namespace in which all our implementation code lives
|
||||
|
|
|
@ -21,22 +21,6 @@ import @1.0::DisplayDesc;
|
|||
import @1.0::DisplayState;
|
||||
import @1.0::EvsResult;
|
||||
import android.hardware.graphics.common@1.2::HardwareBuffer;
|
||||
import android.hardware.camera.device@3.2::CameraMetadata;
|
||||
|
||||
/**
|
||||
* Structure describing the basic properties of an EVS camera, extended from its
|
||||
* v1.0 declaration.
|
||||
*
|
||||
* The HAL is responsible for filling out this structure for each
|
||||
* EVS camera in the system.
|
||||
*/
|
||||
struct CameraDesc {
|
||||
@1.0::CameraDesc v1;
|
||||
/**
|
||||
* Store camera metadata such as lens characteristics.
|
||||
*/
|
||||
CameraMetadata metadata;
|
||||
};
|
||||
|
||||
/**
|
||||
* Structure representing an image buffer through our APIs
|
||||
|
@ -66,7 +50,7 @@ struct BufferDesc {
|
|||
/**
|
||||
* Types of informative streaming events
|
||||
*/
|
||||
enum EvsEventType : uint32_t {
|
||||
enum InfoEventType : uint32_t {
|
||||
/**
|
||||
* Video stream is started
|
||||
*/
|
||||
|
@ -97,17 +81,31 @@ enum EvsEventType : uint32_t {
|
|||
/**
|
||||
* Structure that describes informative events occurred during EVS is streaming
|
||||
*/
|
||||
struct EvsEvent {
|
||||
struct InfoEventDesc {
|
||||
/**
|
||||
* Type of an informative event
|
||||
*/
|
||||
EvsEventType aType;
|
||||
InfoEventType aType;
|
||||
/**
|
||||
* Possible additional information
|
||||
*/
|
||||
uint32_t[4] payload;
|
||||
};
|
||||
|
||||
/**
|
||||
* EVS event definition
|
||||
*/
|
||||
safe_union EvsEvent {
|
||||
/**
|
||||
* A buffer descriptor of an image frame
|
||||
*/
|
||||
BufferDesc buffer;
|
||||
/**
|
||||
* General streaming events
|
||||
*/
|
||||
InfoEventDesc info;
|
||||
};
|
||||
|
||||
/**
|
||||
* EVS Camera Parameter
|
||||
*/
|
||||
|
@ -128,6 +126,14 @@ enum CameraParam : uint32_t {
|
|||
* Gain control
|
||||
*/
|
||||
GAIN,
|
||||
/**
|
||||
* Mirror the image horizontally
|
||||
*/
|
||||
HFLIP,
|
||||
/**
|
||||
* Mirror the image vertically
|
||||
*/
|
||||
VFLIP,
|
||||
/**
|
||||
* Automatic Whitebalance
|
||||
*/
|
||||
|
@ -149,6 +155,11 @@ enum CameraParam : uint32_t {
|
|||
* Manual exposure time of the camera
|
||||
*/
|
||||
ABSOLUTE_EXPOSURE,
|
||||
/**
|
||||
* When AEC is running in either auto or aperture priority, this parameter
|
||||
* sets whether a frame rate varies.
|
||||
*/
|
||||
AUTO_EXPOSURE_PRIORITY,
|
||||
/**
|
||||
* Set the focal point of the camera to the specified position. This
|
||||
* parameter may not be effective when auto focus is enabled.
|
||||
|
|
|
@ -23,7 +23,6 @@ cc_test {
|
|||
defaults: ["VtsHalTargetTestDefaults"],
|
||||
shared_libs: [
|
||||
"libui",
|
||||
"libcamera_metadata",
|
||||
],
|
||||
static_libs: [
|
||||
"android.hardware.automotive.evs@1.0",
|
||||
|
@ -32,7 +31,6 @@ cc_test {
|
|||
"android.hardware.graphics.common@1.0",
|
||||
"android.hardware.graphics.common@1.1",
|
||||
"android.hardware.graphics.common@1.2",
|
||||
"android.hardware.camera.device@3.2",
|
||||
],
|
||||
test_suites: ["general-tests"],
|
||||
cflags: [
|
||||
|
|
|
@ -138,93 +138,93 @@ Return<void> FrameHandler::deliverFrame(const BufferDesc_1_0& bufferArg) {
|
|||
}
|
||||
|
||||
|
||||
Return<void> FrameHandler::deliverFrame_1_1(const BufferDesc_1_1& bufDesc) {
|
||||
const AHardwareBuffer_Desc* pDesc =
|
||||
reinterpret_cast<const AHardwareBuffer_Desc *>(&bufDesc.buffer.description);
|
||||
ALOGD("Received a frame from the camera (%p)",
|
||||
bufDesc.buffer.nativeHandle.getNativeHandle());
|
||||
|
||||
// Store a dimension of a received frame.
|
||||
mFrameWidth = pDesc->width;
|
||||
mFrameHeight = pDesc->height;
|
||||
|
||||
// If we were given an opened display at construction time, then send the received
|
||||
// image back down the camera.
|
||||
if (mDisplay.get()) {
|
||||
// Get the output buffer we'll use to display the imagery
|
||||
BufferDesc_1_0 tgtBuffer = {};
|
||||
mDisplay->getTargetBuffer([&tgtBuffer](const BufferDesc_1_0& buff) {
|
||||
tgtBuffer = buff;
|
||||
}
|
||||
);
|
||||
|
||||
if (tgtBuffer.memHandle == nullptr) {
|
||||
printf("Didn't get target buffer - frame lost\n");
|
||||
ALOGE("Didn't get requested output buffer -- skipping this frame.");
|
||||
Return<void> FrameHandler::notifyEvent(const EvsEvent& event) {
|
||||
// Local flag we use to keep track of when the stream is stopping
|
||||
auto type = event.getDiscriminator();
|
||||
if (type == EvsEvent::hidl_discriminator::info) {
|
||||
mLock.lock();
|
||||
mLatestEventDesc = event.info();
|
||||
if (mLatestEventDesc.aType == InfoEventType::STREAM_STOPPED) {
|
||||
// Signal that the last frame has been received and the stream is stopped
|
||||
mRunning = false;
|
||||
} else if (mLatestEventDesc.aType == InfoEventType::PARAMETER_CHANGED) {
|
||||
ALOGD("Camera parameter 0x%X is changed to 0x%X",
|
||||
mLatestEventDesc.payload[0], mLatestEventDesc.payload[1]);
|
||||
} else {
|
||||
// Copy the contents of the of buffer.memHandle into tgtBuffer
|
||||
copyBufferContents(tgtBuffer, bufDesc);
|
||||
ALOGD("Received an event %s", eventToString(mLatestEventDesc.aType));
|
||||
}
|
||||
mLock.unlock();
|
||||
mEventSignal.notify_all();
|
||||
} else {
|
||||
auto bufDesc = event.buffer();
|
||||
const AHardwareBuffer_Desc* pDesc =
|
||||
reinterpret_cast<const AHardwareBuffer_Desc *>(&bufDesc.buffer.description);
|
||||
ALOGD("Received a frame from the camera (%p)",
|
||||
bufDesc.buffer.nativeHandle.getNativeHandle());
|
||||
|
||||
// Send the target buffer back for display
|
||||
Return<EvsResult> result = mDisplay->returnTargetBufferForDisplay(tgtBuffer);
|
||||
if (!result.isOk()) {
|
||||
printf("HIDL error on display buffer (%s)- frame lost\n",
|
||||
result.description().c_str());
|
||||
ALOGE("Error making the remote function call. HIDL said %s",
|
||||
result.description().c_str());
|
||||
} else if (result != EvsResult::OK) {
|
||||
printf("Display reported error - frame lost\n");
|
||||
ALOGE("We encountered error %d when returning a buffer to the display!",
|
||||
(EvsResult) result);
|
||||
// Store a dimension of a received frame.
|
||||
mFrameWidth = pDesc->width;
|
||||
mFrameHeight = pDesc->height;
|
||||
|
||||
// If we were given an opened display at construction time, then send the received
|
||||
// image back down the camera.
|
||||
if (mDisplay.get()) {
|
||||
// Get the output buffer we'll use to display the imagery
|
||||
BufferDesc_1_0 tgtBuffer = {};
|
||||
mDisplay->getTargetBuffer([&tgtBuffer](const BufferDesc_1_0& buff) {
|
||||
tgtBuffer = buff;
|
||||
}
|
||||
);
|
||||
|
||||
if (tgtBuffer.memHandle == nullptr) {
|
||||
printf("Didn't get target buffer - frame lost\n");
|
||||
ALOGE("Didn't get requested output buffer -- skipping this frame.");
|
||||
} else {
|
||||
// Everything looks good!
|
||||
// Keep track so tests or watch dogs can monitor progress
|
||||
mLock.lock();
|
||||
mFramesDisplayed++;
|
||||
mLock.unlock();
|
||||
// Copy the contents of the of buffer.memHandle into tgtBuffer
|
||||
copyBufferContents(tgtBuffer, bufDesc);
|
||||
|
||||
// Send the target buffer back for display
|
||||
Return<EvsResult> result = mDisplay->returnTargetBufferForDisplay(tgtBuffer);
|
||||
if (!result.isOk()) {
|
||||
printf("HIDL error on display buffer (%s)- frame lost\n",
|
||||
result.description().c_str());
|
||||
ALOGE("Error making the remote function call. HIDL said %s",
|
||||
result.description().c_str());
|
||||
} else if (result != EvsResult::OK) {
|
||||
printf("Display reported error - frame lost\n");
|
||||
ALOGE("We encountered error %d when returning a buffer to the display!",
|
||||
(EvsResult) result);
|
||||
} else {
|
||||
// Everything looks good!
|
||||
// Keep track so tests or watch dogs can monitor progress
|
||||
mLock.lock();
|
||||
mFramesDisplayed++;
|
||||
mLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
switch (mReturnMode) {
|
||||
case eAutoReturn:
|
||||
// Send the camera buffer back now that the client has seen it
|
||||
ALOGD("Calling doneWithFrame");
|
||||
// TODO: Why is it that we get a HIDL crash if we pass back the cloned buffer?
|
||||
mCamera->doneWithFrame_1_1(bufDesc);
|
||||
break;
|
||||
case eNoAutoReturn:
|
||||
// Hang onto the buffer handle for now -- the client will return it explicitly later
|
||||
mHeldBuffers.push(bufDesc);
|
||||
}
|
||||
|
||||
mLock.lock();
|
||||
++mFramesReceived;
|
||||
mLock.unlock();
|
||||
mFrameSignal.notify_all();
|
||||
|
||||
ALOGD("Frame handling complete");
|
||||
}
|
||||
|
||||
|
||||
switch (mReturnMode) {
|
||||
case eAutoReturn:
|
||||
// Send the camera buffer back now that the client has seen it
|
||||
ALOGD("Calling doneWithFrame");
|
||||
mCamera->doneWithFrame_1_1(bufDesc);
|
||||
break;
|
||||
case eNoAutoReturn:
|
||||
// Hang onto the buffer handle for now -- the client will return it explicitly later
|
||||
mHeldBuffers.push(bufDesc);
|
||||
}
|
||||
|
||||
mLock.lock();
|
||||
++mFramesReceived;
|
||||
mLock.unlock();
|
||||
mFrameSignal.notify_all();
|
||||
|
||||
ALOGD("Frame handling complete");
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
|
||||
Return<void> FrameHandler::notify(const EvsEvent& event) {
|
||||
// Local flag we use to keep track of when the stream is stopping
|
||||
mLock.lock();
|
||||
mLatestEventDesc = event;
|
||||
if (mLatestEventDesc.aType == EvsEventType::STREAM_STOPPED) {
|
||||
// Signal that the last frame has been received and the stream is stopped
|
||||
mRunning = false;
|
||||
} else if (mLatestEventDesc.aType == EvsEventType::PARAMETER_CHANGED) {
|
||||
ALOGD("Camera parameter 0x%X is changed to 0x%X",
|
||||
mLatestEventDesc.payload[0], mLatestEventDesc.payload[1]);
|
||||
} else {
|
||||
ALOGD("Received an event %s", eventToString(mLatestEventDesc.aType));
|
||||
}
|
||||
mLock.unlock();
|
||||
mEventSignal.notify_all();
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
|
@ -342,18 +342,18 @@ void FrameHandler::getFrameDimension(unsigned* width, unsigned* height) {
|
|||
}
|
||||
}
|
||||
|
||||
bool FrameHandler::waitForEvent(const EvsEventType aTargetEvent,
|
||||
EvsEvent &event) {
|
||||
bool FrameHandler::waitForEvent(const InfoEventType aTargetEvent,
|
||||
InfoEventDesc &eventDesc) {
|
||||
// Wait until we get an expected parameter change event.
|
||||
std::unique_lock<std::mutex> lock(mLock);
|
||||
auto now = std::chrono::system_clock::now();
|
||||
bool result = mEventSignal.wait_until(lock, now + 5s,
|
||||
[this, aTargetEvent, &event](){
|
||||
[this, aTargetEvent, &eventDesc](){
|
||||
bool flag = mLatestEventDesc.aType == aTargetEvent;
|
||||
if (flag) {
|
||||
event.aType = mLatestEventDesc.aType;
|
||||
event.payload[0] = mLatestEventDesc.payload[0];
|
||||
event.payload[1] = mLatestEventDesc.payload[1];
|
||||
eventDesc.aType = mLatestEventDesc.aType;
|
||||
eventDesc.payload[0] = mLatestEventDesc.payload[0];
|
||||
eventDesc.payload[1] = mLatestEventDesc.payload[1];
|
||||
}
|
||||
|
||||
return flag;
|
||||
|
@ -363,22 +363,21 @@ bool FrameHandler::waitForEvent(const EvsEventType aTargetEvent,
|
|||
return !result;
|
||||
}
|
||||
|
||||
const char *FrameHandler::eventToString(const EvsEventType aType) {
|
||||
const char *FrameHandler::eventToString(const InfoEventType aType) {
|
||||
switch (aType) {
|
||||
case EvsEventType::STREAM_STARTED:
|
||||
case InfoEventType::STREAM_STARTED:
|
||||
return "STREAM_STARTED";
|
||||
case EvsEventType::STREAM_STOPPED:
|
||||
case InfoEventType::STREAM_STOPPED:
|
||||
return "STREAM_STOPPED";
|
||||
case EvsEventType::FRAME_DROPPED:
|
||||
case InfoEventType::FRAME_DROPPED:
|
||||
return "FRAME_DROPPED";
|
||||
case EvsEventType::TIMEOUT:
|
||||
case InfoEventType::TIMEOUT:
|
||||
return "TIMEOUT";
|
||||
case EvsEventType::PARAMETER_CHANGED:
|
||||
case InfoEventType::PARAMETER_CHANGED:
|
||||
return "PARAMETER_CHANGED";
|
||||
case EvsEventType::MASTER_RELEASED:
|
||||
case InfoEventType::MASTER_RELEASED:
|
||||
return "MASTER_RELEASED";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ using ::android::hardware::hidl_handle;
|
|||
using ::android::sp;
|
||||
using ::android::hardware::automotive::evs::V1_0::IEvsDisplay;
|
||||
using ::android::hardware::automotive::evs::V1_0::EvsResult;
|
||||
using ::android::hardware::automotive::evs::V1_0::CameraDesc;
|
||||
using BufferDesc_1_0 = ::android::hardware::automotive::evs::V1_0::BufferDesc;
|
||||
using BufferDesc_1_1 = ::android::hardware::automotive::evs::V1_1::BufferDesc;
|
||||
|
||||
|
@ -55,13 +56,6 @@ public:
|
|||
FrameHandler(android::sp <IEvsCamera> pCamera, CameraDesc cameraInfo,
|
||||
android::sp <IEvsDisplay> pDisplay = nullptr,
|
||||
BufferControlFlag mode = eAutoReturn);
|
||||
virtual ~FrameHandler() {
|
||||
if (mCamera != nullptr) {
|
||||
/* shutdown a camera explicitly */
|
||||
shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
void shutdown();
|
||||
|
||||
bool startStream();
|
||||
|
@ -73,22 +67,19 @@ public:
|
|||
bool isRunning();
|
||||
|
||||
void waitForFrameCount(unsigned frameCount);
|
||||
bool waitForEvent(const EvsEventType aTargetEvent,
|
||||
EvsEvent &eventDesc);
|
||||
bool waitForEvent(const InfoEventType aTargetEvent,
|
||||
InfoEventDesc &eventDesc);
|
||||
void getFramesCounters(unsigned* received, unsigned* displayed);
|
||||
void getFrameDimension(unsigned* width, unsigned* height);
|
||||
|
||||
private:
|
||||
// Implementation for ::android::hardware::automotive::evs::V1_0::IEvsCameraStream
|
||||
Return<void> deliverFrame(const BufferDesc_1_0& buffer) override;
|
||||
|
||||
// Implementation for ::android::hardware::automotive::evs::V1_1::IEvsCameraStream
|
||||
Return<void> deliverFrame_1_1(const BufferDesc_1_1& buffer) override;
|
||||
Return<void> notify(const EvsEvent& event) override;
|
||||
Return<void> deliverFrame(const BufferDesc_1_0& buffer) override;
|
||||
Return<void> notifyEvent(const EvsEvent& event) override;
|
||||
|
||||
// Local implementation details
|
||||
bool copyBufferContents(const BufferDesc_1_0& tgtBuffer, const BufferDesc_1_1& srcBuffer);
|
||||
const char *eventToString(const EvsEventType aType);
|
||||
const char *eventToString(const InfoEventType aType);
|
||||
|
||||
// Values initialized as startup
|
||||
android::sp <IEvsCamera> mCamera;
|
||||
|
@ -109,7 +100,7 @@ private:
|
|||
unsigned mFramesDisplayed = 0; // Simple counter -- rolls over eventually!
|
||||
unsigned mFrameWidth = 0;
|
||||
unsigned mFrameHeight = 0;
|
||||
EvsEvent mLatestEventDesc;
|
||||
InfoEventDesc mLatestEventDesc;
|
||||
};
|
||||
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue