summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--exynos_omx/codecs/exynos_codecs/video/exynos5/mfc_v4l2/dec/src/ExynosVideoDecoder.c4
-rw-r--r--gralloc/gralloc.cpp10
-rw-r--r--gralloc/mapper.cpp102
-rw-r--r--libcamera2/ExynosCameraHWInterface2.cpp58
-rw-r--r--libcamera2/ExynosCameraHWInterface2.h2
-rw-r--r--libgscaler/exynos_gsc_utils.h1
-rw-r--r--libgscaler/exynos_gscaler.c19
7 files changed, 169 insertions, 27 deletions
diff --git a/exynos_omx/codecs/exynos_codecs/video/exynos5/mfc_v4l2/dec/src/ExynosVideoDecoder.c b/exynos_omx/codecs/exynos_codecs/video/exynos5/mfc_v4l2/dec/src/ExynosVideoDecoder.c
index a456a2b..48e152f 100644
--- a/exynos_omx/codecs/exynos_codecs/video/exynos5/mfc_v4l2/dec/src/ExynosVideoDecoder.c
+++ b/exynos_omx/codecs/exynos_codecs/video/exynos5/mfc_v4l2/dec/src/ExynosVideoDecoder.c
@@ -1483,7 +1483,9 @@ static ExynosVideoErrorType MFC_Decoder_Enqueue_Inbuf(
buf.m.planes[i].bytesused = dataSize[i];
}
- if ((((OMX_BUFFERHEADERTYPE *)pPrivate)->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) {
+ // FIXME: figure out why |pPrivate| may be NULL.
+ if (pPrivate &&
+ (((OMX_BUFFERHEADERTYPE *)pPrivate)->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) {
buf.flags |= V4L2_BUF_FLAG_LAST_FRAME;
ALOGV("%s: OMX_BUFFERFLAG_EOS => LAST_FRAME: 0x%x", __func__,
!!(buf.flags & V4L2_BUF_FLAG_LAST_FRAME));
diff --git a/gralloc/gralloc.cpp b/gralloc/gralloc.cpp
index b5f269b..8e26ced 100644
--- a/gralloc/gralloc.cpp
+++ b/gralloc/gralloc.cpp
@@ -71,6 +71,11 @@ extern int gralloc_lock(gralloc_module_t const* module,
int l, int t, int w, int h,
void** vaddr);
+extern int gralloc_lock_ycbcr(gralloc_module_t const* module,
+ buffer_handle_t handle, int usage,
+ int l, int t, int w, int h,
+ struct android_ycbcr *ycbcr);
+
extern int gralloc_unlock(gralloc_module_t const* module,
buffer_handle_t handle);
@@ -80,6 +85,9 @@ extern int gralloc_register_buffer(gralloc_module_t const* module,
extern int gralloc_unregister_buffer(gralloc_module_t const* module,
buffer_handle_t handle);
+extern int gralloc_perform(struct gralloc_module_t const* module,
+ int operation, ... );
+
/*****************************************************************************/
static struct hw_module_methods_t gralloc_module_methods = {
@@ -101,6 +109,8 @@ base: {
unregisterBuffer: gralloc_unregister_buffer,
lock: gralloc_lock,
unlock: gralloc_unlock,
+ perform: gralloc_perform,
+ lock_ycbcr: gralloc_lock_ycbcr,
},
framebuffer: 0,
flags: 0,
diff --git a/gralloc/mapper.cpp b/gralloc/mapper.cpp
index 1a70973..190a7a7 100644
--- a/gralloc/mapper.cpp
+++ b/gralloc/mapper.cpp
@@ -31,6 +31,7 @@
#include <hardware/gralloc.h>
#include "gralloc_priv.h"
+#include "exynos_format.h"
#include <ion/ion.h>
#include <linux/ion.h>
@@ -57,16 +58,59 @@ static int gralloc_unmap(gralloc_module_t const* module, buffer_handle_t handle)
{
private_handle_t* hnd = (private_handle_t*)handle;
- if (!hnd->base)
- return 0;
-
- if (munmap(hnd->base, hnd->size) < 0) {
+ if (hnd->base != NULL && munmap(hnd->base, hnd->size) < 0) {
ALOGE("%s :could not unmap %s %p %d", __func__, strerror(errno),
hnd->base, hnd->size);
}
+ hnd->base = NULL;
+ if (hnd->base1 != NULL && hnd->format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
+ // unmap plane-2 of mapped NV12 TILED format
+ size_t chroma_vstride = ALIGN(hnd->height / 2, 32);
+ size_t chroma_size = chroma_vstride * hnd->stride;
+ if (munmap(hnd->base1, chroma_size) < 0) {
+ ALOGE("%s :could not unmap %s %p %zd", __func__, strerror(errno),
+ hnd->base1, chroma_size);
+ }
+ hnd->base1 = NULL;
+ }
ALOGV("%s: base %p %d %d %d %d\n", __func__, hnd->base, hnd->size,
hnd->width, hnd->height, hnd->stride);
- hnd->base = 0;
+ return 0;
+}
+
+
+static int gralloc_map_yuv(gralloc_module_t const* module, buffer_handle_t handle)
+{
+ private_handle_t* hnd = (private_handle_t*)handle;
+
+ // only support NV12 TILED format
+ if (hnd->format != HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
+ return -EINVAL;
+ }
+
+ size_t chroma_vstride = ALIGN(hnd->height / 2, 32);
+ size_t chroma_size = chroma_vstride * hnd->stride;
+ ALOGI("map_yuv: size=%d/%zu", hnd->size, chroma_size);
+
+ if (hnd->base == NULL) {
+ int err = gralloc_map(module, handle);
+ if (err != 0) {
+ return err;
+ }
+ }
+
+ // map plane-2 for NV12 TILED format
+ void* mappedAddress = mmap(0, chroma_size, PROT_READ|PROT_WRITE, MAP_SHARED,
+ hnd->fd1, 0);
+ if (mappedAddress == MAP_FAILED) {
+ ALOGE("%s: could not mmap %s", __func__, strerror(errno));
+ gralloc_unmap(module, handle);
+ return -errno;
+ }
+
+ ALOGV("%s: chroma %p %d %d %d %d\n", __func__, mappedAddress, hnd->size,
+ hnd->width, hnd->height, hnd->stride);
+ hnd->base1 = mappedAddress;
return 0;
}
@@ -157,6 +201,54 @@ int gralloc_lock(gralloc_module_t const* module,
return 0;
}
+int gralloc_lock_ycbcr(gralloc_module_t const* module,
+ buffer_handle_t handle, int usage,
+ int l, int t, int w, int h,
+ struct android_ycbcr *ycbcr)
+{
+ // This is called when a YUV buffer is being locked for software
+ // access. In this implementation we have nothing to do since
+ // no synchronization with the HW is needed.
+ // Typically this is used to wait for the h/w to finish with
+ // this buffer if relevant. The data cache may need to be
+ // flushed or invalidated depending on the usage bits and the
+ // hardware.
+
+ if (private_handle_t::validate(handle) < 0)
+ return -EINVAL;
+
+ private_handle_t* hnd = (private_handle_t*)handle;
+ ALOGV("lock_ycbcr for fmt=%d %dx%d %dx%d %d", hnd->format, hnd->width, hnd->height,
+ hnd->stride, hnd->vstride, hnd->size);
+ switch (hnd->format) {
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+ {
+ int err = 0;
+ if (hnd->base1 == NULL || hnd->base == NULL) {
+ err = gralloc_map_yuv(module, hnd);
+ }
+ if (err == 0) {
+ ycbcr->y = (void*)hnd->base;
+ ycbcr->cb = (void*)hnd->base1;
+ ycbcr->cr = (void*)((uint8_t *)hnd->base + 1);
+ ycbcr->ystride = hnd->stride;
+ ycbcr->cstride = hnd->stride;
+ ycbcr->chroma_step = 2;
+ memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
+ }
+ return err;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+int gralloc_perform(struct gralloc_module_t const* module, int operation, ... )
+{
+ // dummy implementation required to implement lock_ycbcr
+ return -EINVAL;
+}
+
int gralloc_unlock(gralloc_module_t const* module,
buffer_handle_t handle)
{
diff --git a/libcamera2/ExynosCameraHWInterface2.cpp b/libcamera2/ExynosCameraHWInterface2.cpp
index 8fce907..fa6c8d3 100644
--- a/libcamera2/ExynosCameraHWInterface2.cpp
+++ b/libcamera2/ExynosCameraHWInterface2.cpp
@@ -615,10 +615,15 @@ void RequestManager::ApplyDynamicMetadata(struct camera2_shot_ext *shot_ext)
ALOGV("DEBUG(%s): frameCnt(%d)", __FUNCTION__, shot_ext->shot.ctl.request.frameCount);
for (i = 0 ; i < NUM_MAX_REQUEST_MGR_ENTRY ; i++) {
- if((entries[i].internal_shot.shot.ctl.request.frameCount == shot_ext->shot.ctl.request.frameCount)
- && (entries[i].status == CAPTURED)){
- entries[i].status = METADONE;
- break;
+ if (entries[i].internal_shot.shot.ctl.request.frameCount
+ == shot_ext->shot.ctl.request.frameCount) {
+ if (entries[i].status == CAPTURED) {
+ entries[i].status = METADONE;
+ break;
+ }
+ if (entries[i].status == METADONE) {
+ return;
+ }
}
}
@@ -861,9 +866,10 @@ camera2_shot_ext * RequestManager::GetInternalShotExt(int index)
return &currentEntry->internal_shot;
}
-int RequestManager::FindFrameCnt(struct camera2_shot_ext * shot_ext)
+int RequestManager::FindFrameCnt(struct camera2_shot_ext * shot_ext, bool drain)
{
Mutex::Autolock lock(m_requestMutex);
+ Mutex::Autolock lock2(m_numOfEntriesLock);
int i;
if (m_numOfEntries == 0) {
@@ -879,6 +885,9 @@ int RequestManager::FindFrameCnt(struct camera2_shot_ext * shot_ext)
entries[i].status = CAPTURED;
return entries[i].internal_shot.shot.ctl.request.frameCount;
}
+ if (drain && (entries[i].status >= CAPTURED)) {
+ return entries[i].internal_shot.shot.ctl.request.frameCount;
+ }
CAM_LOGE("ERR(%s): frameCount(%d), index(%d), status(%d)", __FUNCTION__, shot_ext->shot.ctl.request.frameCount, i, entries[i].status);
}
@@ -1052,7 +1061,7 @@ ExynosCameraHWInterface2::ExynosCameraHWInterface2(int cameraId, camera2_device_
m_ctlInfo.flash.m_afFlashDoneFlg= false;
m_ctlInfo.flash.m_flashEnableFlg = false;
m_ctlInfo.flash.m_flashFrameCount = 0;
- m_ctlInfo.flash.m_flashCnt = 0;
+ m_ctlInfo.flash.m_flashCnt = IS_FLASH_STATE_NONE;
m_ctlInfo.flash.m_flashTimeOut = 0;
m_ctlInfo.flash.m_flashDecisionResult = false;
m_ctlInfo.flash.m_flashTorchMode = false;
@@ -2957,7 +2966,7 @@ void ExynosCameraHWInterface2::m_preCaptureSetter(struct camera2_shot_ext * shot
shot_ext->request_scc = 0;
shot_ext->request_scp = 0;
m_ctlInfo.flash.m_flashEnableFlg = false;
- m_ctlInfo.flash.m_flashCnt = 0;
+ m_ctlInfo.flash.m_flashCnt = IS_FLASH_STATE_NONE;
m_ctlInfo.flash.m_afFlashDoneFlg= false;
break;
case IS_FLASH_STATE_NONE:
@@ -3154,7 +3163,7 @@ void ExynosCameraHWInterface2::m_sensorThreadFunc(SignalDrivenThread * self)
matchedFrameCnt = m_ctlInfo.flash.m_flashFrameCount;
ALOGV("Skip frame, request is fixed at %d", matchedFrameCnt);
} else {
- matchedFrameCnt = m_requestManager->FindFrameCnt(shot_ext);
+ matchedFrameCnt = m_requestManager->FindFrameCnt(shot_ext, m_isRequestQueueNull);
}
if (matchedFrameCnt == -1 && m_vdisBubbleCnt > 0) {
@@ -3231,7 +3240,7 @@ void ExynosCameraHWInterface2::m_sensorThreadFunc(SignalDrivenThread * self)
m_ctlInfo.flash.m_flashEnableFlg = false;
m_ctlInfo.flash.m_afFlashDoneFlg = false;
m_ctlInfo.flash.m_flashDecisionResult = false;
- m_ctlInfo.flash.m_flashCnt = 0;
+ m_ctlInfo.flash.m_flashCnt = IS_FLASH_STATE_NONE;
}
m_ctlInfo.af.m_afTriggerTimeOut = 1;
}
@@ -3367,7 +3376,7 @@ void ExynosCameraHWInterface2::m_sensorThreadFunc(SignalDrivenThread * self)
if (!m_ctlInfo.flash.m_flashDecisionResult) {
m_ctlInfo.flash.m_flashEnableFlg = false;
m_ctlInfo.flash.m_afFlashDoneFlg = false;
- m_ctlInfo.flash.m_flashCnt = 0;
+ m_ctlInfo.flash.m_flashCnt = IS_FLASH_STATE_NONE;
} else if ((m_ctlInfo.flash.m_flashCnt == IS_FLASH_STATE_AUTO_DONE) ||
(m_ctlInfo.flash.m_flashCnt == IS_FLASH_STATE_AUTO_OFF)) {
ALOGD("(%s): [Flash] Flash capture start : skip request scc 1#####", __FUNCTION__);
@@ -3381,7 +3390,7 @@ void ExynosCameraHWInterface2::m_sensorThreadFunc(SignalDrivenThread * self)
shot_ext->shot.ctl.aa.aeflashMode = AA_FLASHMODE_OFF;
m_ctlInfo.flash.m_flashEnableFlg = false;
m_ctlInfo.flash.m_afFlashDoneFlg= false;
- m_ctlInfo.flash.m_flashCnt = 0;
+ m_ctlInfo.flash.m_flashCnt = IS_FLASH_STATE_NONE;
}
} else if (shot_ext->shot.ctl.aa.captureIntent == AA_CAPTURE_INTENT_STILL_CAPTURE) {
m_ctlInfo.flash.m_flashDecisionResult = false;
@@ -3408,8 +3417,14 @@ void ExynosCameraHWInterface2::m_sensorThreadFunc(SignalDrivenThread * self)
shot_ext->request_scc = 0;
m_reprocessingFrameCnt = shot_ext->shot.ctl.request.frameCount;
m_ctlInfo.flash.m_flashDecisionResult = false;
- memcpy(&m_jpegMetadata, (void*)(m_requestManager->GetInternalShotExtByFrameCnt(m_reprocessingFrameCnt)),
- sizeof(struct camera2_shot_ext));
+ void *shot = m_requestManager->GetInternalShotExtByFrameCnt(m_reprocessingFrameCnt);
+ if (!shot) { // m_isRequestQueueNull reuse current
+ ALOGD("(%s): isReprocessing: "
+ "m_reprocessingFrameCnt missing, using shot_ext",
+ __FUNCTION__);
+ shot = shot_ext;
+ }
+ memcpy(&m_jpegMetadata, shot, sizeof(struct camera2_shot_ext));
m_streamThreads[1]->SetSignal(SIGNAL_STREAM_REPROCESSING_START);
m_ctlInfo.flash.m_flashEnableFlg = false;
}
@@ -3512,11 +3527,18 @@ void ExynosCameraHWInterface2::m_sensorThreadFunc(SignalDrivenThread * self)
if (shot_ext->request_scc) {
ALOGV("send SIGNAL_STREAM_DATA_COMING (SCC)");
if (shot_ext->shot.ctl.request.outputStreams[0] & STREAM_MASK_JPEG) {
- if (m_ctlInfo.flash.m_flashCnt < IS_FLASH_STATE_CAPTURE)
- memcpy(&m_jpegMetadata, (void*)(m_requestManager->GetInternalShotExtByFrameCnt(shot_ext->shot.ctl.request.frameCount)),
- sizeof(struct camera2_shot_ext));
- else
- memcpy(&m_jpegMetadata, (void*)shot_ext, sizeof(struct camera2_shot_ext));
+ void *shot = shot_ext;
+ if (m_ctlInfo.flash.m_flashCnt < IS_FLASH_STATE_CAPTURE) {
+ shot = m_requestManager->GetInternalShotExtByFrameCnt(
+ shot_ext->shot.ctl.request.frameCount);
+ if (!shot) { // m_isRequestQueueNull reuse current
+ ALOGD("(%s): request_scc: "
+ "m_reprocessingFrameCnt missing, using shot_ext",
+ __FUNCTION__);
+ shot = shot_ext;
+ }
+ }
+ memcpy(&m_jpegMetadata, shot, sizeof(struct camera2_shot_ext));
}
m_streamThreads[1]->SetSignal(SIGNAL_STREAM_DATA_COMING);
}
diff --git a/libcamera2/ExynosCameraHWInterface2.h b/libcamera2/ExynosCameraHWInterface2.h
index a8e3348..927eace 100644
--- a/libcamera2/ExynosCameraHWInterface2.h
+++ b/libcamera2/ExynosCameraHWInterface2.h
@@ -283,7 +283,7 @@ public:
uint8_t GetOutputStream(int index);
camera2_shot_ext * GetInternalShotExtByFrameCnt(int frameCnt);
camera2_shot_ext * GetInternalShotExt(int index);
- int FindFrameCnt(struct camera2_shot_ext * shot_ext);
+ int FindFrameCnt(struct camera2_shot_ext * shot_ext, bool drain);
bool IsVdisEnable(void);
int FindEntryIndexByFrameCnt(int frameCnt);
void Dump(void);
diff --git a/libgscaler/exynos_gsc_utils.h b/libgscaler/exynos_gsc_utils.h
index 8c0217f..8e5c49d 100644
--- a/libgscaler/exynos_gsc_utils.h
+++ b/libgscaler/exynos_gsc_utils.h
@@ -128,6 +128,7 @@ struct GSC_HANDLE {
void *op_mutex;
void *obj_mutex[NUM_OF_GSC_HW];
void *cur_obj_mutex;
+ bool destroy_cur_obj_mutex;
bool flag_local_path;
bool flag_exclusive_open;
struct media_device *media0;
diff --git a/libgscaler/exynos_gscaler.c b/libgscaler/exynos_gscaler.c
index 360812b..0e7bb77 100644
--- a/libgscaler/exynos_gscaler.c
+++ b/libgscaler/exynos_gscaler.c
@@ -561,9 +561,14 @@ bool m_exynos_gsc_find_and_trylock_and_create(
continue;
}
- if (gsc_handle->cur_obj_mutex)
+ /* Trade temporary object for one in the pool */
+ if (gsc_handle->cur_obj_mutex) {
exynos_mutex_unlock(gsc_handle->cur_obj_mutex);
+ if (gsc_handle->destroy_cur_obj_mutex)
+ exynos_mutex_destroy(gsc_handle->cur_obj_mutex);
+ }
+ gsc_handle->destroy_cur_obj_mutex = false;
gsc_handle->cur_obj_mutex = gsc_handle->obj_mutex[i];
flag_find_new_gsc = true;
@@ -729,6 +734,7 @@ void *exynos_gsc_create(
gsc_handle->obj_mutex[i] = NULL;
gsc_handle->cur_obj_mutex = NULL;
+ gsc_handle->destroy_cur_obj_mutex = false;
gsc_handle->flag_local_path = false;
gsc_handle->flag_exclusive_open = false;
@@ -813,6 +819,7 @@ void *exynos_gsc_reserve(int dev_num)
gsc_handle->gsc_fd = -1;
gsc_handle->op_mutex = NULL;
gsc_handle->cur_obj_mutex = NULL;
+ gsc_handle->destroy_cur_obj_mutex = true;
sprintf(mutex_name, "%sObject%d", LOG_TAG, dev_num);
gsc_handle->cur_obj_mutex = exynos_mutex_create(EXYNOS_MUTEX_TYPE_SHARED, mutex_name);
@@ -908,6 +915,7 @@ void *exynos_gsc_create_exclusive(
gsc_handle->obj_mutex[i] = NULL;
gsc_handle->cur_obj_mutex = NULL;
+ gsc_handle->destroy_cur_obj_mutex = false;
gsc_handle->flag_local_path = false;
gsc_handle->flag_exclusive_open = true;
@@ -928,6 +936,7 @@ void *exynos_gsc_create_exclusive(
ALOGE("%s::exynos_mutex_create(%s) fail", __func__, mutex_name);
goto err;
}
+ gsc_handle->destroy_cur_obj_mutex = true;
do {
if (exynos_mutex_trylock(gsc_handle->cur_obj_mutex) == true) {
@@ -965,8 +974,11 @@ err:
if (gsc_handle) {
m_exynos_gsc_destroy(gsc_handle);
- if (gsc_handle->cur_obj_mutex)
+ if (gsc_handle->cur_obj_mutex) {
exynos_mutex_unlock(gsc_handle->cur_obj_mutex);
+ if (gsc_handle->destroy_cur_obj_mutex)
+ exynos_mutex_destroy(gsc_handle->cur_obj_mutex);
+ }
for (i = 0; i < NUM_OF_GSC_HW; i++) {
if ((gsc_handle->obj_mutex[i] != NULL) &&
@@ -1023,6 +1035,9 @@ void exynos_gsc_destroy(
}
}
+ if (gsc_handle->destroy_cur_obj_mutex)
+ exynos_mutex_destroy(gsc_handle->cur_obj_mutex);
+
exynos_mutex_unlock(gsc_handle->op_mutex);
if (exynos_mutex_destroy(gsc_handle->op_mutex) == false)