blob: 8799bd26dec8f3d2335720202efe44d949d0ebf0 [file] [log] [blame]
/*
* 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 <stdio.h>
#include <utils/SystemClock.h>
#include <string>
#include <log/log.h>
#include <DisplayUseCase.h>
#include <AnalyzeUseCase.h>
#include <Utils.h>
using namespace ::android::automotive::evs::support;
class SimpleRenderCallback : public BaseRenderCallback {
void render(const Frame& inputFrame, const Frame& outputFrame) {
ALOGI("SimpleRenderCallback::render");
if (inputFrame.data == nullptr || outputFrame.data == nullptr) {
ALOGE("Invalid frame data was passed to render callback");
return;
}
// TODO(b/130246434): Use OpenCV to implement a more meaningful
// callback.
// Swap the RGB channels.
int stride = inputFrame.stride;
uint8_t* inDataPtr = inputFrame.data;
uint8_t* outDataPtr = outputFrame.data;
for (int i = 0; i < inputFrame.width; i++)
for (int j = 0; j < inputFrame.height; j++) {
outDataPtr[(i + j * stride) * 4 + 0] =
inDataPtr[(i + j * stride) * 4 + 1];
outDataPtr[(i + j * stride) * 4 + 1] =
inDataPtr[(i + j * stride) * 4 + 2];
outDataPtr[(i + j * stride) * 4 + 2] =
inDataPtr[(i + j * stride) * 4 + 0];
outDataPtr[(i + j * stride) * 4 + 3] =
inDataPtr[(i + j * stride) * 4 + 3];
}
}
};
class SimpleAnalyzeCallback : public BaseAnalyzeCallback {
void analyze(const Frame &frame) {
ALOGD("SimpleAnalyzeCallback::analyze");
if (frame.data == nullptr) {
ALOGE("Invalid frame data was passed to analyze callback");
return;
}
// TODO(b/130246434): Now we just put a one second delay as a place
// holder. Replace it with an actual complicated enough algorithm.
ALOGD("SimpleAnalyzerCallback: sleep for one second");
std::this_thread::sleep_for(std::chrono::seconds(1));
};
};
// Main entry point
int main() {
ALOGI("EVS app starting\n");
// Get the default rear view camera from evs support lib
std::string cameraId = Utils::getDefaultRearViewCameraId();
if (cameraId.empty()) {
ALOGE("Cannot find a valid camera");
return EXIT_FAILURE;
}
DisplayUseCase displayUseCase =
DisplayUseCase::createDefaultUseCase(cameraId, new SimpleRenderCallback());
AnalyzeUseCase analyzeUseCase =
AnalyzeUseCase::createDefaultUseCase(cameraId, new SimpleAnalyzeCallback());
// Run both DisplayUseCase and AnalyzeUseCase together for 10 seconds.
if (displayUseCase.startVideoStream()
&& analyzeUseCase.startVideoStream()) {
std::this_thread::sleep_for(std::chrono::seconds(10));
displayUseCase.stopVideoStream();
analyzeUseCase.stopVideoStream();
}
// Run only AnalyzeUseCase for 10 seconds. The display control is back to
// Android framework but the camera is still occupied by AnalyzeUseCase in
// the background.
if (analyzeUseCase.startVideoStream()) {
std::this_thread::sleep_for(std::chrono::seconds(10));
analyzeUseCase.stopVideoStream();
}
return 0;
}