blob: 14be8902d67164dce804b3e2c97489b773de9214 [file] [log] [blame]
/*
* Copyright 2020 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 "MockEvsCamera.h"
#include <stdlib.h>
namespace android {
namespace hardware {
namespace automotive {
namespace sv {
namespace V1_0 {
namespace implementation {
// TODO(b/159733690): the number should come from xml
const int kFramesCount = 4;
const int kFrameGenerationDelayMillis = 30;
const char kConfigFilePath[] =
"/vendor/etc/automotive/evs/evs_sample_configuration.xml";
// Evs Camera Id names defined in sv_sample_config.xml.
const char kEvsCameraDeviceIdNames[4][20] = {
"/dev/video60", "/dev/video61", "/dev/video62", "/dev/video63"
};
MockEvsCamera::MockEvsCamera(const string& cameraId, const Stream& streamCfg) {
mConfigManager = ConfigManager::Create(kConfigFilePath);
mStreamCfg.height = streamCfg.height;
mStreamCfg.width = streamCfg.width;
mCameraDesc.v1.cameraId = cameraId;
unique_ptr<ConfigManager::CameraGroupInfo>& cameraGroupInfo =
mConfigManager->getCameraGroupInfo(mCameraDesc.v1.cameraId);
if (cameraGroupInfo != nullptr) {
mCameraDesc.metadata.setToExternal(
(uint8_t*)cameraGroupInfo->characteristics,
get_camera_metadata_size(cameraGroupInfo->characteristics));
}
}
Return<void> MockEvsCamera::getCameraInfo(getCameraInfo_cb _hidl_cb) {
// Not implemented.
(void)_hidl_cb;
return {};
}
Return<EvsResult> MockEvsCamera::setMaxFramesInFlight(uint32_t bufferCount) {
// Not implemented.
(void)bufferCount;
return EvsResult::OK;
}
Return<EvsResult> MockEvsCamera::startVideoStream(
const ::android::sp<IEvsCameraStream_1_0>& stream) {
LOG(INFO) << __FUNCTION__;
scoped_lock<mutex> lock(mAccessLock);
mStream = IEvsCameraStream_1_1::castFrom(stream).withDefault(nullptr);
if (mStreamState != STOPPED) {
LOG(ERROR) << "Ignoring startVideoStream call when a stream is "
<< "already running.";
return EvsResult::STREAM_ALREADY_RUNNING;
}
// Start the frame generation thread
mStreamState = RUNNING;
mCaptureThread = thread([this]() { generateFrames(); });
return EvsResult::OK;
}
Return<void> MockEvsCamera::doneWithFrame(const BufferDesc_1_0& buffer) {
// Not implemented.
(void)buffer;
return {};
}
Return<void> MockEvsCamera::stopVideoStream() {
LOG(INFO) << __FUNCTION__;
unique_lock<mutex> lock(mAccessLock);
if (mStreamState == RUNNING) {
// Tell the GenerateFrames loop we want it to stop
mStreamState = STOPPING;
// 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
LOG(DEBUG) << __FUNCTION__ << ": Waiting for stream thread to end...";
lock.unlock();
mCaptureThread.join();
lock.lock();
mStreamState = STOPPED;
mStream = nullptr;
LOG(DEBUG) << "Stream marked STOPPED.";
}
return {};
}
Return<int32_t> MockEvsCamera::getExtendedInfo(uint32_t opaqueIdentifier) {
// Not implemented.
(void)opaqueIdentifier;
return 0;
}
Return<EvsResult> MockEvsCamera::setExtendedInfo(uint32_t opaqueIdentifier,
int32_t opaqueValue) {
// Not implemented.
(void)opaqueIdentifier;
(void)opaqueValue;
return EvsResult::OK;
}
Return<void> MockEvsCamera::getCameraInfo_1_1(getCameraInfo_1_1_cb _hidl_cb) {
_hidl_cb(mCameraDesc);
return {};
}
Return<void> MockEvsCamera::getPhysicalCameraInfo(
const hidl_string& deviceId, getPhysicalCameraInfo_cb _hidl_cb) {
CameraDesc_1_1 desc = {};
desc.v1.cameraId = deviceId;
unique_ptr<ConfigManager::CameraInfo>& cameraInfo =
mConfigManager->getCameraInfo(deviceId);
if (cameraInfo != nullptr) {
desc.metadata.setToExternal(
(uint8_t*)cameraInfo->characteristics,
get_camera_metadata_size(cameraInfo->characteristics));
}
_hidl_cb(desc);
return {};
}
Return<EvsResult> MockEvsCamera::doneWithFrame_1_1(
const hardware::hidl_vec<BufferDesc_1_1>& buffer) {
// Not implemented.
(void)buffer;
return EvsResult::OK;
}
Return<EvsResult> MockEvsCamera::setMaster() {
// Not implemented.
return EvsResult::OK;
}
Return<EvsResult> MockEvsCamera::forceMaster(
const sp<IEvsDisplay_1_0>& display) {
// Not implemented.
(void)display;
return EvsResult::OK;
}
Return<EvsResult> MockEvsCamera::unsetMaster() {
// Not implemented.
return EvsResult::OK;
}
Return<void> MockEvsCamera::getParameterList(getParameterList_cb _hidl_cb) {
// Not implemented.
(void)_hidl_cb;
return {};
}
Return<void> MockEvsCamera::getIntParameterRange(
CameraParam id, getIntParameterRange_cb _hidl_cb) {
// Not implemented.
(void)id;
(void)_hidl_cb;
return {};
}
Return<void> MockEvsCamera::setIntParameter(CameraParam id, int32_t value,
setIntParameter_cb _hidl_cb) {
// Not implemented.
(void)id;
(void)value;
(void)_hidl_cb;
return {};
}
Return<void> MockEvsCamera::getIntParameter(
CameraParam id, getIntParameter_cb _hidl_cb) {
// Not implemented.
(void)id;
(void)_hidl_cb;
return {};
}
Return<EvsResult> MockEvsCamera::setExtendedInfo_1_1(
uint32_t opaqueIdentifier, const hidl_vec<uint8_t>& opaqueValue) {
// Not implemented.
(void)opaqueIdentifier;
(void)opaqueValue;
return EvsResult::OK;
}
Return<void> MockEvsCamera::getExtendedInfo_1_1(
uint32_t opaqueIdentifier, getExtendedInfo_1_1_cb _hidl_cb) {
// Not implemented.
(void)opaqueIdentifier;
(void)_hidl_cb;
return {};
}
Return<void> MockEvsCamera::importExternalBuffers(
const hidl_vec<BufferDesc_1_1>& buffers,
importExternalBuffers_cb _hidl_cb) {
// Not implemented.
(void)buffers;
(void)_hidl_cb;
return {};
}
void MockEvsCamera::initializeFrames(int framesCount) {
LOG(INFO) << "StreamCfg width: " << mStreamCfg.width
<< " height: " << mStreamCfg.height;
string label = "EmptyBuffer_";
mGraphicBuffers.resize(framesCount);
mBufferDescs.resize(framesCount);
for (int i = 0; i < framesCount; i++) {
mGraphicBuffers[i] = new GraphicBuffer(mStreamCfg.width,
mStreamCfg.height,
HAL_PIXEL_FORMAT_RGBA_8888,
1,
GRALLOC_USAGE_HW_TEXTURE,
label + (char)(i + 48));
mBufferDescs[i].buffer.nativeHandle =
mGraphicBuffers[i]->getNativeBuffer()->handle;
mBufferDescs[i].deviceId = kEvsCameraDeviceIdNames[i];
AHardwareBuffer_Desc* pDesc =
reinterpret_cast<AHardwareBuffer_Desc*>(
&mBufferDescs[i].buffer.description);
pDesc->width = mStreamCfg.width;
pDesc->height = mStreamCfg.height;
pDesc->layers = 1;
pDesc->usage = GRALLOC_USAGE_HW_TEXTURE;
pDesc->stride = mGraphicBuffers[i]->getStride();
pDesc->format = HAL_PIXEL_FORMAT_RGBA_8888;
}
}
void MockEvsCamera::generateFrames() {
initializeFrames(kFramesCount);
while (true) {
{
scoped_lock<mutex> lock(mAccessLock);
if (mStreamState != RUNNING) {
// Break out of our main thread loop
LOG(INFO) << "StreamState does not equal to RUNNING. "
<< "Exiting the loop";
break;
}
}
mStream->deliverFrame_1_1(mBufferDescs);
std::this_thread::sleep_for(
std::chrono::milliseconds(kFrameGenerationDelayMillis));
}
{
scoped_lock<mutex> lock(mAccessLock);
if (mStream != nullptr) {
LOG(DEBUG) << "Notify EvsEventType::STREAM_STOPPED";
EvsEventDesc evsEventDesc;
evsEventDesc.aType = EvsEventType::STREAM_STOPPED;
mStream->notify(evsEventDesc);
} else {
LOG(WARNING) << "EVS stream is not valid any more. "
<< "The notify call is ignored.";
}
}
}
} // namespace implementation
} // namespace V1_0
} // namespace sv
} // namespace automotive
} // namespace hardware
} // namespace android