QCamera2: Add buffer identity for video native handle.

Issue: Release_recording() can be called with any Imemory pointer
sent earlier. HAL cannot use this pointer to recognize video frame
to match before release this buffer to kernel.

Fix: Buffer identity is introduced to every video buffer and released
buffer can be found by comparing identity.

CRs-Fixed: 1026840
Change-Id: I287d1276fbf2241a2fc6d470e887a91e1daeca4d
This commit is contained in:
Guruprasad Gaonkar 2016-06-20 17:17:55 -07:00 committed by Prateek Chaubey
parent 665ea6feed
commit c93f5696c8
6 changed files with 105 additions and 80 deletions

View file

@ -703,7 +703,6 @@ void QCamera2HardwareInterface::stop_recording(struct camera_device *device)
// Disable power hint for video encoding
hw->m_perfLock.powerHint(POWER_HINT_VIDEO_ENCODE, false);
mVideoMem = NULL;
hw->lockAPI();
qcamera_api_result_t apiResult;
@ -778,17 +777,6 @@ void QCamera2HardwareInterface::release_recording_frame(
}
LOGD("E camera id %d", hw->getCameraId());
//Close and delete duplicated native handle and FD's.
if ((hw->mVideoMem != NULL) && (hw->mStoreMetaDataInFrame)) {
ret = hw->mVideoMem->closeNativeHandle(opaque, TRUE);
if (ret != NO_ERROR) {
LOGE("Invalid video metadata");
return;
}
} else {
LOGW("Possible FD leak. Release recording called after stop");
}
hw->lockAPI();
qcamera_api_result_t apiResult;
ret = hw->processAPI(QCAMERA_SM_EVT_RELEASE_RECORIDNG_FRAME, (void *)opaque);
@ -1681,7 +1669,6 @@ QCamera2HardwareInterface::QCamera2HardwareInterface(uint32_t cameraId)
mJpegClientHandle(0),
mJpegHandleOwner(false),
mMetadataMem(NULL),
mVideoMem(NULL),
mCACDoneReceived(false),
m_bNeedRestart(false),
mIgnoredPreviewCount(0)
@ -2822,10 +2809,6 @@ QCameraMemory *QCamera2HardwareInterface::allocateStreamBuf(
}
videoMemory->setVideoInfo(usage, fmt);
mem = videoMemory;
if (!mParameters.getBufBatchCount()) {
//For batch mode this will be part of user buffer.
mVideoMem = videoMemory;
}
}
break;
case CAM_STREAM_TYPE_CALLBACK:
@ -3157,7 +3140,6 @@ QCameraMemory *QCamera2HardwareInterface::allocateStreamUserBuf(
}
video_mem->setVideoInfo(usage, fmt);
mem = static_cast<QCameraMemory *>(video_mem);
mVideoMem = video_mem;
}
break;
@ -3594,7 +3576,6 @@ int QCamera2HardwareInterface::startRecording()
int32_t rc = NO_ERROR;
LOGI("E");
mVideoMem = NULL;
//link meta stream with video channel if low power mode.
if (isLowPowerMode()) {
// Find and try to link a metadata stream from preview channel

View file

@ -745,7 +745,6 @@ private:
bool TsMakeupProcess(mm_camera_buf_def_t *frame,QCameraStream * stream,TSRect& faceRect);
#endif
QCameraMemory *mMetadataMem;
QCameraVideoMemory *mVideoMem;
static uint32_t sNextJobId;

View file

@ -1373,7 +1373,7 @@ void QCamera2HardwareInterface::video_stream_cb_routine(mm_camera_super_buf_t *s
nsecs_t timeStamp = 0;
bool triggerTCB = FALSE;
LOGH("[KPI Perf] : BEGIN");
LOGD("[KPI Perf] : BEGIN");
QCamera2HardwareInterface *pme = (QCamera2HardwareInterface *)userdata;
if (pme == NULL ||
pme->mCameraHandle == NULL ||
@ -1402,16 +1402,15 @@ void QCamera2HardwareInterface::video_stream_cb_routine(mm_camera_super_buf_t *s
if (pme->mParameters.getVideoBatchSize() == 0) {
timeStamp = nsecs_t(frame->ts.tv_sec) * 1000000000LL
+ frame->ts.tv_nsec;
LOGD("Video frame to encoder TimeStamp : %lld batch = 0",
timeStamp);
pme->dumpFrameToFile(stream, frame, QCAMERA_DUMP_FRM_VIDEO);
videoMemObj = (QCameraVideoMemory *)frame->mem_info;
video_mem = NULL;
if (NULL != videoMemObj) {
video_mem = videoMemObj->getMemory(frame->buf_idx,
(pme->mStoreMetaDataInFrame > 0)? true : false);
videoMemObj->updateNativeHandle(frame->buf_idx);
triggerTCB = TRUE;
LOGH("Video frame TimeStamp : %lld batch = 0 index = %d",
timeStamp, frame->buf_idx);
}
} else {
//Handle video batch callback
@ -1432,7 +1431,7 @@ void QCamera2HardwareInterface::video_stream_cb_routine(mm_camera_super_buf_t *s
}
}
video_mem = stream->mCurMetaMemory;
nh = videoMemObj->updateNativeHandle(stream->mCurMetaIndex);
nh = videoMemObj->getNativeHandle(stream->mCurMetaIndex);
if (video_mem == NULL || nh == NULL) {
LOGE("No Free metadata. Drop this frame");
stream->mCurBufIndex = -1;
@ -1471,8 +1470,9 @@ void QCamera2HardwareInterface::video_stream_cb_routine(mm_camera_super_buf_t *s
stream->mCurBufIndex++;
if (stream->mCurBufIndex == fd_cnt) {
timeStamp = stream->mFirstTimeStamp;
LOGD("Video frame to encoder TimeStamp : %lld batch = %d",
timeStamp, fd_cnt);
LOGH("Video frame to encoder TimeStamp : %lld batch = %d Buffer idx = %d",
timeStamp, fd_cnt,
nh->data[nh->numFds + nh->numInts - VIDEO_METADATA_NUM_COMMON_INTS]);
stream->mCurBufIndex = -1;
stream->mCurMetaIndex = -1;
stream->mCurMetaMemory = NULL;
@ -1486,7 +1486,7 @@ void QCamera2HardwareInterface::video_stream_cb_routine(mm_camera_super_buf_t *s
int fd_cnt = frame->user_buf.bufs_used;
if (NULL != videoMemObj) {
video_mem = videoMemObj->getMemory(frame->buf_idx, true);
nh = videoMemObj->updateNativeHandle(frame->buf_idx);
nh = videoMemObj->getNativeHandle(frame->buf_idx);
} else {
LOGE("videoMemObj NULL");
}
@ -1494,8 +1494,6 @@ void QCamera2HardwareInterface::video_stream_cb_routine(mm_camera_super_buf_t *s
if (nh != NULL) {
timeStamp = nsecs_t(frame->ts.tv_sec) * 1000000000LL
+ frame->ts.tv_nsec;
LOGD("Batch buffer TimeStamp : %lld FD = %d index = %d fd_cnt = %d",
timeStamp, frame->fd, frame->buf_idx, fd_cnt);
for (int i = 0; i < fd_cnt; i++) {
if (frame->user_buf.buf_idx[i] >= 0) {
@ -1526,6 +1524,8 @@ void QCamera2HardwareInterface::video_stream_cb_routine(mm_camera_super_buf_t *s
}
}
triggerTCB = TRUE;
LOGH("Batch buffer TimeStamp : %lld FD = %d index = %d fd_cnt = %d",
timeStamp, frame->fd, frame->buf_idx, fd_cnt);
} else {
LOGE("No Video Meta Available. Return Buffer");
stream->bufDone(super_frame->bufs[0]->buf_idx);
@ -1550,7 +1550,7 @@ void QCamera2HardwareInterface::video_stream_cb_routine(mm_camera_super_buf_t *s
}
free(super_frame);
LOGH("[KPI Perf] : END");
LOGD("[KPI Perf] : END");
}
/*===========================================================================

View file

@ -1333,7 +1333,7 @@ int QCameraVideoMemory::allocate(uint8_t count, size_t size, uint32_t isSecure)
if (!(mBufType & QCAMERA_MEM_TYPE_BATCH)) {
/*
* FDs = 1
* numInts = 5 //offset, size, usage, timestamp, format
* numInts = 5 //offset, size, usage, timestamp, format + 1 for buffer index
*/
rc = allocateMeta(count, 1, VIDEO_METADATA_NUM_INTS);
if (rc != NO_ERROR) {
@ -1401,10 +1401,11 @@ int QCameraVideoMemory::allocateMore(uint8_t count, size_t size)
(media_metadata_buffer *)mMetadata[i]->data;
//FDs = 1
//numInts = 5 (offset, size, usage, timestamp, format)
mNativeHandle[i] = native_handle_create(1, VIDEO_METADATA_NUM_INTS);
mNativeHandle[i] = native_handle_create(1,
(VIDEO_METADATA_NUM_INTS + VIDEO_METADATA_NUM_COMMON_INTS));
#ifdef USE_MEDIA_EXTENSIONS
packet->eType = kMetadataBufferTypeNativeHandleSource;
packet->pHandle = mNativeHandle[i];
packet->pHandle = NULL;
#else
packet->buffer_type = kMetadataBufferTypeCameraSource;
packet->meta_handle = mNativeHandle[i];
@ -1421,6 +1422,7 @@ int QCameraVideoMemory::allocateMore(uint8_t count, size_t size)
nh->data[3] = mUsage;
nh->data[4] = 0; //dummy value for timestamp in non-batch mode
nh->data[5] = mFormat;
nh->data[6] = i;
}
}
mBufferCount = (uint8_t)(mBufferCount + count);
@ -1444,6 +1446,7 @@ int QCameraVideoMemory::allocateMore(uint8_t count, size_t size)
int QCameraVideoMemory::allocateMeta(uint8_t buf_cnt, int numFDs, int numInts)
{
int rc = NO_ERROR;
int mTotalInts = 0;
for (int i = 0; i < buf_cnt; i++) {
mMetadata[i] = mGetMemory(-1,
@ -1460,7 +1463,9 @@ int QCameraVideoMemory::allocateMeta(uint8_t buf_cnt, int numFDs, int numInts)
}
media_metadata_buffer *packet =
(media_metadata_buffer *)mMetadata[i]->data;
mNativeHandle[i] = native_handle_create(numFDs, (numInts * numFDs));
mTotalInts = (numInts * numFDs);
mNativeHandle[i] = native_handle_create(numFDs,
(mTotalInts + VIDEO_METADATA_NUM_COMMON_INTS));
if (mNativeHandle[i] == NULL) {
LOGE("Error in getting video native handle");
for (int j = (i - 1); j >= 0; j--) {
@ -1471,10 +1476,14 @@ int QCameraVideoMemory::allocateMeta(uint8_t buf_cnt, int numFDs, int numInts)
mMetadata[j]->release(mMetadata[j]);
}
return NO_MEMORY;
} else {
//assign buffer index to native handle.
native_handle_t *nh = mNativeHandle[i];
nh->data[numFDs + mTotalInts] = i;
}
#ifdef USE_MEDIA_EXTENSIONS
packet->eType = kMetadataBufferTypeNativeHandleSource;
packet->pHandle = mNativeHandle[i];
packet->pHandle = NULL;
#else
packet->buffer_type = kMetadataBufferTypeCameraSource;
packet->meta_handle = mNativeHandle[i];
@ -1545,54 +1554,59 @@ void QCameraVideoMemory::deallocate()
camera_memory_t *QCameraVideoMemory::getMemory(uint32_t index,
bool metadata) const
{
int i;
if (index >= mMetaBufCount || (!metadata && index >= mBufferCount))
return NULL;
if (metadata)
if (metadata) {
#ifdef USE_MEDIA_EXTENSIONS
media_metadata_buffer *packet = NULL;
for (i = 0; i < mMetaBufCount; i++) {
packet = (media_metadata_buffer *)mMetadata[i]->data;
if (packet != NULL && packet->pHandle == NULL) {
packet->pHandle = mNativeHandle[index];
break;
}
}
if (i < mMetaBufCount) {
return mMetadata[i];
} else {
LOGE("No free video meta memory");
return NULL;
}
#else
return mMetadata[index];
else
#endif
} else {
return mCameraMemory[index];
}
}
/*===========================================================================
* FUNCTION : updateNativeHandle
* FUNCTION : getNativeHandle
*
* DESCRIPTION: Updating native handle pointer
* DESCRIPTION: getNativeHandle from video buffer
*
* PARAMETERS :
* @index : buffer index
* @metadata: flag if it's metadata
*
* RETURN : camera native handle ptr
* NULL if not supported or failed
* RETURN : native_handle_t * type of handle
*==========================================================================*/
native_handle_t *QCameraVideoMemory::updateNativeHandle(uint32_t index, bool metadata)
native_handle_t *QCameraVideoMemory::getNativeHandle(uint32_t index, bool metadata)
{
if (index >= mMetaBufCount || (!metadata && index >= mBufferCount)) {
if (index >= mMetaBufCount || !metadata)
return NULL;
}
native_handle_t *nh = NULL;
if (metadata && mMetadata[index] != NULL) {
media_metadata_buffer *packet =
(media_metadata_buffer *)mMetadata[index]->data;
nh = mNativeHandle[index];
#ifdef USE_MEDIA_EXTENSIONS
packet->pHandle = nh;
#else
packet->meta_handle = nh;
#endif
}
return nh;
return mNativeHandle[index];
}
/*===========================================================================
* FUNCTION : closeNativeHandle
*
* DESCRIPTION: close video native handle
* DESCRIPTION: close video native handle and update cached ptrs
*
* PARAMETERS :
* @opaque : ptr to video frame to be returned
* @data : ptr to video frame to be returned
*
* RETURN : int32_t type of status
* NO_ERROR -- success
@ -1601,28 +1615,24 @@ native_handle_t *QCameraVideoMemory::updateNativeHandle(uint32_t index, bool met
int QCameraVideoMemory::closeNativeHandle(const void *data, bool metadata)
{
int32_t rc = NO_ERROR;
int32_t index = -1;
#ifdef USE_MEDIA_EXTENSIONS
camera_memory_t *video_mem = NULL;
if (metadata) {
index = getMatchBufIndex(data, metadata);
if (index < 0) {
LOGE("Invalid buffer");
return BAD_VALUE;
}
video_mem = getMemory(index, metadata);
media_metadata_buffer * packet = NULL;
if (video_mem) {
packet = (media_metadata_buffer *)video_mem->data;
}
if (packet != NULL && packet->eType ==
kMetadataBufferTypeNativeHandleSource) {
const media_metadata_buffer *packet =
(const media_metadata_buffer *)data;
if ((packet != NULL) && (packet->eType ==
kMetadataBufferTypeNativeHandleSource)
&& (packet->pHandle)) {
native_handle_close(packet->pHandle);
native_handle_delete(packet->pHandle);
packet->pHandle = NULL;
for (int i = 0; i < mMetaBufCount; i++) {
if(mMetadata[i]->data == data) {
media_metadata_buffer *mem =
(media_metadata_buffer *)mMetadata[i]->data;
mem->pHandle = NULL;
break;
}
}
} else {
LOGE("Invalid Data. Could not release");
return BAD_VALUE;
@ -1652,12 +1662,31 @@ int QCameraVideoMemory::getMatchBufIndex(const void *opaque,
int index = -1;
if (metadata) {
#ifdef USE_MEDIA_EXTENSIONS
const media_metadata_buffer *packet =
(const media_metadata_buffer *)opaque;
native_handle_t *nh = NULL;
if ((packet != NULL) && (packet->eType ==
kMetadataBufferTypeNativeHandleSource)
&& (packet->pHandle)) {
nh = (native_handle_t *)packet->pHandle;
int mCommonIdx = (nh->numInts + nh->numFds -
VIDEO_METADATA_NUM_COMMON_INTS);
for (int i = 0; i < mMetaBufCount; i++) {
if(nh->data[mCommonIdx] == mNativeHandle[i]->data[mCommonIdx]) {
index = i;
break;
}
}
}
#else
for (int i = 0; i < mMetaBufCount; i++) {
if (mMetadata[i]->data == opaque) {
if(mMetadata[i]->data == opaque) {
index = i;
break;
}
}
#endif
} else {
for (int i = 0; i < mBufferCount; i++) {
if (mCameraMemory[i]->data == opaque) {

View file

@ -51,6 +51,8 @@ class QCameraMemoryPool;
//OFFSET, SIZE, USAGE, TIMESTAMP, FORMAT
#define VIDEO_METADATA_NUM_INTS 5
//Buffer identity
#define VIDEO_METADATA_NUM_COMMON_INTS 1
enum QCameraMemType {
QCAMERA_MEM_TYPE_DEFAULT = 0,
@ -231,8 +233,8 @@ public:
int getUsage(){return mUsage;};
int getFormat(){return mFormat;};
int convCamtoOMXFormat(cam_format_t format);
native_handle_t *updateNativeHandle(uint32_t index, bool metadata = true);
int closeNativeHandle(const void *data, bool metadata = true);
native_handle_t *getNativeHandle(uint32_t index, bool metadata = true);
private:
camera_memory_t *mMetadata[MM_CAMERA_MAX_NUM_FRAMES];
uint8_t mMetaBufCount;

View file

@ -1180,13 +1180,27 @@ int32_t QCameraStream::bufDone(const void *opaque, bool isMetaData)
{
int32_t rc = NO_ERROR;
int index = -1;
QCameraVideoMemory *mVideoMem = NULL;
if ((mStreamInfo != NULL)
&& (mStreamInfo->streaming_mode == CAM_STREAMING_MODE_BATCH)
&& (mStreamBatchBufs != NULL)) {
index = mStreamBatchBufs->getMatchBufIndex(opaque, isMetaData);
mVideoMem = (QCameraVideoMemory *)mStreamBatchBufs;
} else if (mStreamBufs != NULL){
index = mStreamBufs->getMatchBufIndex(opaque, isMetaData);
mVideoMem = (QCameraVideoMemory *)mStreamBufs;
}
//Close and delete duplicated native handle and FD's.
if (mVideoMem != NULL) {
rc = mVideoMem->closeNativeHandle(opaque, isMetaData);
if (rc != NO_ERROR) {
LOGE("Invalid video metadata");
return rc;
}
} else {
LOGE("Possible FD leak. Release recording called after stop");
}
if (index == -1 || index >= mNumBufs || mBufDefs == NULL) {