QCamera2: HAL/HAL3: Convert Boottime from ISP to MONOTONIC
Issue: Diplay freeze observed sometimes, if there is any suspend/resume of the device. The issue found to be with differences in the timesources used by display and camera for timestamp calculation. Fix: Measure the clock offset between BOOTTIME and MONOTONIC. The clock domain source for ISP is BOOTTIME and for display, it is MONOTONIC. The offset is used to convert from clock domain of camera to display. Added following set prop to switch between camera time sources. persist.camera.time.monotonic <value> Default value is 1. value 0 indicates Boot time from camera. value 1 indicates Monotonic time from camera. Change-Id: I733aa17e89ccaa7f5ea6d2eae5e1cd6428c81a85 CRs-Fixed: 1005906
This commit is contained in:
parent
40ca15284d
commit
dc89a99bdd
6 changed files with 129 additions and 7 deletions
|
@ -1671,7 +1671,8 @@ QCamera2HardwareInterface::QCamera2HardwareInterface(uint32_t cameraId)
|
|||
mMetadataMem(NULL),
|
||||
mCACDoneReceived(false),
|
||||
m_bNeedRestart(false),
|
||||
mIgnoredPreviewCount(0)
|
||||
mIgnoredPreviewCount(0),
|
||||
mBootToMonoTimestampOffset(0)
|
||||
{
|
||||
#ifdef TARGET_TS_MAKEUP
|
||||
memset(&mFaceRect, -1, sizeof(mFaceRect));
|
||||
|
@ -1959,6 +1960,23 @@ int QCamera2HardwareInterface::openCamera()
|
|||
pthread_mutex_unlock(&gCamLock);
|
||||
}
|
||||
|
||||
// Setprop to decide the time source (whether boottime or monotonic).
|
||||
// By default, use monotonic time.
|
||||
property_get("persist.camera.time.monotonic", value, "1");
|
||||
mBootToMonoTimestampOffset = 0;
|
||||
if (atoi(value) == 1) {
|
||||
// if monotonic is set, then need to use time in monotonic.
|
||||
// So, Measure the clock offset between BOOTTIME and MONOTONIC
|
||||
// The clock domain source for ISP is BOOTTIME and
|
||||
// for display is MONOTONIC
|
||||
// The below offset is used to convert from clock domain of other subsystem
|
||||
// (hardware composer) to that of camera. Assumption is that this
|
||||
// offset won't change during the life cycle of the camera device. In other
|
||||
// words, camera device shouldn't be open during CPU suspend.
|
||||
mBootToMonoTimestampOffset = getBootToMonoTimeOffset();
|
||||
}
|
||||
LOGH("mBootToMonoTimestampOffset = %lld", mBootToMonoTimestampOffset);
|
||||
|
||||
return NO_ERROR;
|
||||
|
||||
error_exit3:
|
||||
|
@ -10075,4 +10093,35 @@ bool QCamera2HardwareInterface::isLowPowerMode()
|
|||
return isLowpower;
|
||||
}
|
||||
|
||||
/*===========================================================================
|
||||
* FUNCTION : getBootToMonoTimeOffset
|
||||
*
|
||||
* DESCRIPTION: Calculate offset that is used to convert from
|
||||
* clock domain of boot to monotonic
|
||||
*
|
||||
* PARAMETERS :
|
||||
* None
|
||||
*
|
||||
* RETURN : clock offset between boottime and monotonic time.
|
||||
*
|
||||
*==========================================================================*/
|
||||
nsecs_t QCamera2HardwareInterface::getBootToMonoTimeOffset()
|
||||
{
|
||||
// try three times to get the clock offset, choose the one
|
||||
// with the minimum gap in measurements.
|
||||
const int tries = 3;
|
||||
nsecs_t bestGap, measured;
|
||||
for (int i = 0; i < tries; ++i) {
|
||||
const nsecs_t tmono = systemTime(SYSTEM_TIME_MONOTONIC);
|
||||
const nsecs_t tbase = systemTime(SYSTEM_TIME_BOOTTIME);
|
||||
const nsecs_t tmono2 = systemTime(SYSTEM_TIME_MONOTONIC);
|
||||
const nsecs_t gap = tmono2 - tmono;
|
||||
if (i == 0 || gap < bestGap) {
|
||||
bestGap = gap;
|
||||
measured = tbase - ((tmono + tmono2) >> 1);
|
||||
}
|
||||
}
|
||||
return measured;
|
||||
}
|
||||
|
||||
}; // namespace qcamera
|
||||
|
|
|
@ -382,6 +382,7 @@ private:
|
|||
QCameraExif *getExifData();
|
||||
cam_sensor_t getSensorType();
|
||||
bool isLowPowerMode();
|
||||
nsecs_t getBootToMonoTimeOffset();
|
||||
|
||||
int32_t processAutoFocusEvent(cam_auto_focus_data_t &focus_data);
|
||||
int32_t processZoomEvent(cam_crop_data_t &crop_info);
|
||||
|
@ -765,7 +766,9 @@ private:
|
|||
Mutex mMapLock;
|
||||
Condition mMapCond;
|
||||
// Count to determine the number of preview frames ignored for displaying.
|
||||
uint8_t mIgnoredPreviewCount;
|
||||
uint8_t mIgnoredPreviewCount;
|
||||
//The offset between BOOTTIME and MONOTONIC timestamps
|
||||
nsecs_t mBootToMonoTimestampOffset;
|
||||
};
|
||||
|
||||
}; // namespace qcamera
|
||||
|
|
|
@ -734,6 +734,9 @@ void QCamera2HardwareInterface::synchronous_stream_cb_routine(
|
|||
}
|
||||
|
||||
frameTime = nsecs_t(frame->ts.tv_sec) * 1000000000LL + frame->ts.tv_nsec;
|
||||
// Convert Boottime from camera to Monotime for display if needed.
|
||||
// Otherwise, mBootToMonoTimestampOffset value will be 0.
|
||||
frameTime = frameTime - pme->mBootToMonoTimestampOffset;
|
||||
// Calculate the future presentation time stamp for displaying frames at regular interval
|
||||
//mPreviewTimestamp = pme->mCameraDisplay.computePresentationTimeStamp(frameTime);
|
||||
stream->mStreamTimestamp = frameTime;
|
||||
|
@ -1538,6 +1541,11 @@ void QCamera2HardwareInterface::video_stream_cb_routine(mm_camera_super_buf_t *s
|
|||
cbArg.cb_type = QCAMERA_DATA_TIMESTAMP_CALLBACK;
|
||||
cbArg.msg_type = CAMERA_MSG_VIDEO_FRAME;
|
||||
cbArg.data = video_mem;
|
||||
|
||||
// Convert Boottime from camera to Monotime for video if needed.
|
||||
// Otherwise, mBootToMonoTimestampOffset value will be 0.
|
||||
timeStamp = timeStamp - pme->mBootToMonoTimestampOffset;
|
||||
LOGD("Final video buffer TimeStamp : %lld ", timeStamp);
|
||||
cbArg.timestamp = timeStamp;
|
||||
int32_t rc = pme->m_cbNotifier.notifyCallback(cbArg);
|
||||
if (rc != NO_ERROR) {
|
||||
|
|
|
@ -63,6 +63,8 @@ namespace qcamera {
|
|||
|
||||
#define DATA_PTR(MEM_OBJ,INDEX) MEM_OBJ->getPtr( INDEX )
|
||||
|
||||
#define TIME_SOURCE ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN
|
||||
|
||||
#define EMPTY_PIPELINE_DELAY 2
|
||||
#define PARTIAL_RESULT_COUNT 2
|
||||
#define FRAME_SKIP_DELAY 0
|
||||
|
@ -361,7 +363,9 @@ QCamera3HardwareInterface::QCamera3HardwareInterface(uint32_t cameraId,
|
|||
mLdafCalibExist(false),
|
||||
mPowerHintEnabled(false),
|
||||
mLastCustIntentFrmNum(-1),
|
||||
mState(CLOSED)
|
||||
mState(CLOSED),
|
||||
mBootToMonoTimestampOffset(0),
|
||||
mUseAVTimer(false)
|
||||
{
|
||||
getLogLevel();
|
||||
m_perfLock.lock_init();
|
||||
|
@ -730,6 +734,23 @@ int QCamera3HardwareInterface::openCamera()
|
|||
pthread_mutex_unlock(&gCamLock);
|
||||
}
|
||||
|
||||
// Setprop to decide the time source (whether boottime or monotonic).
|
||||
// By default, use monotonic time.
|
||||
property_get("persist.camera.time.monotonic", value, "1");
|
||||
mBootToMonoTimestampOffset = 0;
|
||||
if (atoi(value) == 1) {
|
||||
// if monotonic is set, then need to use time in monotonic.
|
||||
// So, Measure the clock offset between BOOTTIME and MONOTONIC
|
||||
// The clock domain source for ISP is BOOTTIME and
|
||||
// for display is MONOTONIC
|
||||
// The below offset is used to convert from clock domain of other subsystem
|
||||
// (hardware composer) to that of camera. Assumption is that this
|
||||
// offset won't change during the life cycle of the camera device. In other
|
||||
// words, camera device shouldn't be open during CPU suspend.
|
||||
mBootToMonoTimestampOffset = getBootToMonoTimeOffset();
|
||||
}
|
||||
LOGH("mBootToMonoTimestampOffset = %lld", mBootToMonoTimestampOffset);
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
|
@ -2615,6 +2636,12 @@ void QCamera3HardwareInterface::handleMetadataWithLock(
|
|||
uint32_t frame_number, urgent_frame_number;
|
||||
int64_t capture_time;
|
||||
|
||||
// Convert Boottime from camera to Monotime except for VT usecase where AVTimer is used.
|
||||
uint8_t timestampSource = TIME_SOURCE;
|
||||
nsecs_t timeOffset = mBootToMonoTimestampOffset;
|
||||
if (mUseAVTimer || (ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN != timestampSource))
|
||||
timeOffset = 0;
|
||||
|
||||
int32_t *p_frame_number_valid =
|
||||
POINTER_OF_META(CAM_INTF_META_FRAME_NUMBER_VALID, metadata);
|
||||
uint32_t *p_frame_number = POINTER_OF_META(CAM_INTF_META_FRAME_NUMBER, metadata);
|
||||
|
@ -2640,7 +2667,7 @@ void QCamera3HardwareInterface::handleMetadataWithLock(
|
|||
} else {
|
||||
frame_number_valid = *p_frame_number_valid;
|
||||
frame_number = *p_frame_number;
|
||||
capture_time = *p_capture_time;
|
||||
capture_time = *p_capture_time - timeOffset;
|
||||
urgent_frame_number_valid = *p_urgent_frame_number_valid;
|
||||
urgent_frame_number = *p_urgent_frame_number;
|
||||
}
|
||||
|
@ -3367,6 +3394,7 @@ int QCamera3HardwareInterface::processCaptureRequest(
|
|||
LOGE("Failed to disable CDS for HFR mode");
|
||||
|
||||
}
|
||||
|
||||
setMobicat();
|
||||
|
||||
/* Set fps and hfr mode while sending meta stream info so that sensor
|
||||
|
@ -6258,7 +6286,7 @@ int QCamera3HardwareInterface::initStaticMetadata(uint32_t cameraId)
|
|||
staticInfo.update(ANDROID_TONEMAP_MAX_CURVE_POINTS,
|
||||
&gCamCapability[cameraId]->max_tone_map_curve_points, 1);
|
||||
|
||||
uint8_t timestampSource = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;
|
||||
uint8_t timestampSource = TIME_SOURCE;
|
||||
staticInfo.update(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
|
||||
×tampSource, 1);
|
||||
|
||||
|
@ -10109,4 +10137,35 @@ int32_t QCamera3HardwareInterface::setBundleInfo()
|
|||
return rc;
|
||||
}
|
||||
|
||||
/*===========================================================================
|
||||
* FUNCTION : getBootToMonoTimeOffset
|
||||
*
|
||||
* DESCRIPTION: Calculate offset that is used to convert from
|
||||
* clock domain of boot to monotonic
|
||||
*
|
||||
* PARAMETERS :
|
||||
* None
|
||||
*
|
||||
* RETURN : clock offset between boottime and monotonic time.
|
||||
*
|
||||
*==========================================================================*/
|
||||
nsecs_t QCamera3HardwareInterface::getBootToMonoTimeOffset()
|
||||
{
|
||||
// try three times to get the clock offset, choose the one
|
||||
// with the minimum gap in measurements.
|
||||
const int tries = 3;
|
||||
nsecs_t bestGap, measured;
|
||||
for (int i = 0; i < tries; ++i) {
|
||||
const nsecs_t tmono = systemTime(SYSTEM_TIME_MONOTONIC);
|
||||
const nsecs_t tbase = systemTime(SYSTEM_TIME_BOOTTIME);
|
||||
const nsecs_t tmono2 = systemTime(SYSTEM_TIME_MONOTONIC);
|
||||
const nsecs_t gap = tmono2 - tmono;
|
||||
if (i == 0 || gap < bestGap) {
|
||||
bestGap = gap;
|
||||
measured = tbase - ((tmono + tmono2) >> 1);
|
||||
}
|
||||
}
|
||||
return measured;
|
||||
}
|
||||
|
||||
}; //end namespace qcamera
|
||||
|
|
|
@ -64,7 +64,6 @@ using ::android::hardware::camera::common::V1_0::helper::CameraMetadata;
|
|||
#endif
|
||||
|
||||
/* Time related macros */
|
||||
typedef int64_t nsecs_t;
|
||||
#define NSEC_PER_SEC 1000000000LLU
|
||||
#define NSEC_PER_USEC 1000LLU
|
||||
#define NSEC_PER_33MSEC 33000000LLU
|
||||
|
@ -292,6 +291,7 @@ private:
|
|||
int32_t notifyErrorForPendingRequests();
|
||||
int32_t getReprocessibleOutputStreamId(uint32_t &id);
|
||||
int32_t handleCameraDeviceError();
|
||||
nsecs_t getBootToMonoTimeOffset();
|
||||
|
||||
bool isOnEncoder(const cam_dimension_t max_viewfinder_size,
|
||||
uint32_t width, uint32_t height);
|
||||
|
@ -497,6 +497,9 @@ private:
|
|||
uint32_t mSurfaceStridePadding;
|
||||
|
||||
State mState;
|
||||
//The offset between BOOTTIME and MONOTONIC timestamps
|
||||
nsecs_t mBootToMonoTimestampOffset;
|
||||
bool mUseAVTimer;
|
||||
};
|
||||
|
||||
}; // namespace qcamera
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
# Camera
|
||||
PRODUCT_PROPERTY_OVERRIDES += \
|
||||
media.camera.ts.monotonic=0
|
||||
media.camera.ts.monotonic=1
|
||||
|
||||
# Properties
|
||||
PRODUCT_PROPERTY_OVERRIDES += \
|
||||
|
|
Loading…
Reference in a new issue