blob: 0ebf7d52b4713940e866a2ae6e7019659315bddd [file] [log] [blame]
/*
* Copyright (C) 2018-2020 Intel Corporation.
*
* 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 "SyncManager"
#include <sys/sysinfo.h>
#include <math.h>
#include "iutils/CameraLog.h"
#include "SyncManager.h"
namespace icamera {
SyncManager *SyncManager::sInstance = nullptr;
Mutex SyncManager::sLock;
#define SEC_TO_MS(sec) ((sec) * (1000))
#define USEC_TO_MS(usec) ((usec) / (1000))
const int max_vc_sync_count = 128;
SyncManager* SyncManager::getInstance()
{
AutoMutex lock(sLock);
if (sInstance == nullptr) {
sInstance = new SyncManager();
}
return sInstance;
}
void SyncManager::releaseInstance()
{
AutoMutex lock(sLock);
LOG1("@%s", __func__);
if (sInstance) {
delete sInstance;
sInstance = nullptr;
}
}
SyncManager::SyncManager()
{
LOG1("@%s", __func__);
AutoMutex lock(mLock);
for (int i = 0; i < MAX_CAMERA_NUMBER; i++) {
for (int j = 0; j < MAX_BUFFER_COUNT; j++) {
mCameraBufInfo[i][j].sequence = -1;
CLEAR(mCameraBufInfo[i][j].sof_ts);
}
}
mTotalSyncCamNum = 0;
for (int i = 0; i < MAX_CAMERA_NUMBER; i++)
mVcSyncCount[i] = 0;
}
SyncManager::~SyncManager()
{
LOG1("@%s", __func__);
}
bool SyncManager::isSynced(int cameraId, long sequence)
{
LOG1("@%s", __func__);
const int TIME_DIFF_MS = 2;
bool sync = true;
int index = sequence % MAX_BUFFER_COUNT;
AutoMutex lock(mLock);
camera_buf_info bufInfo = mCameraBufInfo[cameraId][index];
int syncNum = 0;
bool isSync[MAX_CAMERA_NUMBER];
long frameSyncedMs[MAX_CAMERA_NUMBER];
long curFrameMs = USEC_TO_MS(bufInfo.sof_ts.tv_usec) + SEC_TO_MS(bufInfo.sof_ts.tv_sec);
//first step: To check whether the current frame is synced with others camera channel
// if timestamp difference <= 2ms, then think the frame is synced
for (int i = 0; i < MAX_CAMERA_NUMBER; i++) {
isSync[i] = false;
frameSyncedMs[i] = 0;
if (mCameraBufInfo[i][0].sequence == -1 || i == cameraId) {
continue;
}
for (int j = 0; j < MAX_BUFFER_COUNT; j++) {
if (mCameraBufInfo[i][j].sequence >= 0) {
camera_buf_info &temp = mCameraBufInfo[i][j];
long tempFrameMs = USEC_TO_MS(temp.sof_ts.tv_usec) + SEC_TO_MS(temp.sof_ts.tv_sec);
if (abs(tempFrameMs - curFrameMs ) <= TIME_DIFF_MS) {
isSync[syncNum] = true;
frameSyncedMs[syncNum] = tempFrameMs;
syncNum++;
break;
}
}
}
}
//second step: if current frame is synced with frames from other cameraID,
// to check whether other 3 channel frames synced or not
if (syncNum >= mTotalSyncCamNum - 1) {
for (int i = 0; i < mTotalSyncCamNum - 1; i++) {
if (isSync[i]) {
if ((i + 1 < mTotalSyncCamNum - 1) &&
abs(frameSyncedMs[i]-frameSyncedMs[i+1]) <= TIME_DIFF_MS) {
sync &= true;
} else if ((i + 1 == mTotalSyncCamNum - 1) &&
abs(frameSyncedMs[i]-frameSyncedMs[0]) <= TIME_DIFF_MS) {
sync &= true;
} else {
sync &= false;
}
}
}
} else {
sync = false;
}
LOG1("Id:%d, sof_ts:%ldms, sequence:%ld sync %d", cameraId, curFrameMs, sequence, sync);
return sync;
}
void SyncManager::updateCameraBufInfo(int cameraId, camera_buf_info* info)
{
LOG1("@%s", __func__);
int index = info->sequence % MAX_BUFFER_COUNT;
AutoMutex lock(mLock);
mCameraBufInfo[cameraId][index] = *info;
}
void SyncManager::updateSyncCamNum()
{
AutoMutex l(mLock);
CheckError(mTotalSyncCamNum >= MAX_CAMERA_NUMBER, VOID_VALUE,
"%s: sync cameras enough!", __func__);
mTotalSyncCamNum++;
}
bool SyncManager::vcSynced(int vc)
{
CheckError(vc >= MAX_CAMERA_NUMBER, false, "%s: vc %d error!", __func__, vc);
AutoMutex l(mVcSyncLock);
int count = mVcSyncCount[vc];
int minCount = INT_MAX;
int maxCount = 0;
for (int i = 0; i < mTotalSyncCamNum; i++) {
minCount = std::min(minCount, mVcSyncCount[i]);
maxCount = std::max(maxCount, mVcSyncCount[i]);
}
// Check again if status is circling back to 0.
// Most of time handling code won't be executed because condition is false.
if (maxCount - minCount > max_vc_sync_count / 2) {
minCount = max_vc_sync_count;
maxCount = 0;
for (int i = 0; i < mTotalSyncCamNum; i++) {
count = (mVcSyncCount[i] + max_vc_sync_count) % (max_vc_sync_count + max_vc_sync_count / 4);
minCount = std::min(minCount, count);
maxCount = std::max(maxCount, count);
}
count = (mVcSyncCount[vc] + max_vc_sync_count) % (max_vc_sync_count + max_vc_sync_count / 4);
}
if (count > minCount) {
LOGVCSYNC("vc %d ready: false", vc);
return false;
} else
return true;
};
void SyncManager::updateVcSyncCount(int vc)
{
CheckError(vc >= MAX_CAMERA_NUMBER, VOID_VALUE, "%s: vc %d error!", __func__, vc);
AutoMutex l(mVcSyncLock);
mVcSyncCount[vc] = (mVcSyncCount[vc] + 1) % (max_vc_sync_count + 1);
};
void SyncManager::printVcSyncCount(void)
{
AutoMutex l(mVcSyncLock);
for (int i = 0; i < mTotalSyncCamNum; i++)
LOGVCSYNC("[%d]", mVcSyncCount[i]);
}
} // namespace icamera