diff options
-rw-r--r-- | exynos_omx/codecs/exynos_codecs/video/exynos5/mfc_v4l2/dec/src/ExynosVideoDecoder.c | 4 | ||||
-rw-r--r-- | gralloc/gralloc.cpp | 10 | ||||
-rw-r--r-- | gralloc/mapper.cpp | 102 | ||||
-rw-r--r-- | libcamera2/ExynosCameraHWInterface2.cpp | 58 | ||||
-rw-r--r-- | libcamera2/ExynosCameraHWInterface2.h | 2 | ||||
-rw-r--r-- | libgscaler/exynos_gsc_utils.h | 1 | ||||
-rw-r--r-- | libgscaler/exynos_gscaler.c | 19 |
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 ¤tEntry->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) |