You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
169 lines
4.9 KiB
169 lines
4.9 KiB
4 months ago
|
// 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 "FaceTracker.h"
|
||
|
|
||
|
#include <android-base/logging.h>
|
||
|
#include <android/binder_manager.h>
|
||
|
#include <utils/Log.h>
|
||
|
|
||
|
#include <memory>
|
||
|
#include <mutex>
|
||
|
#include <thread>
|
||
|
|
||
|
namespace android {
|
||
|
namespace automotive {
|
||
|
namespace computepipe {
|
||
|
|
||
|
using ::android::automotive::computepipe::example::FaceOutput;
|
||
|
namespace {
|
||
|
constexpr char kReigstryInterface[] = "router";
|
||
|
constexpr char kGraphName[] = "Face Tracker Graph";
|
||
|
} // namespace
|
||
|
|
||
|
/**
|
||
|
* RemoteState monitor
|
||
|
*/
|
||
|
PipeState RemoteState::GetCurrentState() {
|
||
|
std::unique_lock<std::mutex> lock(mStateLock);
|
||
|
mWait.wait(lock, [this]() { return hasChanged; });
|
||
|
hasChanged = false;
|
||
|
return mState;
|
||
|
}
|
||
|
|
||
|
void RemoteState::UpdateCurrentState(const PipeState& state) {
|
||
|
std::lock_guard<std::mutex> lock(mStateLock);
|
||
|
mState = state;
|
||
|
if (mState == PipeState::ERR_HALT) {
|
||
|
mTerminationCb(true, "Received error from runner");
|
||
|
} else if (mState == PipeState::DONE) {
|
||
|
mTerminationCb(false, "");
|
||
|
} else {
|
||
|
hasChanged = true;
|
||
|
mWait.notify_all();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
RemoteState::RemoteState(std::function<void(bool, std::string)>& cb) : mTerminationCb(cb) {
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* StateCallback methods
|
||
|
*/
|
||
|
StateCallback::StateCallback(std::shared_ptr<RemoteState> s) : mStateTracker(s) {
|
||
|
}
|
||
|
|
||
|
ndk::ScopedAStatus StateCallback::handleState(PipeState state) {
|
||
|
mStateTracker->UpdateCurrentState(state);
|
||
|
return ndk::ScopedAStatus::ok();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* FaceTracker methods
|
||
|
*/
|
||
|
ndk::ScopedAStatus FaceTracker::init(std::function<void(bool, std::string)>&& cb) {
|
||
|
auto termination = cb;
|
||
|
mRemoteState = std::make_shared<RemoteState>(termination);
|
||
|
std::string instanceName = std::string() + IPipeQuery::descriptor + "/" + kReigstryInterface;
|
||
|
|
||
|
ndk::SpAIBinder binder(AServiceManager_getService(instanceName.c_str()));
|
||
|
CHECK(binder.get());
|
||
|
|
||
|
std::shared_ptr<IPipeQuery> queryService = IPipeQuery::fromBinder(binder);
|
||
|
mClientInfo = ndk::SharedRefBase::make<ClientInfo>();
|
||
|
ndk::ScopedAStatus status = queryService->getPipeRunner(kGraphName, mClientInfo, &mPipeRunner);
|
||
|
if (!status.isOk()) {
|
||
|
LOG(ERROR) << "Failed to get handle to runner";
|
||
|
return status;
|
||
|
}
|
||
|
mStreamCallback = ndk::SharedRefBase::make<StreamCallback>();
|
||
|
mStateCallback = ndk::SharedRefBase::make<StateCallback>(mRemoteState);
|
||
|
return setupConfig();
|
||
|
}
|
||
|
|
||
|
ndk::ScopedAStatus FaceTracker::setupConfig() {
|
||
|
ndk::ScopedAStatus status = mPipeRunner->init(mStateCallback);
|
||
|
if (!status.isOk()) {
|
||
|
LOG(ERROR) << "Failed to init runner";
|
||
|
return status;
|
||
|
}
|
||
|
status = mPipeRunner->setPipeInputSource(0);
|
||
|
if (!status.isOk()) {
|
||
|
LOG(ERROR) << "Failed to set pipe input config";
|
||
|
return status;
|
||
|
}
|
||
|
status = mPipeRunner->setPipeOutputConfig(0, 10, mStreamCallback);
|
||
|
if (!status.isOk()) {
|
||
|
LOG(ERROR) << "Failed to set pipe output config";
|
||
|
return status;
|
||
|
}
|
||
|
status = mPipeRunner->applyPipeConfigs();
|
||
|
if (!status.isOk()) {
|
||
|
LOG(ERROR) << "Failed to set apply configs";
|
||
|
return status;
|
||
|
}
|
||
|
std::thread t(&FaceTracker::start, this);
|
||
|
t.detach();
|
||
|
return ndk::ScopedAStatus::ok();
|
||
|
}
|
||
|
|
||
|
void FaceTracker::start() {
|
||
|
PipeState state = mRemoteState->GetCurrentState();
|
||
|
CHECK(state == PipeState::CONFIG_DONE);
|
||
|
ndk::ScopedAStatus status = mPipeRunner->startPipe();
|
||
|
CHECK(status.isOk());
|
||
|
state = mRemoteState->GetCurrentState();
|
||
|
CHECK(state == PipeState::RUNNING);
|
||
|
}
|
||
|
|
||
|
void FaceTracker::stop() {
|
||
|
ndk::ScopedAStatus status = mPipeRunner->startPipe();
|
||
|
CHECK(status.isOk());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Stream Callback implementation
|
||
|
*/
|
||
|
|
||
|
ndk::ScopedAStatus StreamCallback::deliverPacket(const PacketDescriptor& in_packet) {
|
||
|
std::string output(in_packet.data.begin(), in_packet.data.end());
|
||
|
|
||
|
FaceOutput faceData;
|
||
|
faceData.ParseFromString(output);
|
||
|
|
||
|
BoundingBox currentBox = faceData.box();
|
||
|
|
||
|
if (!faceData.has_box()) {
|
||
|
mLastBox = BoundingBox();
|
||
|
return ndk::ScopedAStatus::ok();
|
||
|
}
|
||
|
|
||
|
if (!mLastBox.has_top_x()) {
|
||
|
mLastBox = currentBox;
|
||
|
return ndk::ScopedAStatus::ok();
|
||
|
}
|
||
|
|
||
|
if (currentBox.top_x() > mLastBox.top_x() + 1) {
|
||
|
LOG(ERROR) << "Face moving left";
|
||
|
} else if (currentBox.top_x() + 1 < mLastBox.top_x()) {
|
||
|
LOG(ERROR) << "Face moving right";
|
||
|
}
|
||
|
mLastBox = currentBox;
|
||
|
return ndk::ScopedAStatus::ok();
|
||
|
}
|
||
|
|
||
|
} // namespace computepipe
|
||
|
} // namespace automotive
|
||
|
} // namespace android
|