blob: 2fe0c86ce639c26f13e09d6b1cfaa254a5c28ec3 [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 <android-base/logging.h>
#include <android/hardware/automotive/evs/1.1/IEvsEnumerator.h>
#include <android/hardware/automotive/sv/1.0/ISurroundViewService.h>
#include <android/hardware/automotive/sv/1.0/ISurroundView2dSession.h>
#include <android/hardware/automotive/sv/1.0/ISurroundView3dSession.h>
#include <hidl/HidlTransportSupport.h>
#include <stdio.h>
#include <utils/StrongPointer.h>
#include <utils/Log.h>
#include <thread>
#include "SurroundViewServiceCallback.h"
// libhidl:
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::sp;
using android::hardware::Return;
using android::hardware::automotive::evs::V1_0::EvsResult;
using BufferDesc_1_0 = android::hardware::automotive::evs::V1_0::BufferDesc;
using DisplayState = android::hardware::automotive::evs::V1_0::DisplayState;
using namespace android::hardware::automotive::sv::V1_0;
using namespace android::hardware::automotive::evs::V1_1;
const int kLowResolutionWidth = 120;
const int kLowResolutionHeight = 90;
enum DemoMode {
UNKNOWN,
DEMO_2D,
DEMO_3D,
};
bool run2dSurroundView(sp<ISurroundViewService> pSurroundViewService,
sp<IEvsDisplay> pDisplay) {
LOG(INFO) << "Run 2d Surround View demo";
// Call HIDL API "start2dSession"
sp<ISurroundView2dSession> surroundView2dSession;
SvResult svResult;
pSurroundViewService->start2dSession(
[&surroundView2dSession, &svResult](
const sp<ISurroundView2dSession>& session, SvResult result) {
surroundView2dSession = session;
svResult = result;
});
if (surroundView2dSession == nullptr || svResult != SvResult::OK) {
LOG(ERROR) << "Failed to start2dSession";
return false;
} else {
LOG(INFO) << "start2dSession succeeded";
}
sp<SurroundViewServiceCallback> sv2dCallback
= new SurroundViewServiceCallback(pDisplay, surroundView2dSession);
// Start 2d stream with callback
if (surroundView2dSession->startStream(sv2dCallback) != SvResult::OK) {
LOG(ERROR) << "Failed to start 2d stream";
return false;
}
// Let the SV algorithm run for 10 seconds for HIGH_QUALITY
std::this_thread::sleep_for(std::chrono::seconds(10));
// Switch to low quality and lower resolution
Sv2dConfig config;
config.width = kLowResolutionWidth;
config.blending = SvQuality::LOW;
if (surroundView2dSession->set2dConfig(config) != SvResult::OK) {
LOG(ERROR) << "Failed to set2dConfig";
return false;
}
// Let the SV algorithm run for 10 seconds for LOW_QUALITY
std::this_thread::sleep_for(std::chrono::seconds(10));
// TODO(b/150412555): wait for the last frame
// Stop the 2d stream and session
surroundView2dSession->stopStream();
pSurroundViewService->stop2dSession(surroundView2dSession);
surroundView2dSession = nullptr;
LOG(INFO) << "SV 2D session finished.";
return true;
};
bool run3dSurroundView(sp<ISurroundViewService> pSurroundViewService,
sp<IEvsDisplay> pDisplay) {
LOG(INFO) << "Run 3d Surround View demo";
// Call HIDL API "start3dSession"
sp<ISurroundView3dSession> surroundView3dSession;
SvResult svResult;
pSurroundViewService->start3dSession(
[&surroundView3dSession, &svResult](
const sp<ISurroundView3dSession>& session, SvResult result) {
surroundView3dSession = session;
svResult = result;
});
if (surroundView3dSession == nullptr || svResult != SvResult::OK) {
LOG(ERROR) << "Failed to start3dSession";
return false;
} else {
LOG(INFO) << "start3dSession succeeded";
}
// TODO(b/150412555): now we have the dummy view here since the views are
// set in service. This should be fixed.
std::vector<View3d> singleView(1);
surroundView3dSession->setViews(singleView);
if (surroundView3dSession->setViews(singleView) != SvResult::OK) {
LOG(ERROR) << "Failed to setViews";
return false;
}
sp<SurroundViewServiceCallback> sv3dCallback
= new SurroundViewServiceCallback(pDisplay, surroundView3dSession);
// Start 3d stream with callback
if (surroundView3dSession->startStream(sv3dCallback) != SvResult::OK) {
LOG(ERROR) << "Failed to start 3d stream";
return false;
}
// Let the SV algorithm run for 10 seconds for HIGH_QUALITY
std::this_thread::sleep_for(std::chrono::seconds(10));
// Switch to low quality and lower resolution
Sv3dConfig config;
config.width = kLowResolutionWidth;
config.height = kLowResolutionHeight;
config.carDetails = SvQuality::LOW;
if (surroundView3dSession->set3dConfig(config) != SvResult::OK) {
LOG(ERROR) << "Failed to set3dConfig";
return false;
}
// Let the SV algorithm run for 10 seconds for LOW_QUALITY
std::this_thread::sleep_for(std::chrono::seconds(10));
// TODO(b/150412555): wait for the last frame
// Stop the 3d stream and session
surroundView3dSession->stopStream();
pSurroundViewService->stop3dSession(surroundView3dSession);
surroundView3dSession = nullptr;
LOG(DEBUG) << "SV 3D session finished.";
return true;
};
// Main entry point
int main(int argc, char** argv) {
// Start up
LOG(INFO) << "SV app starting";
DemoMode mode = UNKNOWN;
for (int i=1; i< argc; i++) {
if (strcmp(argv[i], "--use2d") == 0) {
mode = DEMO_2D;
} else if (strcmp(argv[i], "--use3d") == 0) {
mode = DEMO_3D;
} else {
LOG(WARNING) << "Ignoring unrecognized command line arg: "
<< argv[i];
}
}
if (mode == UNKNOWN) {
LOG(ERROR) << "No demo mode is specified. Exiting";
return EXIT_FAILURE;
}
// Set thread pool size to one to avoid concurrent events from the HAL.
// This pool will handle the SurroundViewStream callbacks.
configureRpcThreadpool(1, false /* callerWillJoin */);
// Try to connect to EVS service
LOG(INFO) << "Acquiring EVS Enumerator";
sp<IEvsEnumerator> evs = IEvsEnumerator::getService();
if (evs == nullptr) {
LOG(ERROR) << "getService(default) returned NULL. Exiting.";
return EXIT_FAILURE;
}
// Try to connect to SV service
LOG(INFO) << "Acquiring SV Service";
android::sp<ISurroundViewService> surroundViewService
= ISurroundViewService::getService("default");
if (surroundViewService == nullptr) {
LOG(ERROR) << "getService(default) returned NULL.";
return EXIT_FAILURE;
} else {
LOG(INFO) << "Get ISurroundViewService default";
}
// Connect to evs display
int displayId;
evs->getDisplayIdList([&displayId](auto idList) {
displayId = idList[0];
});
LOG(INFO) << "Acquiring EVS Display with ID: "
<< displayId;
sp<IEvsDisplay> display = evs->openDisplay_1_1(displayId);
if (display == nullptr) {
LOG(ERROR) << "EVS Display unavailable. Exiting.";
return EXIT_FAILURE;
}
if (mode == DEMO_2D) {
if (!run2dSurroundView(surroundViewService, display)) {
LOG(ERROR) << "Something went wrong in 2d surround view demo. "
<< "Exiting.";
return EXIT_FAILURE;
}
} else if (mode == DEMO_3D) {
if (!run3dSurroundView(surroundViewService, display)) {
LOG(ERROR) << "Something went wrong in 3d surround view demo. "
<< "Exiting.";
return EXIT_FAILURE;
}
}
evs->closeDisplay(display);
LOG(DEBUG) << "SV sample app finished running successfully";
return EXIT_SUCCESS;
}