blob: bcc9286039fe6f8161a269362b139738bc7b3639 [file] [log] [blame]
/*
* Copyright (C) 2019 MediaTek Inc.
*
* 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.
*/
#define LOG_TAG "MtkCam/SyncHelperBase"
//
#include <memory>
#include <mtkcam/utils/std/Log.h>
#include "mtkcam/pipeline/utils/SyncHelper/SyncHelperBase.h"
#include <vector>
/******************************************************************************
*
******************************************************************************/
// using namespace NSCam::v3::Utils::Imp;
/******************************************************************************
*
******************************************************************************/
std::shared_ptr<NSCam::v3::Utils::Imp::ISyncHelperBase>
NSCam::v3::Utils::Imp::ISyncHelperBase::createInstance() {
return std::make_shared<SyncHelperBase>();
}
/******************************************************************************
*
******************************************************************************/
NSCam::v3::Utils::Imp::SyncHelperBase::SyncHelperBase() : mUserCounter(0) {
mSyncTimeStart = std::chrono::system_clock::now();
mResultTimeStart = std::chrono::system_clock::now();
}
NSCam::v3::Utils::Imp::SyncHelperBase::~SyncHelperBase() {}
/******************************************************************************
*
******************************************************************************/
NSCam::MERROR NSCam::v3::Utils::Imp::SyncHelperBase::start(int CamId) {
NSCam::MERROR err = NO_ERROR;
mUserCounter++;
mContextMap.emplace(CamId, std::shared_ptr<SyncContext>(new SyncContext()));
return err;
}
/******************************************************************************
*
******************************************************************************/
NSCam::MERROR NSCam::v3::Utils::Imp::SyncHelperBase::stop(int CamId __unused) {
NSCam::MERROR err = NO_ERROR;
mUserCounter--;
if (mUserCounter == 0) {
mContextMap.clear();
}
return err;
}
/******************************************************************************
*
******************************************************************************/
NSCam::MERROR NSCam::v3::Utils::Imp::SyncHelperBase::init(int CamId __unused) {
NSCam::MERROR err = NO_ERROR;
return err;
}
/******************************************************************************
*
******************************************************************************/
NSCam::MERROR NSCam::v3::Utils::Imp::SyncHelperBase::uninit(
int CamId __unused) {
NSCam::MERROR err = NO_ERROR;
return err;
}
/******************************************************************************
*
******************************************************************************/
NSCam::MERROR NSCam::v3::Utils::Imp::SyncHelperBase::syncEnqHW(
SyncParam const& sParam) {
NSCam::MERROR err = NO_ERROR;
std::vector<int> searchCamIdByTargetInSyncQueue;
mSyncQLock.lock();
for (auto& syncTargetCamId : sParam.mSyncCams) {
auto findTargetCamInSyncQueue =
std::find(mSyncQueue.begin(), mSyncQueue.end(), syncTargetCamId);
if (findTargetCamInSyncQueue != mSyncQueue.end()) {
searchCamIdByTargetInSyncQueue.push_back(*findTargetCamInSyncQueue);
}
}
if (searchCamIdByTargetInSyncQueue.size() != sParam.mSyncCams.size()) {
// this cam needs to other cam ready.
mSyncQueue.push_back(sParam.mCamId);
MY_LOGD("CamID = %d wait+ q:t(%zu:%zu)", sParam.mCamId,
sParam.mSyncCams.size(), searchCamIdByTargetInSyncQueue.size());
mSyncQLock.unlock();
auto context = mContextMap.at(sParam.mCamId);
sem_wait(&(context->mSyncSem));
MY_LOGD("CamID = %d wait-", sParam.mCamId);
} else {
mSyncQLock.unlock();
// all camera is ready.
for (auto& camId : searchCamIdByTargetInSyncQueue) {
auto targetContext = mContextMap.at(camId);
sem_post(&(targetContext->mSyncSem));
MY_LOGD("all cam ready CamID = %d, postCamID = %d!", sParam.mCamId,
camId);
mSyncQLock.lock();
// clear camId that in sync queue
mSyncQueue.erase(std::remove(mSyncQueue.begin(), mSyncQueue.end(), camId),
mSyncQueue.end());
auto currentTime = std::chrono::system_clock::now();
std::chrono::duration<double> diff = currentTime - mSyncTimeStart;
MY_LOGD("sync time duration: %lf", diff.count());
mSyncTimeStart = currentTime;
mSyncQLock.unlock();
}
}
return err;
}
/******************************************************************************
*
******************************************************************************/
NSCam::MERROR NSCam::v3::Utils::Imp::SyncHelperBase::syncResultCheck(
SyncParam* sParam) {
NSCam::MERROR err = NO_ERROR;
bool syncResult = true;
std::shared_ptr<SyncContext> context1;
std::shared_ptr<SyncContext> context2;
auto getResult = [](int64_t time1, int64_t time2, int64_t tolerance) {
int timeStamp_ms_main1 = time1 / 1000000;
int timeStamp_ms_main2 = time2 / 1000000;
int tolerance_ms = tolerance / 1000;
int64_t diff = abs(timeStamp_ms_main1 - timeStamp_ms_main2);
if (diff <= tolerance_ms) {
return true;
} else {
return false;
}
};
std::vector<int> searchCamIdByTargetInResultQueue;
// assign current data
context1 = mContextMap.at(sParam->mCamId);
context1->mResultTimeStamp = sParam->mReslutTimeStamp;
mResultQLock.lock();
for (auto& syncTargetCamId : sParam->mSyncCams) {
auto findTargetCamInResultQueue =
std::find(mResultQueue.begin(), mResultQueue.end(), syncTargetCamId);
if (findTargetCamInResultQueue != mResultQueue.end()) {
searchCamIdByTargetInResultQueue.push_back(*findTargetCamInResultQueue);
}
}
if (searchCamIdByTargetInResultQueue.size() != sParam->mSyncCams.size()) {
MY_LOGD("CamID = %d wait+ q:t(%zu:%zu)", sParam->mCamId,
sParam->mSyncCams.size(), searchCamIdByTargetInResultQueue.size());
mResultQueue.push_back(sParam->mCamId);
mResultQLock.unlock();
sem_wait(&(context1->mResultSem));
MY_LOGD("CamID = %d wait-", sParam->mCamId);
for (auto& syncTargetCamId : sParam->mSyncCams) {
context2 = mContextMap.at(syncTargetCamId);
syncResult &=
getResult(context1->mResultTimeStamp, context2->mResultTimeStamp,
sParam->mSyncTolerance);
MY_LOGD("CamID = %d, time1=%" PRId64
"ns, ret = %d, synID = %d, time2=%" PRId64
"ns, tolerance=%" PRId64 "us",
sParam->mCamId, context1->mResultTimeStamp, syncResult,
syncTargetCamId, context2->mResultTimeStamp,
sParam->mSyncTolerance);
}
} else {
mResultQLock.unlock();
// all camera is ready.
for (auto& camId : searchCamIdByTargetInResultQueue) {
context2 = mContextMap.at(camId);
syncResult &=
getResult(context1->mResultTimeStamp, context2->mResultTimeStamp,
sParam->mSyncTolerance);
sem_post(&(context2->mResultSem));
MY_LOGD("CamID = %d, time1=%" PRId64
"ns, ret = %d, synID = %d, time2=%" PRId64 "ns tolerance=%" PRId64
"us",
sParam->mCamId, context1->mResultTimeStamp, syncResult, camId,
context2->mResultTimeStamp, sParam->mSyncTolerance);
mResultQLock.lock();
// clear camId that in result queue
mResultQueue.erase(
std::remove(mResultQueue.begin(), mResultQueue.end(), camId),
mResultQueue.end());
auto currentTime = std::chrono::system_clock::now();
std::chrono::duration<double> diff = currentTime - mResultTimeStart;
MY_LOGD("result time duration: %lf", diff.count());
mResultTimeStart = currentTime;
mResultQLock.unlock();
}
}
sParam->mSyncResult = syncResult;
return err;
}