| /* |
| * Copyright 2008, The Android Open Source Project |
| * Copyright 2013, Samsung Electronics Co. LTD |
| * |
| * 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. |
| */ |
| |
| /*! |
| * \file SecCameraHardware.cpp |
| * \brief source file for Android Camera Ext HAL |
| * \author teahyung kim (tkon.kim@samsung.com) |
| * \date 2013/04/30 |
| * |
| */ |
| |
| #ifndef ANDROID_HARDWARE_SECCAMERAHARDWARE_CPP |
| #define ANDROID_HARDWARE_SECCAMERAHARDWARE_CPP |
| |
| #define LOG_NDEBUG 0 |
| #define LOG_TAG "SecCameraHardware" |
| |
| #include "SecCameraHardware.h" |
| |
| #define CLEAR(x) memset(&(x), 0, sizeof(x)) |
| |
| #define CHECK_ERR(x, log) if (CC_UNLIKELY(x < 0)) { \ |
| ALOGE log; \ |
| return false; \ |
| } |
| |
| #define CHECK_ERR_N(x, log) if (CC_UNLIKELY(x < 0)) { \ |
| ALOGE log; \ |
| return x; \ |
| } |
| |
| #define CHECK_ERR_GOTO(out, x, log) if (CC_UNLIKELY(x < 0)) { \ |
| ALOGE log; \ |
| goto out; \ |
| } |
| |
| #define FLITE0_DEV_PATH "/dev/video100" |
| #define FLITE1_DEV_PATH "/dev/video101" |
| |
| #define MAX_THUMBNAIL_SIZE (60000) |
| |
| #define EXYNOS_MEM_DEVICE_DEV_NAME "/dev/exynos-mem" |
| |
| /* for MC */ |
| #define BACK_SENSOR_ENTITY_A_NM "S5K4ECGX 5-0056" |
| #define BACK_SENSOR_ENTITY_B_NM "S5K4ECGX 4-0056" |
| #define PFX_MIPI_CSIS_SUBDEV_ENTITY_NM "s5p-mipi-csis" |
| #define PFX_FLITE_SUBDEV_ENTITY_NM "flite-subdev" |
| #define PFX_FLITE_VIDEODEV_ENTITY_NM "exynos-fimc-lite" |
| #define MEDIA_DEV_EXT_PATH "/dev/media2" |
| #define PSFX_ENTITY_NUM_A 0 |
| #define PSFX_ENTITY_NUM_B 1 |
| |
| namespace android { |
| |
| struct record_heap { |
| uint32_t type; // make sure that this is 4 byte. |
| phyaddr_t y; |
| phyaddr_t cbcr; |
| uint32_t buf_index; |
| uint32_t reserved; |
| }; |
| |
| gralloc_module_t const* SecCameraHardware::mGrallocHal; |
| |
| SecCameraHardware::SecCameraHardware(int cameraId, camera_device_t *dev) |
| : ISecCameraHardware(cameraId, dev) |
| { |
| if (cameraId == CAMERA_FACING_BACK) |
| mFliteFormat = CAM_PIXEL_FORMAT_YUV422I; |
| else |
| mFliteFormat = CAM_PIXEL_FORMAT_YUV422I; |
| |
| mPreviewFormat = CAM_PIXEL_FORMAT_YUV420SP; |
| /* set suitably */ |
| mRecordingFormat = CAM_PIXEL_FORMAT_YUV420; |
| mPictureFormat = CAM_PIXEL_FORMAT_JPEG; |
| |
| mFactoryTestNum = 0; |
| mBFactoryStopSmartThread = 0; |
| |
| mZoomValue = 10; |
| mFimc1CSC = NULL; |
| mFimc2CSC = NULL; |
| |
| #if IS_FW_DEBUG |
| m_mem_fd = -1; |
| #endif |
| |
| CLEAR(mWindowBuffer); |
| |
| if (!mGrallocHal) { |
| int ret = 0; |
| ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **)&mGrallocHal); |
| if (CC_UNLIKELY(ret)) |
| ALOGE("SecCameraHardware: error, fail on loading gralloc HAL(0x%X)", (uint32_t)mGrallocHal); |
| } |
| |
| createInstance(cameraId); |
| } |
| |
| SecCameraHardware::~SecCameraHardware() |
| { |
| } |
| |
| SecCameraHardware::FLiteV4l2::FLiteV4l2() |
| { |
| mCameraFd = -1; |
| mBufferCount = 0; |
| mIsInternalISP = 0; |
| mStreamOn = false; |
| mCmdStop = 0; |
| mFastCapture = false; |
| mFactoryTestNum_fimc = 0; |
| #ifdef APPLY_ESD |
| mI2CErr = false; |
| #endif |
| } |
| |
| SecCameraHardware::FLiteV4l2::~FLiteV4l2() |
| { |
| } |
| |
| /* HACK */ |
| #define SENSOR_SCENARIO_MASK 0xF0000000 |
| #define SENSOR_SCENARIO_SHIFT 28 |
| #define SENSOR_MODULE_MASK 0x0FFFFFFF |
| #define SENSOR_MODULE_SHIFT 0 |
| |
| int SecCameraHardware::FLiteV4l2::init(const char *devPath, const int cameraId) |
| { |
| int err; |
| |
| mCameraFd = open(devPath, O_RDWR); |
| mCameraId = cameraId; |
| CHECK_ERR_N(mCameraFd, ("FLiteV4l2 init: error %d, open %s (%d - %s)", mCameraFd, devPath, errno, strerror(errno))); |
| ALOGV("FLiteV4l2 init: %s, fd(%d)", devPath, mCameraFd); |
| |
| #if defined(USE_VIDIOC_QUERY_CAP) |
| /* fimc_v4l2_querycap */ |
| struct v4l2_capability cap; |
| CLEAR(cap); |
| err = ioctl(mCameraFd, VIDIOC_QUERYCAP, &cap); |
| CHECK_ERR_N(err, ("FLiteV4l2 init: error %d, VIDIOC_QUERYCAP", err)); |
| |
| if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE)) { |
| ALOGE("FLiteV4l2 init: error, no capture devices"); |
| return -1; |
| } |
| #endif |
| |
| /* fimc_v4l2_enuminput */ |
| struct v4l2_input input; |
| CLEAR(input); |
| /* input.index = cameraId; */ |
| input.index = 0; |
| |
| #if VENDOR_FEATURE |
| err = ioctl(mCameraFd, VIDIOC_ENUMINPUT, &input); |
| CHECK_ERR_N(err, ("FLiteV4l2 init: error %d, VIDIOC_ENUMINPUT", err)); |
| ALOGV("FLiteV4l2 init: camera[%d] %s", input.index, input.name); |
| |
| mIsInternalISP = !strncmp((const char*)input.name, "ISP Camera", 10); |
| #endif |
| |
| /* fimc_v4l2_s_input */ |
| input.index = (2 << SENSOR_SCENARIO_SHIFT) | 57; |
| err = ioctl(mCameraFd, VIDIOC_S_INPUT, &input); |
| CHECK_ERR_N(err, ("FLiteV4l2 init: error %d, VIDIOC_S_INPUT", err)); |
| |
| #ifdef FAKE_SENSOR |
| fakeIndex = 0; |
| fakeByteData = 0; |
| #endif |
| return 0; |
| } |
| |
| void SecCameraHardware::FLiteV4l2::deinit() |
| { |
| if (mCameraFd >= 0) { |
| close(mCameraFd); |
| mCameraFd = -1; |
| } |
| mBufferCount = 0; |
| mFactoryTestNum_fimc = 0; |
| ALOGV("FLiteV4l2 deinit EX"); |
| } |
| |
| void SecCameraHardware::FLiteV4l2::getSensorSize(int frm_ratio, uint32_t *width, uint32_t *height) |
| { |
| switch (frm_ratio) { |
| case CAM_FRMRATIO_QCIF: |
| *width = 1232; |
| *height = 1008; |
| break; |
| case CAM_FRMRATIO_VGA: |
| *width = 1392; /* 1280 */; |
| *height = 1044; /* 960 */; |
| break; |
| case CAM_FRMRATIO_SQUARE: |
| *width = 1392; |
| *height = 1392; |
| break; |
| case CAM_FRMRATIO_D1: |
| *width = 1392; /* 720 */; |
| *height = 928; /* 480 */; |
| break; |
| case CAM_FRMRATIO_HD: |
| *width = 1344; /* 1280 */; |
| *height = 756; /* 720 */; |
| break; |
| default: |
| ALOGW("nativeGetSensorSize: invalid frame ratio %d", frm_ratio); |
| *width = 1392; /* 1280 */; |
| *height = 1044; /* 960 */; |
| break; |
| } |
| |
| } |
| |
| int SecCameraHardware::FLiteV4l2::startPreview(image_rect_type *fliteSize, |
| cam_pixel_format format, int numBufs, int fps, bool movieMode, node_info_t *mFliteNode) |
| { |
| /* fimc_v4l2_enum_fmt */ |
| int err; |
| bool found = false; |
| |
| #if defined(USE_VIDIOC_ENUM_FORMAT) |
| struct v4l2_fmtdesc fmtdesc; |
| CLEAR(fmtdesc); |
| fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| fmtdesc.index = 0; |
| |
| while ((err = ioctl(mCameraFd, VIDIOC_ENUM_FMT, &fmtdesc)) == 0) { |
| if (fmtdesc.pixelformat == (uint32_t)format) { |
| ALOGV("FLiteV4l2 start: %s", fmtdesc.description); |
| found = true; |
| break; |
| } |
| fmtdesc.index++; |
| } |
| if (!found) { |
| ALOGE("FLiteV4l2 start: error, unsupported pixel format (%c%c%c%c)" |
| " fmtdesc.pixelformat = %d, %s, err=%d", format, format >> 8, format >> 16, format >> 24, |
| fmtdesc.pixelformat, fmtdesc.description, err); |
| return -1; |
| } |
| #endif |
| |
| #ifdef USE_CAPTURE_MODE |
| /* |
| capture_mode = oprmode |
| oprmode = 0 (preview) |
| oprmode = 1 (single capture) |
| oprmode = 2 (HDR capture) |
| */ |
| err = sctrl(CAM_CID_CAPTURE_MODE, false); |
| if (err < 0) |
| ALOGE("ERROR(%s): mFlite.sctrl(%d) CAM_CID_CAPTURE_MODE failed", __FUNCTION__, err); |
| #endif |
| |
| v4l2_field field; |
| if (movieMode) |
| field = (enum v4l2_field)IS_MODE_PREVIEW_VIDEO; |
| else |
| field = (enum v4l2_field)IS_MODE_PREVIEW_STILL; |
| |
| /* fimc_v4l2_s_fmt */ |
| struct v4l2_format v4l2_fmt; |
| CLEAR(v4l2_fmt); |
| if (mIsInternalISP) { |
| v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| v4l2_fmt.fmt.pix.pixelformat = format; |
| v4l2_fmt.fmt.pix.field = field; |
| |
| getSensorSize(fliteSize->width * 10 / fliteSize->height, |
| &(v4l2_fmt.fmt.pix.width), &(v4l2_fmt.fmt.pix.height)); |
| ALOGD("FIMC IS FMT width:%d, height:%d", v4l2_fmt.fmt.pix.width, v4l2_fmt.fmt.pix.height); |
| |
| err = ioctl(mCameraFd, VIDIOC_S_FMT, &v4l2_fmt); |
| CHECK_ERR_N(err, ("FLiteV4l2 startPreview: error %d, VIDIOC_S_FMT", err)); |
| } else { |
| v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| v4l2_fmt.fmt.pix_mp.width = fliteSize->width; |
| v4l2_fmt.fmt.pix_mp.height = fliteSize->height; |
| v4l2_fmt.fmt.pix_mp.pixelformat = format; |
| v4l2_fmt.fmt.pix_mp.field = field; |
| err = ioctl(mCameraFd, VIDIOC_S_FMT, &v4l2_fmt); |
| CHECK_ERR_N(err, ("FLiteV4l2 start: error %d, VIDIOC_S_FMT", err)); |
| } |
| |
| #ifdef CACHEABLE |
| sctrl(V4L2_CID_CACHEABLE, 1); |
| #endif |
| /* setting fps */ |
| ALOGV("DEBUG(%s): FLiteV4l2 setting fps: %d", __FUNCTION__, fps); |
| #if 0 |
| err = sctrl(V4L2_CID_CAM_FRAME_RATE, fps); |
| #else |
| struct v4l2_streamparm streamParam; |
| streamParam.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| streamParam.parm.capture.timeperframe.numerator = 1; |
| streamParam.parm.capture.timeperframe.denominator = fps; |
| ALOGI("INFO(%s[%d]:set framerate (denominator=%d)", __FUNCTION__, __LINE__, fps); |
| err = sparm(&streamParam); |
| #endif |
| CHECK_ERR_N(err, ("ERR(%s): sctrl V4L2_CID_CAM_FRAME_RATE(%d) value(%d)", __FUNCTION__, err, fps)); |
| |
| /* sctrl(V4L2_CID_EMBEDDEDDATA_ENABLE, 0); */ |
| |
| /* fimc_v4l2_reqbufs */ |
| struct v4l2_requestbuffers req; |
| CLEAR(req); |
| req.count = numBufs; |
| req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| #ifdef USE_USERPTR |
| req.memory = V4L2_MEMORY_USERPTR; |
| #else |
| req.memory = V4L2_MEMORY_MMAP; |
| #endif |
| err = ioctl(mCameraFd, VIDIOC_REQBUFS, &req); |
| CHECK_ERR_N(err, ("FLiteV4l2 start: error %d, VIDIOC_REQBUFS", err)); |
| |
| mBufferCount = (int)req.count; |
| |
| if (mIsInternalISP) |
| sctrl(V4L2_CID_IS_S_SCENARIO_MODE, field); |
| |
| /* setting mFliteNode for Q/DQ */ |
| mFliteNode->width = v4l2_fmt.fmt.pix.width; |
| mFliteNode->height = v4l2_fmt.fmt.pix.height; |
| mFliteNode->format = v4l2_fmt.fmt.pix.pixelformat; |
| mFliteNode->planes = NUM_FLITE_BUF_PLANE + SPARE_PLANE; |
| mFliteNode->memory = req.memory; |
| mFliteNode->type = req.type; |
| mFliteNode->buffers= numBufs; |
| |
| return 0; |
| } |
| |
| int SecCameraHardware::FLiteV4l2::startCapture(image_rect_type *img, |
| cam_pixel_format format, int numBufs, int capKind) |
| { |
| /* fimc_v4l2_enum_fmt */ |
| int err; |
| bool found = false; |
| |
| #if VENDOR_FEATURE |
| /* Notify mode that is postview or main image. |
| This code added temporarily for resolution factory test just before PVR. |
| Please fix me using VIDIOC_ENUM_FMT. */ |
| if (mCameraId == CAMERA_FACING_BACK) { |
| struct v4l2_control ctrl; |
| CLEAR(ctrl); |
| if (!mIsInternalISP) { |
| ctrl.id = V4L2_CID_START_CAPTURE_KIND; |
| ctrl.value = capKind; |
| } |
| err = ioctl(mCameraFd, VIDIOC_S_CTRL, &ctrl); |
| CHECK_ERR_N(err, ("FimcV4l2 startCapture: error %d, id %#x value %d", err, ctrl.id, ctrl.value)); |
| } |
| #endif |
| |
| #if defined(USE_VIDIOC_ENUM_FORMAT) |
| struct v4l2_fmtdesc fmtdesc; |
| CLEAR(fmtdesc); |
| fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| fmtdesc.index = 0; |
| |
| while ((err = ioctl(mCameraFd, VIDIOC_ENUM_FMT, &fmtdesc)) == 0) { |
| if (fmtdesc.pixelformat == (uint32_t)format) { |
| ALOGV("FLiteV4l2 start: %s", fmtdesc.description); |
| found = true; |
| break; |
| } |
| |
| fmtdesc.index++; |
| } |
| |
| if (!found) { |
| ALOGE("FLiteV4l2 start: error, unsupported pixel format (%c%c%c%c)" |
| " fmtdesc.pixelformat = %d, %s, err=%d", format, format >> 8, format >> 16, format >> 24, |
| fmtdesc.pixelformat, fmtdesc.description, err); |
| return -1; |
| } |
| #endif |
| |
| /* fimc_v4l2_s_fmt */ |
| struct v4l2_format v4l2_fmt; |
| CLEAR(v4l2_fmt); |
| |
| #ifdef NOTDEFINED |
| if (mIsInternalISP) { |
| v4l2_fmt.type = V4L2_BUF_TYPE_PRIVATE; |
| v4l2_fmt.fmt.pix.pixelformat = format; |
| v4l2_fmt.fmt.pix.field = (enum v4l2_field)IS_MODE_CAPTURE_STILL; |
| |
| ALOGV("requested capture size %dx%d", img->width, img->height); |
| getSensorSize(img->width*10/img->height, |
| &(v4l2_fmt.fmt.pix.width), &(v4l2_fmt.fmt.pix.height)); |
| ALOGD("FIMC IS FMT width:%d, height:%d", v4l2_fmt.fmt.pix.width, v4l2_fmt.fmt.pix.height); |
| |
| err = ioctl(mCameraFd, VIDIOC_S_FMT, &v4l2_fmt); |
| CHECK_ERR_N(err, ("FLiteV4l2 startCapture: error %d, VIDIOC_S_FMT", err)); |
| } |
| #endif |
| |
| #ifdef USE_CAPTURE_MODE |
| /* |
| capture_mode = oprmode |
| oprmode = 0 (preview) |
| oprmode = 1 (single capture) |
| oprmode = 2 (HDR capture) |
| */ |
| err = sctrl(CAM_CID_CAPTURE_MODE, true); |
| CHECK_ERR_N(err, ("ERR(%s): sctrl V4L2_CID_CAMERA_CAPTURE(%d) enable failed", __FUNCTION__, err)); |
| #endif |
| |
| ALOGV("DEBUG(%s): requested capture size %dx%d %d", __FUNCTION__, img->width, img->height, format); |
| |
| if (!mIsInternalISP) { |
| v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| v4l2_fmt.fmt.pix_mp.width = img->width; |
| v4l2_fmt.fmt.pix_mp.height = img->height; |
| v4l2_fmt.fmt.pix_mp.pixelformat = format; |
| |
| err = ioctl(mCameraFd, VIDIOC_S_FMT, &v4l2_fmt); |
| CHECK_ERR_N(err, ("FLiteV4l2 start: error %d, VIDIOC_S_FMT", err)); |
| } |
| |
| if (mIsInternalISP) |
| sctrl(V4L2_CID_IS_S_SCENARIO_MODE, IS_MODE_CAPTURE_STILL); |
| |
| /* fimc_v4l2_reqbufs */ |
| struct v4l2_requestbuffers req; |
| CLEAR(req); |
| req.count = SKIP_CAPTURE_CNT; |
| req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| #ifdef USE_USERPTR |
| req.memory = V4L2_MEMORY_USERPTR; |
| #else |
| req.memory = V4L2_MEMORY_MMAP; |
| #endif |
| |
| err = ioctl(mCameraFd, VIDIOC_REQBUFS, &req); |
| CHECK_ERR_N(err, ("FLiteV4l2 start: error %d, VIDIOC_REQBUFS", err)); |
| |
| mBufferCount = (int)req.count; |
| |
| return 0; |
| } |
| |
| int SecCameraHardware::FLiteV4l2::startRecord(image_rect_type *img, image_rect_type *videoSize, |
| cam_pixel_format format, int numBufs) |
| { |
| /* fimc_v4l2_enum_fmt */ |
| int err; |
| bool found = false; |
| struct v4l2_fmtdesc fmtdesc; |
| CLEAR(fmtdesc); |
| fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| fmtdesc.index = 0; |
| |
| while ((err = ioctl(mCameraFd, VIDIOC_ENUM_FMT, &fmtdesc)) == 0) { |
| if (fmtdesc.pixelformat == (uint32_t)format) { |
| ALOGV("FLiteV4l2 start: %s", fmtdesc.description); |
| found = true; |
| break; |
| } |
| fmtdesc.index++; |
| } |
| |
| if (!found) { |
| ALOGE("FLiteV4l2 start: error, unsupported pixel format (%c%c%c%c)" |
| " fmtdesc.pixelformat = %d, %s, err=%d", format, format >> 8, format >> 16, format >> 24, |
| fmtdesc.pixelformat, fmtdesc.description, err); |
| return -1; |
| } |
| |
| /* fimc_v4l2_s_fmt */ |
| struct v4l2_format v4l2_fmt; |
| CLEAR(v4l2_fmt); |
| |
| if (mIsInternalISP) { |
| v4l2_fmt.type = V4L2_BUF_TYPE_PRIVATE; |
| v4l2_fmt.fmt.pix.pixelformat = format; |
| v4l2_fmt.fmt.pix.field = (enum v4l2_field)IS_MODE_PREVIEW_VIDEO; |
| |
| getSensorSize(videoSize->width*10/videoSize->height, |
| &(v4l2_fmt.fmt.pix.width), &(v4l2_fmt.fmt.pix.height)); |
| ALOGD("FIMC IS FMT width:%d, height:%d", v4l2_fmt.fmt.pix.width, v4l2_fmt.fmt.pix.height); |
| |
| err = ioctl(mCameraFd, VIDIOC_S_FMT, &v4l2_fmt); |
| CHECK_ERR_N(err, ("FLiteV4l2 startCapture: error %d, VIDIOC_S_FMT", err)); |
| } |
| |
| v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| v4l2_fmt.fmt.pix.width = videoSize->width; |
| v4l2_fmt.fmt.pix.height = videoSize->height; |
| v4l2_fmt.fmt.pix.pixelformat = format; |
| v4l2_fmt.fmt.pix.priv = V4L2_PIX_FMT_MODE_CAPTURE; |
| |
| err = ioctl(mCameraFd, VIDIOC_S_FMT, &v4l2_fmt); |
| CHECK_ERR_N(err, ("FLiteV4l2 start: error %d, VIDIOC_S_FMT", err)); |
| |
| if (!mIsInternalISP) { |
| v4l2_fmt.type = V4L2_BUF_TYPE_PRIVATE; |
| v4l2_fmt.fmt.pix.width = videoSize->width; |
| v4l2_fmt.fmt.pix.height = videoSize->height; |
| v4l2_fmt.fmt.pix.pixelformat = format; |
| v4l2_fmt.fmt.pix.field = (enum v4l2_field)IS_MODE_PREVIEW_STILL; |
| |
| ALOGD("Sensor FMT %dx%d", v4l2_fmt.fmt.pix.width, v4l2_fmt.fmt.pix.height); |
| |
| err = ioctl(mCameraFd, VIDIOC_S_FMT, &v4l2_fmt); |
| CHECK_ERR_N(err, ("FLiteV4l2 start: error %d, VIDIOC_S_FMT", err)); |
| } |
| |
| if (mIsInternalISP) |
| sctrl(V4L2_CID_IS_S_SCENARIO_MODE, IS_MODE_PREVIEW_VIDEO); |
| |
| /* fimc_v4l2_reqbufs */ |
| struct v4l2_requestbuffers req; |
| CLEAR(req); |
| req.count = numBufs; |
| req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| #ifdef USE_USERPTR |
| req.memory = V4L2_MEMORY_USERPTR; |
| #else |
| req.memory = V4L2_MEMORY_MMAP; |
| #endif |
| |
| err = ioctl(mCameraFd, VIDIOC_REQBUFS, &req); |
| CHECK_ERR_N(err, ("FLiteV4l2 start: error %d, VIDIOC_REQBUFS", err)); |
| |
| mBufferCount = (int)req.count; |
| |
| return 0; |
| } |
| |
| int SecCameraHardware::FLiteV4l2::reqBufZero(node_info_t *mFliteNode) |
| { |
| int err; |
| /* fimc_v4l2_reqbufs */ |
| struct v4l2_requestbuffers req; |
| CLEAR(req); |
| req.count = 0; |
| req.type = mFliteNode->type; |
| req.memory = mFliteNode->memory; |
| ALOGV("DEBUG(%s): type[%d] memory[%d]", __FUNCTION__, req.type, req.memory); |
| err = ioctl(mCameraFd, VIDIOC_REQBUFS, &req); |
| CHECK_ERR_N(err, ("FLiteV4l2 reqBufZero: error %d", err)); |
| return 1; |
| } |
| |
| int SecCameraHardware::FLiteV4l2::querybuf2(unsigned int index, int planeCnt, ExynosBuffer *buf) |
| { |
| struct v4l2_buffer v4l2_buf; |
| struct v4l2_plane planes[VIDEO_MAX_PLANES]; |
| int err; |
| |
| CLEAR(v4l2_buf); |
| CLEAR(planes); |
| |
| /* loop for buffer count */ |
| v4l2_buf.index = index; |
| v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| v4l2_buf.memory = V4L2_MEMORY_MMAP; |
| v4l2_buf.length = planeCnt; |
| v4l2_buf.m.planes = planes; |
| |
| err = ioctl(mCameraFd , VIDIOC_QUERYBUF, &v4l2_buf); |
| if (err < 0) { |
| ALOGE("ERR(%s)(%d): error %d, index %d", __func__, __LINE__, err, index); |
| return 0; |
| } |
| |
| /* loop for planes */ |
| for (int i = 0; i < planeCnt; i++) { |
| unsigned int length = v4l2_buf.m.planes[i].length; |
| unsigned int offset = v4l2_buf.m.planes[i].m.mem_offset; |
| char *vAdr = (char *) mmap(0, |
| v4l2_buf.m.planes[i].length, |
| PROT_READ | PROT_WRITE, MAP_SHARED, |
| mCameraFd, offset); |
| ALOGV("DEBUG(%s): [%d][%d] length %d, offset %d vadr %p", __FUNCTION__, index, i, length, offset, vAdr); |
| if (vAdr == NULL) { |
| ALOGE("ERR(%s)(%d): [%d][%d] vAdr is %p", __func__, __LINE__, index, i, vAdr); |
| return 0; |
| } else { |
| buf->virt.extP[i] = vAdr; |
| buf->size.extS[i] = length; |
| memset(buf->virt.extP[i], 0x0, buf->size.extS[i]); |
| } |
| } |
| |
| return 1; |
| } |
| |
| int SecCameraHardware::FLiteV4l2::expBuf(unsigned int index, int planeCnt, ExynosBuffer *buf) |
| { |
| struct v4l2_exportbuffer v4l2_expbuf; |
| int err; |
| |
| for (int i = 0; i < planeCnt; i++) { |
| memset(&v4l2_expbuf, 0, sizeof(v4l2_expbuf)); |
| v4l2_expbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| v4l2_expbuf.index = index; |
| err = ioctl(mCameraFd, VIDIOC_EXPBUF, &v4l2_expbuf); |
| if (err < 0) { |
| ALOGE("ERR(%s)(%d): [%d][%d] failed %d", __func__, __LINE__, index, i, err); |
| goto EXP_ERR; |
| } else { |
| ALOGV("DEBUG(%s): [%d][%d] fd %d", __FUNCTION__, index, i, v4l2_expbuf.fd); |
| buf->fd.extFd[i] = v4l2_expbuf.fd; |
| } |
| } |
| return 1; |
| |
| EXP_ERR: |
| for (int i = 0; i < planeCnt; i++) { |
| if (buf->fd.extFd[i] > 0) |
| ion_free(buf->fd.extFd[i]); |
| } |
| return 0; |
| } |
| |
| |
| sp<MemoryHeapBase> SecCameraHardware::FLiteV4l2::querybuf(uint32_t *frmsize) |
| { |
| struct v4l2_buffer v4l2_buf; |
| v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| v4l2_buf.memory = V4L2_MEMORY_MMAP; |
| v4l2_buf.length = 0; |
| |
| for (int i = 0; i < mBufferCount; i++) { |
| int err; |
| v4l2_buf.index = i; |
| err = ioctl(mCameraFd , VIDIOC_QUERYBUF, &v4l2_buf); |
| if (err < 0) { |
| ALOGE("FLiteV4l2 querybufs: error %d, index %d", err, i); |
| *frmsize = 0; |
| return NULL; |
| } |
| } |
| |
| *frmsize = v4l2_buf.length; |
| |
| return mBufferCount == 1 ? |
| new MemoryHeapBase(mCameraFd, v4l2_buf.length, v4l2_buf.m.offset) : NULL; |
| } |
| |
| int SecCameraHardware::FLiteV4l2::qbuf(uint32_t index) |
| { |
| struct v4l2_buffer v4l2_buf; |
| CLEAR(v4l2_buf); |
| v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| v4l2_buf.memory = V4L2_MEMORY_MMAP; |
| v4l2_buf.index = index; |
| |
| int err = ioctl(mCameraFd, VIDIOC_QBUF, &v4l2_buf); |
| CHECK_ERR_N(err, ("FLiteV4l2 qbuf: error %d", err)); |
| |
| return 0; |
| } |
| |
| int SecCameraHardware::FLiteV4l2::dqbuf() |
| { |
| struct v4l2_buffer v4l2_buf; |
| v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| v4l2_buf.memory = V4L2_MEMORY_MMAP; |
| |
| int err = ioctl(mCameraFd, VIDIOC_DQBUF, &v4l2_buf); |
| CHECK_ERR_N(err, ("FLiteV4l2 dqbuf: error %d", err)); |
| |
| if (v4l2_buf.index > (uint32_t)mBufferCount) { |
| ALOGE("FLiteV4l2 dqbuf: error %d, invalid index", v4l2_buf.index); |
| return -1; |
| } |
| |
| return v4l2_buf.index; |
| } |
| |
| int SecCameraHardware::FLiteV4l2::dqbuf(uint32_t *index) |
| { |
| struct v4l2_buffer v4l2_buf; |
| v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| v4l2_buf.memory = V4L2_MEMORY_MMAP; |
| |
| int err = ioctl(mCameraFd, VIDIOC_DQBUF, &v4l2_buf); |
| if (err >= 0) |
| *index = v4l2_buf.index; |
| |
| return err; |
| } |
| |
| int SecCameraHardware::FLiteV4l2::qbuf2(node_info_t *node, uint32_t index) |
| { |
| struct v4l2_buffer v4l2_buf; |
| struct v4l2_plane planes[VIDEO_MAX_PLANES]; |
| int i; |
| int ret = 0; |
| |
| CLEAR(planes); |
| CLEAR(v4l2_buf); |
| |
| v4l2_buf.m.planes = planes; |
| v4l2_buf.type = node->type; |
| v4l2_buf.memory = node->memory; |
| v4l2_buf.index = index; |
| v4l2_buf.length = node->planes; |
| |
| for(i = 0; i < node->planes; i++){ |
| if (node->memory == V4L2_MEMORY_DMABUF) |
| v4l2_buf.m.planes[i].m.fd = (int)(node->buffer[index].fd.extFd[i]); |
| else if (node->memory == V4L2_MEMORY_USERPTR) { |
| v4l2_buf.m.planes[i].m.userptr = (unsigned long)(node->buffer[index].virt.extP[i]); |
| } else if (node->memory == V4L2_MEMORY_MMAP) { |
| v4l2_buf.m.planes[i].m.userptr = (unsigned long)(node->buffer[index].virt.extP[i]); |
| } else { |
| ALOGE("ERR(%s):invalid node->memory(%d)", __func__, node->memory); |
| return -1; |
| } |
| v4l2_buf.m.planes[i].length = (unsigned long)(node->buffer[index].size.extS[i]); |
| } |
| |
| ret = exynos_v4l2_qbuf(node->fd, &v4l2_buf); |
| if (ret < 0) { |
| ALOGE("ERR(%s):exynos_v4l2_qbuf failed (index:%d)(ret:%d)", __func__, index, ret); |
| return -1; |
| } |
| |
| return ret; |
| } |
| |
| int SecCameraHardware::FLiteV4l2::qbufForCapture(ExynosBuffer *buf, uint32_t index) |
| { |
| struct v4l2_buffer v4l2_buf; |
| struct v4l2_plane planes[VIDEO_MAX_PLANES]; |
| unsigned int i; |
| int ret = 0; |
| |
| CLEAR(planes); |
| CLEAR(v4l2_buf); |
| |
| v4l2_buf.m.planes = planes; |
| v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| #ifdef USE_USERPTR |
| v4l2_buf.memory = V4L2_MEMORY_USERPTR; |
| #else |
| v4l2_buf.memory = V4L2_MEMORY_MMAP; |
| #endif |
| v4l2_buf.index = index; |
| v4l2_buf.length = 2; |
| |
| for(i = 0; i < v4l2_buf.length; i++){ |
| if (v4l2_buf.memory == V4L2_MEMORY_DMABUF) |
| v4l2_buf.m.planes[i].m.fd = (int)(buf->fd.extFd[i]); |
| else if (v4l2_buf.memory == V4L2_MEMORY_USERPTR) { |
| v4l2_buf.m.planes[i].m.userptr = (unsigned long)(buf->virt.extP[i]); |
| } else if (v4l2_buf.memory == V4L2_MEMORY_MMAP) { |
| v4l2_buf.m.planes[i].m.userptr = (unsigned long)(buf->virt.extP[i]); |
| } else { |
| ALOGE("ERR(%s):invalid node->memory(%d)", __func__, v4l2_buf.memory); |
| return -1; |
| } |
| v4l2_buf.m.planes[i].length = (unsigned long)(buf->size.extS[i]); |
| } |
| |
| ret = exynos_v4l2_qbuf(this->getFd(), &v4l2_buf); |
| if (ret < 0) { |
| ALOGE("ERR(%s):exynos_v4l2_qbuf failed (index:%d)(ret:%d)", __func__, index, ret); |
| return -1; |
| } |
| |
| return ret; |
| } |
| |
| |
| int SecCameraHardware::FLiteV4l2::dqbuf2(node_info_t *node) |
| { |
| struct v4l2_buffer v4l2_buf; |
| struct v4l2_plane planes[VIDEO_MAX_PLANES]; |
| int ret; |
| |
| CLEAR(planes); |
| CLEAR(v4l2_buf); |
| |
| v4l2_buf.type = node->type; |
| v4l2_buf.memory = node->memory; |
| v4l2_buf.m.planes = planes; |
| v4l2_buf.length = node->planes; |
| |
| ret = exynos_v4l2_dqbuf(node->fd, &v4l2_buf); |
| if (ret < 0) { |
| if (ret != -EAGAIN) |
| ALOGE("ERR(%s):VIDIOC_DQBUF failed (%d)", __func__, ret); |
| return ret; |
| } |
| |
| if (v4l2_buf.flags & V4L2_BUF_FLAG_ERROR) { |
| ALOGE("ERR(%s):VIDIOC_DQBUF returned with error (%d)", __func__, V4L2_BUF_FLAG_ERROR); |
| return -1; |
| } |
| |
| return v4l2_buf.index; |
| } |
| |
| int SecCameraHardware::FLiteV4l2::dqbufForCapture(ExynosBuffer *buf) |
| { |
| struct v4l2_buffer v4l2_buf; |
| struct v4l2_plane planes[VIDEO_MAX_PLANES]; |
| int ret; |
| |
| CLEAR(planes); |
| CLEAR(v4l2_buf); |
| |
| v4l2_buf.m.planes = planes; |
| v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| #ifdef USE_USERPTR |
| v4l2_buf.memory = V4L2_MEMORY_USERPTR; |
| #else |
| v4l2_buf.memory = V4L2_MEMORY_MMAP; |
| #endif |
| v4l2_buf.length = 1; |
| |
| ret = exynos_v4l2_dqbuf(this->getFd(), &v4l2_buf); |
| if (ret < 0) { |
| if (ret != -EAGAIN) |
| ALOGE("ERR(%s):VIDIOC_DQBUF failed (%d)", __func__, ret); |
| return ret; |
| } |
| |
| if (v4l2_buf.flags & V4L2_BUF_FLAG_ERROR) { |
| ALOGE("ERR(%s):VIDIOC_DQBUF returned with error (%d)", __func__, V4L2_BUF_FLAG_ERROR); |
| return -1; |
| } |
| |
| return v4l2_buf.index; |
| } |
| |
| #ifdef FAKE_SENSOR |
| int SecCameraHardware::FLiteV4l2::fakeQbuf2(node_info_t *node, uint32_t index) |
| { |
| fakeByteData++; |
| fakeByteData = fakeByteData % 0xFF; |
| |
| for (int i = 0; i < node->planes; i++) { |
| memset(node->buffer[index].virt.extP[i], fakeByteData, |
| node->buffer[index].size.extS[i]); |
| |
| } |
| fakeIndex = index; |
| return fakeIndex; |
| } |
| |
| int SecCameraHardware::FLiteV4l2::fakeDqbuf2(node_info_t *node) |
| { |
| return fakeIndex; |
| } |
| #endif |
| |
| |
| int SecCameraHardware::FLiteV4l2::stream(bool on) |
| { |
| ALOGV("DEBUG(%s): stream E", __FUNCTION__); |
| enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| int err = ioctl(mCameraFd, on ? VIDIOC_STREAMON : VIDIOC_STREAMOFF, &type); |
| CHECK_ERR_N(err, ("FLiteV4l2 stream: error %d", err)); |
| |
| err = sctrl(V4L2_CID_IS_S_STREAM, on ? IS_ENABLE_STREAM : IS_DISABLE_STREAM); |
| CHECK_ERR_N(err, ("s_stream: error %d", err)); |
| |
| mStreamOn = on; |
| |
| ALOGV("FLiteV4l2 stream: stream turning %s", on ? "on" : "off"); |
| |
| return 0; |
| } |
| |
| #ifndef FPOLLING |
| int SecCameraHardware::FLiteV4l2::polling(bool bFactoryTest, bool recordingMode) |
| { |
| int err = 0; |
| struct pollfd events; |
| CLEAR(events); |
| events.fd = mCameraFd; |
| events.events = POLLIN | POLLERR; |
| |
| const long timeOut = 5000; |
| if (bFactoryTest) { |
| const int count = 60 * 5; |
| int sec = 1000; |
| for (int j = 0; j < count; j++) { |
| if (mFactoryTestNum_fimc == 0) { |
| return 1; |
| } |
| err = poll(&events, 1, sec); |
| } |
| } else if (recordingMode) { |
| const long sliceTimeOut = 66; |
| |
| for (int i = 0; i < (timeOut / sliceTimeOut); i++) { |
| if (!mStreamOn) |
| return 0; |
| err = poll(&events, 1, sliceTimeOut); |
| if (err > 0) |
| break; |
| } |
| } else { |
| #if 1 /* for test fast capture */ |
| const int count = 40; |
| for (int i = 0; i < count; i++) { |
| err = poll(&events, 1, timeOut / count); |
| if (mFastCapture) { |
| return 0; |
| } |
| } |
| #else |
| err = poll(&events, 1, timeOut); |
| #endif |
| } |
| |
| if (CC_UNLIKELY(err <= 0)) |
| ALOGE("FLiteV4l2 poll: error %d", err); |
| |
| return err; |
| } |
| #endif |
| |
| int SecCameraHardware::FLiteV4l2::notictrl(uint32_t id, int *read_val) |
| { |
| struct v4l2_control ctrl; |
| CLEAR(ctrl); |
| ctrl.id = id; |
| |
| #if VENDOR_FEATURE |
| int err = ioctl(mCameraFd, VIDIOC_NOTI_CTRL, &ctrl); |
| if (err < 0) |
| ALOGD("FLiteV4L2 notictrl: sound interrupt timeout. NO ERROR."); |
| |
| *read_val = ctrl.value; |
| |
| return err; |
| #else |
| return 0; |
| #endif |
| } |
| |
| int SecCameraHardware::FLiteV4l2::gctrl(uint32_t id, int *value) |
| { |
| struct v4l2_control ctrl; |
| CLEAR(ctrl); |
| ctrl.id = id; |
| |
| #ifdef APPLY_ESD |
| if (CC_UNLIKELY(mI2CErr == true)) { |
| ALOGE("gctrl() mI2CErr:true"); |
| *value = 0; |
| return 0; |
| } |
| #endif |
| |
| int err = ioctl(mCameraFd, VIDIOC_G_CTRL, &ctrl); |
| #ifdef APPLY_ESD |
| if (CC_UNLIKELY(err < 0)) { |
| mI2CErr = true; |
| } |
| #endif |
| CHECK_ERR_N(err, ("FLiteV4l2 gctrl: error %d, id %#x", err, id)); |
| *value = ctrl.value; |
| |
| return 0; |
| } |
| |
| int SecCameraHardware::FLiteV4l2::gctrl(uint32_t id, unsigned short *value) |
| { |
| struct v4l2_control ctrl; |
| CLEAR(ctrl); |
| ctrl.id = id; |
| |
| #ifdef APPLY_ESD |
| if (CC_UNLIKELY(mI2CErr == true)) { |
| ALOGE("gctrl() mI2CErr:true"); |
| *value = 0; |
| return 0; |
| } |
| #endif |
| |
| int err = ioctl(mCameraFd, VIDIOC_G_CTRL, &ctrl); |
| #ifdef APPLY_ESD |
| if (CC_UNLIKELY(err < 0)) { |
| mI2CErr = true; |
| } |
| #endif |
| CHECK_ERR_N(err, ("FLiteV4l2 gctrl: error %d, id %#x", err, id)); |
| *value = (unsigned short)ctrl.value; |
| |
| return 0; |
| } |
| |
| int SecCameraHardware::FLiteV4l2::gctrl(uint32_t id, char *value, int size) |
| { |
| struct v4l2_ext_controls ctrls; |
| struct v4l2_ext_control ctrl; |
| |
| CLEAR(ctrls); |
| ctrls.ctrl_class = V4L2_CTRL_CLASS_CAMERA; |
| ctrls.count = 1; |
| ctrls.controls = &ctrl; |
| |
| CLEAR(ctrl); |
| ctrl.id = id; |
| ctrl.string = value; |
| ctrl.size=size; |
| |
| int err = ioctl(mCameraFd, VIDIOC_G_EXT_CTRLS, &ctrls); |
| CHECK_ERR_N(err, ("FLiteV4l2 gctrl: error %d, id %#x", err, id)); |
| |
| return 0; |
| } |
| |
| int SecCameraHardware::FLiteV4l2::sctrl(uint32_t id, int value) |
| { |
| struct v4l2_control ctrl; |
| CLEAR(ctrl); |
| ctrl.id = id; |
| ctrl.value = value; |
| |
| int err = ioctl(mCameraFd, VIDIOC_S_CTRL, &ctrl); |
| CHECK_ERR_N(err, ("FLiteV4l2 sctrl: error %d, id %#x value %d", err, id, value)); |
| |
| return 0; |
| } |
| |
| #ifndef FCJUNG |
| int SecCameraHardware::FLiteV4l2::sctrl(uint32_t id, char *value, int size) |
| { |
| struct v4l2_ext_controls ctrls; |
| struct v4l2_ext_control ctrl; |
| |
| |
| CLEAR(ctrls); |
| ctrls.ctrl_class = V4L2_CTRL_CLASS_CAMERA; |
| ctrls.count = 1; |
| ctrls.controls = &ctrl; |
| |
| CLEAR(ctrl); |
| ctrl.id = id; |
| ctrl.string = value; |
| ctrl.size=size; |
| |
| int err = ioctl(mCameraFd, VIDIOC_S_EXT_CTRLS, &ctrls); |
| CHECK_ERR_N(err, ("FimcV4l2 ext sctrl: error %d, id %#x", err, id)); |
| |
| return 0; |
| } |
| #endif |
| |
| int SecCameraHardware::FLiteV4l2::sparm(struct v4l2_streamparm *stream_parm) |
| { |
| int err = ioctl(mCameraFd, VIDIOC_S_PARM, stream_parm); |
| CHECK_ERR_N(err, ("FLiteV4l2 sparm: error %d, value %d", err, |
| stream_parm->parm.capture.timeperframe.denominator)); |
| |
| return 0; |
| } |
| |
| |
| int SecCameraHardware::FLiteV4l2::getYuvPhyaddr(int index, |
| phyaddr_t *y, |
| phyaddr_t *cbcr) |
| { |
| struct v4l2_control ctrl; |
| int err; |
| |
| if (y) { |
| CLEAR(ctrl); |
| ctrl.id = V4L2_CID_PADDR_Y; |
| ctrl.value = index; |
| |
| err = ioctl(mCameraFd, VIDIOC_S_CTRL, &ctrl); |
| CHECK_ERR_N(err, ("FLiteV4l2 getYuvPhyaddr: error %d, V4L2_CID_PADDR_Y", err)); |
| |
| *y = ctrl.value; |
| } |
| |
| if (cbcr) { |
| CLEAR(ctrl); |
| ctrl.id = V4L2_CID_PADDR_CBCR; |
| ctrl.value = index; |
| |
| err = ioctl(mCameraFd, VIDIOC_S_CTRL, &ctrl); |
| CHECK_ERR_N(err, ("FLiteV4l2 getYuvPhyaddr: error %d, V4L2_CID_PADDR_CBCR", err)); |
| |
| *cbcr = ctrl.value; |
| } |
| return 0; |
| } |
| |
| int SecCameraHardware::FLiteV4l2::getYuvPhyaddr(int index, |
| phyaddr_t *y, |
| phyaddr_t *cb, |
| phyaddr_t *cr) |
| { |
| struct v4l2_control ctrl; |
| int err; |
| |
| if (y) { |
| CLEAR(ctrl); |
| ctrl.id = V4L2_CID_PADDR_Y; |
| ctrl.value = index; |
| |
| err = ioctl(mCameraFd, VIDIOC_S_CTRL, &ctrl); |
| CHECK_ERR_N(err, ("FLiteV4l2 getYuvPhyaddr: error %d, V4L2_CID_PADDR_Y", err)); |
| |
| *y = ctrl.value; |
| } |
| |
| if (cb) { |
| CLEAR(ctrl); |
| ctrl.id = V4L2_CID_PADDR_CB; |
| ctrl.value = index; |
| |
| err = ioctl(mCameraFd, VIDIOC_S_CTRL, &ctrl); |
| CHECK_ERR_N(err, ("FLiteV4l2 getYuvPhyaddr: error %d, V4L2_CID_PADDR_CB", err)); |
| |
| *cb = ctrl.value; |
| } |
| |
| if (cr) { |
| CLEAR(ctrl); |
| ctrl.id = V4L2_CID_PADDR_CR; |
| ctrl.value = index; |
| |
| err = ioctl(mCameraFd, VIDIOC_S_CTRL, &ctrl); |
| CHECK_ERR_N(err, ("FLiteV4l2 getYuvPhyaddr: error %d, V4L2_CID_PADDR_CR", err)); |
| |
| *cr = ctrl.value; |
| } |
| |
| return 0; |
| } |
| |
| #ifndef FCJUNG |
| int SecCameraHardware::FLiteV4l2::setFactoryTestNumFimc(uint32_t mFactoryTestNum) |
| { |
| mFactoryTestNum_fimc = mFactoryTestNum; |
| ALOGV("factory test number in Fimc : %d", mFactoryTestNum_fimc); |
| return 0; |
| } |
| #endif |
| |
| int SecCameraHardware::FLiteV4l2::setFastCaptureFimc(uint32_t IsFastCaptureCalled) |
| { |
| mFastCapture = IsFastCaptureCalled; |
| ALOGD("Set Fast capture in fimc : %d", mFastCapture); |
| return 0; |
| } |
| |
| int SecCameraHardware::FLiteV4l2::reset() |
| { |
| struct v4l2_control ctrl; |
| CLEAR(ctrl); |
| ctrl.id = V4L2_CID_CAMERA_RESET; |
| ctrl.value = 0; |
| |
| int err = ioctl(mCameraFd, VIDIOC_S_CTRL, &ctrl); |
| CHECK_ERR_N(err, ("FLiteV4l2 reset: error %d", err)); |
| |
| return 0; |
| } |
| |
| void SecCameraHardware::FLiteV4l2::forceStop() |
| { |
| mCmdStop = 1; |
| return; |
| } |
| |
| int SecCameraHardware::FLiteV4l2::getFd() |
| { |
| return mCameraFd; |
| } |
| |
| #ifdef ENABLE_MC |
| bool SecCameraHardware::initMC() |
| { |
| int err = -1; |
| unsigned int i; |
| int devNum; |
| char node[30]; |
| |
| struct media_link *links = NULL; |
| |
| mMedia = exynos_media_open(MEDIA_DEV_EXT_PATH); |
| |
| if (mMedia == NULL) { |
| ALOGE("ERR(%s):Cannot open media device (error : %s)", __func__, strerror(errno)); |
| goto err; |
| } else { |
| CLEAR(node); |
| |
| if (mCameraId == CAMERA_FACING_BACK) { |
| /* camera sensor */ |
| strncpy(node, BACK_SENSOR_ENTITY_A_NM, sizeof(node) - 1); |
| ALOGV("DEBUG(%s):node : %s", __func__, node); |
| mSensorEntity = exynos_media_get_entity_by_name(mMedia, node, strlen(node)); |
| ALOGV("DEBUG(%s):mSensorEntity : 0x%p [%s]", __func__, mSensorEntity, mSensorEntity->info.name); |
| CLEAR(node); |
| |
| /* mipi subdev */ |
| snprintf(node, sizeof(node) - 1, "%s.%d", PFX_MIPI_CSIS_SUBDEV_ENTITY_NM, PSFX_ENTITY_NUM_A); |
| ALOGV("DEBUG(%s):node : %s", __func__, node); |
| mMipiEntity = exynos_media_get_entity_by_name(mMedia, node, strlen(node)); |
| ALOGV("DEBUG(%s):mMipiEntity : 0x%p [%s]", __func__, mMipiEntity, mMipiEntity->info.name); |
| CLEAR(node); |
| |
| /* fimc-lite subdev */ |
| snprintf(node, sizeof(node) - 1, "%s.%d", PFX_FLITE_SUBDEV_ENTITY_NM, PSFX_ENTITY_NUM_A); |
| ALOGV("DEBUG(%s):node : %s", __func__, node); |
| mFliteSdEntity = exynos_media_get_entity_by_name(mMedia, node, strlen(node)); |
| ALOGV("DEBUG(%s):mFliteSdEntity : 0x%p [%s]", __func__, mFliteSdEntity, mFliteSdEntity->info.name); |
| CLEAR(node); |
| |
| /* fimc-lite videodev */ |
| snprintf(node, sizeof(node) - 1, "%s.%d", PFX_FLITE_VIDEODEV_ENTITY_NM, PSFX_ENTITY_NUM_A); |
| ALOGV("DEBUG(%s):node : %s", __func__, node); |
| mFliteVdEntity = exynos_media_get_entity_by_name(mMedia, node, strlen(node)); |
| ALOGV("DEBUG(%s):mFliteVdEntity : 0x%p [%s]", __func__, mFliteVdEntity, mFliteVdEntity->info.name); |
| CLEAR(node); |
| |
| ALOGV("DEBUG(%s):sensor_sd : numlink : %d [%s]", __func__, mSensorEntity->num_links, mSensorEntity->info.name); |
| ALOGV("DEBUG(%s):mipi_sd : numlink : %d [%s]", __func__, mMipiEntity->num_links, mMipiEntity->info.name); |
| ALOGV("DEBUG(%s):flite_sd : numlink : %d [%s]", __func__, mFliteSdEntity->num_links, mFliteSdEntity->info.name); |
| ALOGV("DEBUG(%s):flite_vd : numlink : %d [%s]", __func__, mFliteVdEntity->num_links, mFliteVdEntity->info.name); |
| |
| /* sensor subdev to mipi subdev */ |
| links = mSensorEntity->links; |
| if (links == NULL || |
| links->source->entity != mSensorEntity || |
| links->sink->entity != mMipiEntity) { |
| ALOGE("ERR(%s):Cannot make link camera sensor to mipi", __func__); |
| goto err; |
| } |
| |
| if (exynos_media_setup_link(mMedia, links->source, links->sink, MEDIA_LNK_FL_ENABLED) < 0) { |
| ALOGE("ERR(%s):Cannot make setup camera sensor to mipi", __func__); |
| goto err; |
| } |
| ALOGV("DEBUG(%s):[LINK SUCCESS] sensor subdev to mipi subdev", __func__); |
| |
| /* mipi subdev to fimc-lite subdev */ |
| for (i = 0; i < mMipiEntity->num_links; i++) { |
| links = &mMipiEntity->links[i]; |
| ALOGV("DEBUG(%s):i=%d: links->source->entity : %p, mMipiEntity : %p", __func__, i, |
| links->source->entity, mMipiEntity); |
| ALOGV("DEBUG(%s):i=%d: links->sink->entity : %p, mFliteSdEntity : %p", __func__, i, |
| links->sink->entity, mFliteSdEntity); |
| if (links == NULL || |
| links->source->entity != mMipiEntity || |
| links->sink->entity != mFliteSdEntity) { |
| continue; |
| } else if (exynos_media_setup_link(mMedia, links->source, links->sink, MEDIA_LNK_FL_ENABLED) < 0) { |
| ALOGE("ERR(%s):Cannot make setup mipi subdev to fimc-lite subdev", __func__); |
| goto err; |
| } |
| } |
| ALOGV("DEBUG(%s):[LINK SUCCESS] mipi subdev to fimc-lite subdev", __func__); |
| |
| /* fimc-lite subdev TO fimc-lite video dev */ |
| for (i = 0; i < mFliteSdEntity->num_links; i++) { |
| links = &mFliteSdEntity->links[i]; |
| ALOGV("DEBUG(%s):i=%d: links->source->entity : %p, mFliteSdEntity : %p", __func__, i, |
| links->source->entity, mFliteSdEntity); |
| ALOGV("DEBUG(%s):i=%d: links->sink->entity : %p, mFliteVdEntity : %p", __func__, i, |
| links->sink->entity, mFliteVdEntity); |
| if (links == NULL || |
| links->source->entity != mFliteSdEntity || |
| links->sink->entity != mFliteVdEntity) { |
| continue; |
| } else if (exynos_media_setup_link(mMedia, links->source, links->sink, MEDIA_LNK_FL_ENABLED) < 0) { |
| ALOGE("ERR(%s):Cannot make setup fimc-lite subdev to fimc-lite video dev", __func__); |
| goto err; |
| } |
| } |
| ALOGV("DEBUG(%s):[LINK SUCCESS] fimc-lite subdev to fimc-lite video dev", __func__); |
| |
| setAllMCSubdevFormat(mFLiteSize.width, mFLiteSize.height, CAMERA_EXT_PREVIEW); |
| |
| } |
| |
| } |
| |
| return true; |
| err: |
| if (mMedia) |
| exynos_media_close(mMedia); |
| mMedia = NULL; |
| |
| return false; |
| } |
| #endif |
| |
| bool SecCameraHardware::setMCSubdevFormat(struct media_entity *entity, |
| int w, int h, unsigned int pad, |
| int ext_cam_mode) |
| { |
| struct v4l2_subdev_format fmt; |
| struct v4l2_mbus_framefmt format; |
| CLEAR(fmt); |
| CLEAR(format); |
| ALOGV("DEBUG(%s): name %s", __func__, entity->info.name); |
| entity->fd = exynos_subdev_open_devname(entity->info.name, O_RDWR); |
| if (entity->fd < 0) { |
| ALOGE("DEBUG(%s): failed invalid fd : %d", __func__, entity->fd); |
| return false; |
| |
| } else { |
| ALOGD("DEBUG(%s): successed subdev open fd:%d", __func__, entity->fd); |
| |
| format.width = w; |
| format.height = h; |
| |
| switch (ext_cam_mode) { |
| case CAMERA_EXT_PREVIEW: |
| case CAMERA_EXT_CAPTURE_YUV: |
| format.code = V4L2_MBUS_FMT_YUYV8_2X8; |
| break; |
| case CAMERA_EXT_CAPTURE_JPEG: |
| format.code = V4L2_MBUS_FMT_JPEG_1X8; |
| break; |
| default: |
| format.code = V4L2_MBUS_FMT_YUYV8_2X8; |
| break; |
| } |
| |
| fmt.pad = pad; |
| fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; |
| fmt.format = format; |
| |
| if (exynos_subdev_s_fmt(entity->fd, &fmt) < 0) { |
| ALOGE("ERR(%s): subdev set format is failed", __func__); |
| return false; |
| } else { |
| ALOGV("DEBUG(%s): subdev set format is successed", __func__); |
| } |
| } |
| |
| int fd = exynos_subdev_close(entity->fd); |
| if (fd < 0) |
| ALOGE("ERR(%s): failed close fd : %d", __func__, entity->fd); |
| |
| return true; |
| } |
| |
| bool SecCameraHardware::setAllMCSubdevFormat(int w, int h, int ext_cam_mode) |
| { |
| ALOGV("DEBUG(%s): w(%d), h(%d), ext_cam_mode(%d)", __func__, w, h, ext_cam_mode); |
| |
| /* Sensor */ |
| if (setMCSubdevFormat(mSensorEntity, w, h, 0, ext_cam_mode) == false) { |
| ALOGE("ERR(%s): failed m_set_subdev_format mSensorEntity", __func__); |
| return false; |
| } |
| |
| /* MIPI-CSIS subdev set format */ |
| if (setMCSubdevFormat(mMipiEntity, w, h, 0, ext_cam_mode) == false) { |
| ALOGE("ERR(%s): failed m_set_subdev_format mMipiEntity(0)", __func__); |
| return false; |
| } |
| if (setMCSubdevFormat(mMipiEntity, w, h, 1, ext_cam_mode) == false) { |
| ALOGE("ERR(%s): failed m_set_subdev_format mMipiEntity(1)", __func__); |
| return false; |
| } |
| |
| /* FIMC-LITE subdev set format */ |
| if (setMCSubdevFormat(mFliteSdEntity, w, h, 1, ext_cam_mode) == false) { |
| ALOGE("ERR(%s): failed m_set_subdev_format mFliteSdEntity", __func__); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| |
| bool SecCameraHardware::init() |
| { |
| ALOGD("init E"); |
| |
| LOG_PERFORMANCE_START(1); |
| CLEAR(mFliteNode); |
| CSC_METHOD cscMethod = CSC_METHOD_HW; |
| |
| #ifdef ENABLE_MC |
| /* init media controller */ |
| if (initMC() == false) { |
| ALOGE("initMC X: error"); |
| goto fimc_out; |
| } |
| #endif |
| int err; |
| |
| if (mCameraId == CAMERA_FACING_BACK) |
| err = mFlite.init(FLITE0_DEV_PATH, mCameraId); |
| else |
| err = mFlite.init(FLITE1_DEV_PATH, mCameraId); |
| |
| if (CC_UNLIKELY(err < 0)) { |
| ALOGE("initCamera X: error(%d), %s", err, |
| (mCameraId == CAMERA_FACING_BACK) ? FLITE0_DEV_PATH : FLITE1_DEV_PATH); |
| goto fimc_out; |
| } |
| if (mCameraId == CAMERA_FACING_BACK) { |
| char read_prop[92]; |
| int res_prop = 0; |
| int value = 0; |
| |
| CLEAR(read_prop); |
| res_prop = property_get("persist.sys.camera.fw_update", read_prop, "0"); |
| ALOGD("Lens Close Hold persist.sys.camera.fw_update [%s], res %d", read_prop, res_prop); |
| |
| // ISP boot option : "0" => Normal, "1" => fw_update |
| if (!strcmp(read_prop, "1")) |
| value = 0x1; |
| else |
| { |
| CLEAR(read_prop); |
| res_prop = property_get("persist.sys.camera.samsung", read_prop, "0"); |
| ALOGD("Lens Close Hold persist.sys.camera.samsung [%s], res %d", read_prop, res_prop); |
| |
| // samsung app : "0" => 3th party app, "1" => samsung app |
| if (!strcmp(read_prop, "1")) |
| value = 0x0; |
| else |
| value = 0x1; |
| } |
| |
| CLEAR(read_prop); |
| res_prop = property_get("persist.sys.camera.mem", read_prop, "0"); |
| ALOGD("ISP mem : property get [%s], res %d", read_prop, res_prop); |
| |
| // ISP target memory : "0" => NOR, "1" => EEPROM |
| if (!strcmp(read_prop, "1")) |
| value |= (0x1 << 8); |
| else |
| value |= 0x0; |
| |
| ALOGD("call camera init with value: 0x%02X", value); |
| err = nativeSetParameters(CAM_CID_CAMERA_INIT, value); |
| if (CC_UNLIKELY(err < 0)) { |
| ALOGE("camera init error:%d", err); |
| } |
| } |
| mFliteNode.fd = mFlite.getFd(); |
| ALOGV("mFlite fd %d", mFlite.getFd()); |
| |
| #if 0 |
| if (!mEnableDZoom) { |
| err = mFimc1.init(FLITE1_DEV_PATH, mCameraId); |
| if (CC_UNLIKELY(err < 0)) { |
| ALOGE("initCamera X: error, %s", FLITE1_DEV_PATH); |
| goto fimc1_out; |
| } |
| |
| if (mFlite.mIsInternalISP) { |
| mFlite.sctrl(CAM_CID_IS_S_FORMAT_SCENARIO, IS_MODE_PREVIEW_STILL); |
| } |
| } |
| #endif |
| |
| setExifFixedAttribute(); |
| |
| /* init CSC (fimc1, fimc2) */ |
| mFimc1CSC = csc_init(cscMethod); |
| if (mFimc1CSC == NULL) |
| ALOGE("ERR(%s): mFimc1CSC csc_init() fail", __func__); |
| err = csc_set_hw_property(mFimc1CSC, CSC_HW_PROPERTY_FIXED_NODE, FIMC1_NODE_NUM); |
| if (err != 0) |
| ALOGE("ERR(%s): fimc0 open failed %d", __func__, err); |
| |
| mFimc2CSC = csc_init(cscMethod); |
| if (mFimc2CSC == NULL) |
| ALOGE("ERR(%s): mFimc2CSC csc_init() fail", __func__); |
| err = csc_set_hw_property(mFimc2CSC, CSC_HW_PROPERTY_FIXED_NODE, FIMC2_NODE_NUM); |
| if (err != 0) |
| ALOGE("ERR(%s): fimc1 open failed %d", __func__, err); |
| |
| LOG_PERFORMANCE_END(1, "total"); |
| return ISecCameraHardware::init(); |
| |
| fimc_out: |
| #if IS_FW_DEBUG |
| if ((mCameraId == CAMERA_FACING_FRONT) || (mCameraId == FD_SERVICE_CAMERA_ID)) { |
| mPrevOffset = 0; |
| mCurrOffset = 0; |
| mPrevWp = 0; |
| mCurrWp = 0; |
| mDebugVaddr = 0; |
| |
| int ret = nativeGetDebugAddr(&mDebugVaddr); |
| if (ret < 0) { |
| ALOGE("ERR(%s):Fail on SecCamera->getDebugAddr()", __func__); |
| mPrintDebugEnabled = false; |
| } else { |
| mPrintDebugEnabled = true; |
| ISecCameraHardware::printDebugFirmware(); |
| munmap((void *)mDebugVaddr, FIMC_IS_FW_MMAP_REGION_SIZE); |
| if (m_mem_fd >= 0) |
| close(m_mem_fd); |
| m_mem_fd = -1; |
| mPrintDebugEnabled = false; |
| } |
| } |
| #endif |
| |
| mFlite.deinit(); |
| return false; |
| } |
| |
| void SecCameraHardware::initDefaultParameters() |
| { |
| char str[16]; |
| CLEAR(str); |
| if (mCameraId == CAMERA_FACING_BACK) { |
| snprintf(str, sizeof(str), "%f", (double)Exif::DEFAULT_BACK_FOCAL_LEN_NUM/ |
| Exif::DEFAULT_BACK_FOCAL_LEN_DEN); |
| mParameters.set(CameraParameters::KEY_FOCAL_LENGTH, str); |
| mParameters.set(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE, "69.0"); |
| mParameters.set(CameraParameters::KEY_VERTICAL_VIEW_ANGLE, "46.3"); |
| } else { |
| snprintf(str, sizeof(str), "%f", (double)Exif::DEFAULT_FRONT_FOCAL_LEN_NUM/ |
| Exif::DEFAULT_FRONT_FOCAL_LEN_DEN); |
| mParameters.set(CameraParameters::KEY_FOCAL_LENGTH, str); |
| mParameters.set(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE, "54.7"); |
| mParameters.set(CameraParameters::KEY_VERTICAL_VIEW_ANGLE, "42.3"); |
| } |
| |
| ISecCameraHardware::initDefaultParameters(); |
| } |
| |
| void SecCameraHardware::release() |
| { |
| ALOGD("release E"); |
| |
| /* Forced wake up sound interrupt */ |
| mCameraPower = false; |
| nativeSetParameters(CAM_CID_CAMERA_POWER_OFF, 1); |
| ExynosBuffer nullBuf; |
| int i = 0; |
| |
| ISecCameraHardware::release(); |
| |
| mFlite.deinit(); |
| |
| /* flite buffer free */ |
| for (i = 0; i < FLITE_BUF_CNT; i++) { |
| freeMem(&mFliteNode.buffer[i]); |
| mFliteNode.buffer[i] = nullBuf; |
| } |
| |
| /* capture buffer free */ |
| for (i = 0; i < SKIP_CAPTURE_CNT; i++) { |
| freeMem(&mPictureBufDummy[i]); |
| mPictureBufDummy[i] = nullBuf; |
| } |
| freeMem(&mPictureBuf); |
| mPictureBuf = nullBuf; |
| |
| mInitRecSrcQ(); |
| mInitRecDstBuf(); |
| |
| /* deinit CSC (fimc0, fimc1) */ |
| if (mFimc1CSC) |
| csc_deinit(mFimc1CSC); |
| mFimc1CSC = NULL; |
| |
| if (mFimc2CSC) |
| csc_deinit(mFimc2CSC); |
| mFimc2CSC = NULL; |
| |
| #ifdef ENABLE_MC |
| if (mMedia) |
| exynos_media_close(mMedia); |
| #endif |
| mMedia = NULL; |
| } |
| |
| #ifndef FPOLLING |
| bool SecCameraHardware::isFactoryTest() |
| { |
| return ( mFactoryTestNum ) ? true : false; |
| } |
| #endif |
| |
| #ifndef FCJUNG |
| int SecCameraHardware::nativeSetFactoryTestNum(uint32_t mFactoryTestNum) |
| { |
| mFlite.setFactoryTestNumFimc(mFactoryTestNum); |
| return 0; |
| } |
| #endif |
| |
| int SecCameraHardware::nativeSetFastCapture(bool onOff) |
| { |
| mFastCaptureCalled = onOff; |
| |
| mFlite.setFastCaptureFimc(mFastCaptureCalled); |
| return 0; |
| } |
| |
| bool SecCameraHardware::nativeCreateSurface(uint32_t width, uint32_t height, uint32_t halPixelFormat) |
| { |
| ALOGV("nativeCreateSurfaces: E"); |
| int min_bufs; |
| |
| if (CC_UNLIKELY(mFlagANWindowRegister == true)) { |
| ALOGI("Surface already exist!!"); |
| return true; |
| } |
| |
| status_t err; |
| |
| if (mPreviewWindow->get_min_undequeued_buffer_count(mPreviewWindow, &min_bufs)) { |
| ALOGE("%s: could not retrieve min undequeued buffer count", __FUNCTION__); |
| return INVALID_OPERATION; |
| } |
| |
| if (min_bufs >= PREVIEW_BUF_CNT) { |
| ALOGE("%s: warning, min undequeued buffer count %d is too high (expecting at most %d)", __FUNCTION__, |
| min_bufs, PREVIEW_BUF_CNT - 1); |
| } |
| |
| ALOGD("%s: setting buffer count to %d", __FUNCTION__, PREVIEW_BUF_CNT); |
| if (mPreviewWindow->set_buffer_count(mPreviewWindow, PREVIEW_BUF_CNT)) { |
| ALOGE("%s: could not set buffer count", __FUNCTION__); |
| return INVALID_OPERATION; |
| } |
| |
| if (mPreviewWindow->set_usage(mPreviewWindow, GRALLOC_SET_USAGE_FOR_CAMERA) != 0) { |
| ALOGE("ERR(%s):could not set usage on gralloc buffer", __func__); |
| return INVALID_OPERATION; |
| } |
| |
| ALOGD("DEBUG(%s): %d/%d", __FUNCTION__, width, height); |
| if (mPreviewWindow->set_buffers_geometry(mPreviewWindow, |
| width, height, |
| halPixelFormat)) { |
| ALOGE("%s: could not set buffers geometry ", __FUNCTION__); |
| return INVALID_OPERATION; |
| } |
| |
| mFlagANWindowRegister = true; |
| |
| return true; |
| } |
| |
| bool SecCameraHardware::nativeDestroySurface(void) |
| { |
| ALOGV("nativeDestroySurface: E"); |
| mFlagANWindowRegister = false; |
| |
| return true; |
| } |
| |
| int SecCameraHardware::save_dump_path( uint8_t *real_data, int data_size, const char* filePath) |
| { |
| FILE *fp = NULL; |
| char *buffer = NULL; |
| |
| ALOGE("save dump E"); |
| fp = fopen(filePath, "wb"); |
| |
| if (fp == NULL) { |
| ALOGE("Save dump image open error"); |
| return -1; |
| } |
| |
| ALOGE("%s: real_data size ========> %d", __func__, data_size); |
| buffer = (char *) malloc(data_size); |
| if (buffer == NULL) { |
| ALOGE("Save buffer alloc failed"); |
| if (fp) |
| fclose(fp); |
| |
| return -1; |
| } |
| |
| memcpy(buffer, real_data, data_size); |
| |
| fflush(stdout); |
| |
| fwrite(buffer, 1, data_size, fp); |
| |
| fflush(fp); |
| |
| if (fp) |
| fclose(fp); |
| if (buffer) |
| free(buffer); |
| |
| ALOGE("save dump X"); |
| return 0; |
| } |
| |
| bool SecCameraHardware::nativeFlushSurfaceYUV420(uint32_t width, uint32_t height, uint32_t size, uint32_t index, int type) |
| { |
| //ALOGV("%s: width=%d, height=%d, size=0x%x, index=%d", __FUNCTION__, width, height, size, index); |
| ExynosBuffer dstBuf; |
| buffer_handle_t *buf_handle = NULL; |
| |
| if (CC_UNLIKELY(!mPreviewWindowSize.width)) { |
| ALOGE("nativeFlushSurfacePostview: error, Preview window %dx%d", mPreviewWindowSize.width, mPreviewWindowSize.height); |
| return false; |
| } |
| |
| if (CC_UNLIKELY(mFlagANWindowRegister == false)) { |
| ALOGE("%s::mFlagANWindowRegister == false fail", __FUNCTION__); |
| return false; |
| } |
| |
| if (mPreviewWindow && mGrallocHal) { |
| int stride; |
| if (0 != mPreviewWindow->dequeue_buffer(mPreviewWindow, &buf_handle, &stride)) { |
| ALOGE("Could not dequeue gralloc buffer!\n"); |
| return false; |
| } else { |
| if (mPreviewWindow->lock_buffer(mPreviewWindow, buf_handle) != 0) |
| ALOGE("ERR(%s):Could not lock gralloc buffer !!", __func__ ); |
| } |
| |
| unsigned int vaddr[3]; |
| if (!mGrallocHal->lock(mGrallocHal, |
| *buf_handle, |
| GRALLOC_LOCK_FOR_CAMERA, |
| 0, 0, width, height, (void **)vaddr)) { |
| |
| char *src; |
| char *ptr = (char *)vaddr[0]; |
| src = (char *)mPostviewHeap->data; |
| |
| memcpy(ptr, src, width * height); |
| src += width * height; |
| ptr = (char *)vaddr[1]; |
| memcpy(ptr, src, (width * height ) >> 1); |
| |
| mGrallocHal->unlock(mGrallocHal, *buf_handle); |
| } |
| |
| if (0 != mPreviewWindow->enqueue_buffer(mPreviewWindow, buf_handle)) { |
| ALOGE("Could not enqueue gralloc buffer!\n"); |
| return false; |
| } |
| } else if (!mGrallocHal) { |
| ALOGE("nativeFlushSurface: gralloc HAL is not loaded"); |
| return false; |
| } |
| |
| return true; |
| |
| CANCEL: |
| if (mPreviewWindow->cancel_buffer(mPreviewWindow, buf_handle) != 0) |
| ALOGE("ERR(%s):Fail to cancel buffer", __func__); |
| |
| return false; |
| } |
| |
| bool SecCameraHardware::nativeFlushSurface(uint32_t width, uint32_t height, uint32_t size, uint32_t index, int type) |
| { |
| //ALOGV("%s: width=%d, height=%d, size=0x%x, index=%d", __FUNCTION__, width, height, size, index); |
| ExynosBuffer dstBuf; |
| buffer_handle_t *buf_handle = NULL; |
| |
| if (CC_UNLIKELY(!mPreviewWindowSize.width)) { |
| ALOGE("nativeFlushSurface: error, Preview window %dx%d", mPreviewWindowSize.width, mPreviewWindowSize.height); |
| return false; |
| } |
| |
| if (CC_UNLIKELY(mFlagANWindowRegister == false)) { |
| ALOGE("%s::mFlagANWindowRegister == false fail", __FUNCTION__); |
| return false; |
| } |
| |
| if (mPreviewWindow && mGrallocHal) { |
| int stride; |
| if (0 != mPreviewWindow->dequeue_buffer(mPreviewWindow, &buf_handle, &stride)) { |
| ALOGE("Could not dequeue gralloc buffer!\n"); |
| return false; |
| } else { |
| if (mPreviewWindow->lock_buffer(mPreviewWindow, buf_handle) != 0) |
| ALOGE("ERR(%s):Could not lock gralloc buffer !!", __func__ ); |
| } |
| |
| unsigned int vaddr[3]; |
| if (!mGrallocHal->lock(mGrallocHal, |
| *buf_handle, |
| GRALLOC_LOCK_FOR_CAMERA, |
| 0, 0, width, height, (void **)vaddr)) { |
| |
| /* csc start flite(s) -> fimc0 -> gralloc(d) */ |
| if (mFimc1CSC) { |
| /* set zoom info */ |
| mPreviewZoomRect.w = ALIGN_DOWN((mFLiteSize.width * 10 / mZoomValue), 2); |
| mPreviewZoomRect.h = ALIGN_DOWN((mFLiteSize.height * 10 / mZoomValue), 2); |
| |
| mPreviewZoomRect.x = ALIGN_DOWN(((mFLiteSize.width - mPreviewZoomRect.w) / 2), 2); |
| mPreviewZoomRect.y = ALIGN_DOWN(((mFLiteSize.height - mPreviewZoomRect.h) / 2), 2); |
| |
| /* src : FLite */ |
| csc_set_src_format(mFimc1CSC, |
| mFLiteSize.width, mFLiteSize.height, |
| mPreviewZoomRect.x, mPreviewZoomRect.y, |
| mPreviewZoomRect.w, mPreviewZoomRect.h, |
| V4L2_PIX_2_HAL_PIXEL_FORMAT(mFliteNode.format), |
| 0); |
| |
| if (type == CAMERA_HEAP_POSTVIEW) { |
| csc_set_src_buffer(mFimc1CSC, |
| (void **)mPictureBufDummy[0].fd.extFd, CSC_MEMORY_DMABUF); |
| } else { |
| csc_set_src_buffer(mFimc1CSC, |
| (void **)mFliteNode.buffer[index].fd.extFd, CSC_MEMORY_DMABUF); |
| } |
| |
| /* mSaveDump("/data/camera_source%d.yuv", &mFliteNode.buffer[index], index); */ |
| |
| int halPixelFormat = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_FULL; |
| |
| /* when recording, narrow color range will be applied */ |
| if (mMovieMode) |
| halPixelFormat = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP; |
| |
| /* dst : GRALLOC */ |
| csc_set_dst_format(mFimc1CSC, |
| mPreviewSize.width, mPreviewSize.height, |
| 0, 0, |
| mPreviewSize.width, mPreviewSize.height, |
| halPixelFormat, |
| 0); |
| |
| const private_handle_t *priv_handle = private_handle_t::dynamicCast(*buf_handle); |
| dstBuf.fd.extFd[0] = priv_handle->fd; |
| dstBuf.fd.extFd[1] = priv_handle->fd1; |
| dstBuf.virt.extP[0] = (char *)vaddr[0]; |
| dstBuf.virt.extP[1] = (char *)vaddr[1]; |
| dstBuf.size.extS[0] = mPreviewSize.width * mPreviewSize.height; |
| dstBuf.size.extS[1] = mPreviewSize.width * mPreviewSize.height / 2; |
| |
| csc_set_dst_buffer(mFimc1CSC, |
| (void **)dstBuf.fd.extFd, CSC_MEMORY_DMABUF); |
| |
| mFimc1CSCLock.lock(); |
| if (csc_convert(mFimc1CSC) != 0) { |
| ALOGE("ERR(%s):csc_convert(mFimc1CSC) fail", __func__); |
| mFimc1CSCLock.unlock(); |
| goto CANCEL; |
| } |
| mFimc1CSCLock.unlock(); |
| } |
| |
| mGrallocHal->unlock(mGrallocHal, *buf_handle); |
| } |
| |
| if (0 != mPreviewWindow->enqueue_buffer(mPreviewWindow, buf_handle)) { |
| ALOGE("Could not enqueue gralloc buffer!\n"); |
| return false; |
| } |
| } else if (!mGrallocHal) { |
| ALOGE("nativeFlushSurface: gralloc HAL is not loaded"); |
| return false; |
| } |
| |
| #if 0 |
| mSaveDump("/data/camera_flush%d.yuv", &dstBuf, count); |
| count++; |
| if(count > 3) count = 0; |
| #endif |
| /* if CAMERA_MSG_PREVIEW_METADATA, prepare callback buffer */ |
| if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) { |
| if (nativePreviewCallback(index, &dstBuf) < 0) |
| ALOGE("ERROR(%s): nativePreviewCallback failed", __func__); |
| } |
| |
| |
| return true; |
| |
| CANCEL: |
| if (mPreviewWindow->cancel_buffer(mPreviewWindow, buf_handle) != 0) |
| ALOGE("ERR(%s):Fail to cancel buffer", __func__); |
| |
| return false; |
| } |
| |
| bool SecCameraHardware::beautyLiveFlushSurface(uint32_t width, uint32_t height, uint32_t size, uint32_t index, int type) |
| { |
| //ALOGV("%s: width=%d, height=%d, size=0x%x, index=%d", __FUNCTION__, width, height, size, index); |
| ExynosBuffer dstBuf; |
| buffer_handle_t *buf_handle = NULL; |
| |
| if (CC_UNLIKELY(!mPreviewWindowSize.width)) { |
| ALOGE("nativeFlushSurface: error, Preview window %dx%d", mPreviewWindowSize.width, mPreviewWindowSize.height); |
| return false; |
| } |
| |
| if (CC_UNLIKELY(mFlagANWindowRegister == false)) { |
| ALOGE("%s::mFlagANWindowRegister == false fail", __FUNCTION__); |
| return false; |
| } |
| |
| if (mPreviewWindow && mGrallocHal) { |
| int stride; |
| if (0 != mPreviewWindow->dequeue_buffer(mPreviewWindow, &buf_handle, &stride)) { |
| ALOGE("Could not dequeue gralloc buffer!\n"); |
| return false; |
| } else { |
| if (mPreviewWindow->lock_buffer(mPreviewWindow, buf_handle) != 0) |
| ALOGE("ERR(%s):Could not lock gralloc buffer !!", __func__ ); |
| } |
| |
| unsigned int vaddr[3]; |
| if (!mGrallocHal->lock(mGrallocHal, |
| *buf_handle, |
| GRALLOC_LOCK_FOR_CAMERA, |
| 0, 0, width, height, (void **)vaddr)) { |
| /////////////////////////////////////////////////////////////////////// |
| char *frame = NULL; |
| if ( type==CAMERA_HEAP_PREVIEW) { |
| frame = ((char *)mPreviewHeap->data) + (mPreviewFrameSize * index); |
| } else { |
| frame = ((char *)mPostviewHeap->data); |
| } |
| char *src = frame; |
| char *ptr = (char *)vaddr[0]; |
| |
| if (src == NULL || ptr == NULL) |
| return false; |
| |
| // Y |
| memcpy(ptr, src, width * height); |
| src += width * height; |
| if (mPreviewFormat == CAM_PIXEL_FORMAT_YVU420P) { |
| /* YV12 */ |
| //ALOGV("%s: yuv420p YV12", __func__); |
| // V |
| ptr = (char *)vaddr[1]; |
| if (src == NULL || ptr == NULL) |
| return false; |
| |
| memcpy(ptr, src, width * height / 4); |
| src += width * height / 4; |
| // U |
| ptr = (char *)vaddr[2]; |
| if (src == NULL || ptr == NULL) |
| return false; |
| |
| memcpy(ptr, src, width * height / 4); |
| } else if (mPreviewFormat == CAM_PIXEL_FORMAT_YUV420SP) { |
| /* NV21 */ |
| //ALOGV("%s: yuv420sp NV21", __func__); |
| ptr = (char *)vaddr[1]; |
| if (src == NULL || ptr == NULL) |
| return false; |
| |
| memcpy(ptr, src, (width * height) >> 1); |
| } |
| /////////////////////////////////////////////////////////////////////// |
| mGrallocHal->unlock(mGrallocHal, *buf_handle); |
| } |
| |
| if (0 != mPreviewWindow->enqueue_buffer(mPreviewWindow, buf_handle)) { |
| ALOGE("Could not enqueue gralloc buffer!\n"); |
| return false; |
| } |
| } else if (!mGrallocHal) { |
| ALOGE("nativeFlushSurface: gralloc HAL is not loaded"); |
| return false; |
| } |
| |
| /* if CAMERA_MSG_PREVIEW_METADATA, prepare callback buffer */ |
| if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) { |
| if (nativePreviewCallback(index, &dstBuf) < 0) |
| ALOGE("ERROR(%s): nativePreviewCallback failed", __func__); |
| } |
| |
| return true; |
| |
| CANCEL: |
| if (mPreviewWindow->cancel_buffer(mPreviewWindow, buf_handle) != 0) |
| ALOGE("ERR(%s):Fail to cancel buffer", __func__); |
| |
| return false; |
| } |
| |
| |
| |
| image_rect_type SecCameraHardware::nativeGetWindowSize() |
| { |
| image_rect_type window; |
| if (!mMovieMode) { |
| window.width = mPreviewSize.width; |
| window.height = mPreviewSize.height; |
| return window; |
| } |
| |
| switch (FRM_RATIO(mPreviewSize)) { |
| case CAM_FRMRATIO_QCIF: |
| window.width = 528; |
| window.height = 432; |
| break; |
| case CAM_FRMRATIO_VGA: |
| window.width = 640; |
| window.height = 480; |
| break; |
| case CAM_FRMRATIO_WVGA: |
| window.width = 800; |
| window.height = 480; |
| break; |
| case CAM_FRMRATIO_D1: |
| window.width = 720; |
| window.height = 480; |
| break; |
| case CAM_FRMRATIO_HD: |
| window.width = 800; |
| window.height = 450; |
| break; |
| default: |
| ALOGW("nativeGetWindowSize: invalid frame ratio %d", FRM_RATIO(mPreviewSize)); |
| window.width = mPreviewSize.width; |
| window.height = mPreviewSize.height; |
| break; |
| } |
| return window; |
| } |
| |
| #ifdef BURST_SHOT_SUPPORT |
| bool SecCameraHardware::nativeSaveJpegPicture(const char *fname, burst_item* item){ |
| int cnt = 0; |
| uint32_t written = 0; |
| |
| uint8_t* buf = mBurstShot.getAddress(item); |
| uint32_t size = item->size; |
| |
| //ALOGD("opening file [%s]\n", fname); |
| LOG_PERFORMANCE_START(1); |
| int fd = open(fname, O_RDWR | O_CREAT, 0664); |
| if (fd < 0) { |
| ALOGE("failed to create file [%s]: %s", fname, strerror(errno)); |
| return false; |
| } |
| LOG_PERFORMANCE_END(1, "open"); |
| |
| //ALOGD("writing %d bytes to file [%s]\n", size, fname); |
| LOG_PERFORMANCE_START(2); |
| while (written < size) { |
| int nw; |
| nw = ::write(fd, |
| buf + written, |
| size - written); |
| |
| //ALOGD("writing %d bytes\n", nw); |
| |
| if (nw < 0) { |
| ALOGE("failed to write to file [%s]: %s", |
| fname, strerror(errno)); |
| break; |
| } |
| written += nw; |
| cnt++; |
| } |
| LOG_PERFORMANCE_END(2, "write"); |
| //ALOGD("done writing %d bytes to file [%s] in %d passes\n", size, fname, cnt); |
| ::close(fd); |
| |
| if (chmod(fname,0664) < 0) { |
| ALOGE("failed chmod '%s'",fname); |
| } |
| |
| if (chown(fname, AID_MEDIA, AID_MEDIA_RW) < 0) { |
| ALOGE("failed chown '%s' user(%d) group(%d)", fname, AID_MEDIA, AID_MEDIA_RW); |
| } |
| |
| return true; |
| } |
| #endif |
| |
| bool SecCameraHardware::allocatePreviewHeap() |
| { |
| if (mPreviewHeap) { |
| mPreviewHeap->release(mPreviewHeap); |
| mPreviewHeap = 0; |
| mPreviewHeapFd = -1; |
| } |
| |
| /* not need to alloc MHB by mM2MExyMemFd for ion */ |
| #ifdef BOARD_USE_MHB_ION |
| if (mEnableDZoom) { |
| mPreviewHeap = mGetMemoryCb(-1, mPreviewFrameSize, PREVIEW_BUF_CNT, &mPreviewHeapFd); |
| if (!mPreviewHeap || mPreviewHeapFd < 0) { |
| ALOGE("allocatePreviewHeap: error, fail to create preview heap(%d)", mPreviewHeap); |
| return false; |
| } |
| } else { |
| mPreviewHeap = mGetMemoryCb((int)mFlite.getfd(), mPreviewFrameSize, PREVIEW_BUF_CNT, 0); |
| if (!mPreviewHeap) { |
| ALOGE("allocatePreviewHeap: error, fail to create preview heap(%d %d)", mPreviewHeap, mPreviewHeapFd); |
| return false; |
| } |
| } |
| #else |
| if (mEnableDZoom) { |
| mPreviewHeap = mGetMemoryCb(-1, mPreviewFrameSize, PREVIEW_BUF_CNT, 0); |
| if (!mPreviewHeap) { |
| ALOGE("allocatePreviewHeap: error, fail to create preview heap(%d)", mPreviewHeap); |
| return false; |
| } |
| } else { |
| mPreviewHeap = mGetMemoryCb((int)mFlite.getfd(), mPreviewFrameSize, PREVIEW_BUF_CNT, 0); |
| if (!mPreviewHeap) { |
| ALOGE("allocatePreviewHeap: error, fail to create preview heap(%d)", mPreviewHeap); |
| return false; |
| } |
| } |
| #endif |
| |
| ALOGD("allocatePreviewHeap: %dx%d, frame %dx%d", |
| mOrgPreviewSize.width, mOrgPreviewSize.height, mPreviewFrameSize, PREVIEW_BUF_CNT); |
| |
| return true; |
| } |
| |
| #ifndef FCJUNG |
| int SecCameraHardware::nativeSetStream(bool flag) |
| { |
| int err = mFlite.stream(flag); |
| if ( mCaptureMode == RUNNING_MODE_SINGLE ) |
| Fimc_stream_true_part2(); |
| return err; |
| } |
| #endif |
| |
| status_t SecCameraHardware::nativeStartPreview() |
| { |
| ALOGV("nativeStartPreview E"); |
| |
| int err; |
| int formatMode; |
| |
| /* YV12 */ |
| ALOGD("nativeStartPreview: Preview Format = %s", |
| mFliteFormat == CAM_PIXEL_FORMAT_YVU420P ? "YV12" : |
| mFliteFormat == CAM_PIXEL_FORMAT_YUV420SP ? "NV21" : |
| mFliteFormat == CAM_PIXEL_FORMAT_YUV422I ? "YUYV" : |
| "Others"); |
| |
| /* This is for VT test mode (SelfTest Mode) */ |
| if ((mVtMode > 0) && mFlite.mIsInternalISP && !mFullPreviewRunning) |
| nativeSetParameters(CAM_CID_VT_MODE, mVtMode); |
| |
| err = mFlite.startPreview(&mFLiteSize, mFliteFormat, FLITE_BUF_CNT, mFps, mMovieMode, &mFliteNode); |
| CHECK_ERR_N(err, ("nativeStartPreview: error, mFlite.start")); |
| |
| mFlite.querybuf(&mPreviewFrameSize); |
| if (mPreviewFrameSize == 0) { |
| ALOGE("nativeStartPreview: error, mFlite.querybuf"); |
| return UNKNOWN_ERROR; |
| } |
| |
| if (!allocatePreviewHeap()) { |
| ALOGE("nativeStartPreview: error, allocatePreviewHeap"); |
| return NO_MEMORY; |
| } |
| |
| for (int i = 0; i < FLITE_BUF_CNT; i++) { |
| err = mFlite.qbuf(i); |
| CHECK_ERR_N(err, ("nativeStartPreview: error %d, mFlite.qbuf(%d)", err, i)); |
| } |
| |
| err = mFlite.stream(true); |
| CHECK_ERR_N(err, ("nativeStartPreview: error %d, mFlite.stream", err)); |
| |
| ALOGV("nativeStartPreview X"); |
| return NO_ERROR; |
| } |
| |
| status_t SecCameraHardware::nativeStartPreviewZoom() |
| { |
| ALOGV("nativeStartPreviewZoom E"); |
| |
| int err; |
| int formatMode; |
| int i = 0; |
| ExynosBuffer nullBuf; |
| |
| /* YV12 */ |
| ALOGD("nativeStartPreview: FLite Format = %s", |
| mFliteFormat == CAM_PIXEL_FORMAT_YVU420P ? "YV12" : |
| mFliteFormat == CAM_PIXEL_FORMAT_YUV420SP ? "NV21" : |
| mFliteFormat == CAM_PIXEL_FORMAT_YUV422I ? "YUYV" : |
| "Others"); |
| |
| err = mFlite.startPreview(&mFLiteSize, mFliteFormat, FLITE_BUF_CNT, mFps, mMovieMode, &mFliteNode); |
| CHECK_ERR_N(err, ("nativeStartPreviewZoom: error, mFlite.start")); |
| mFliteNode.ionClient = mIonCameraClient; |
| |
| ALOGI("INFO(%s): mFliteNode.fd [%d]" , __func__, mFliteNode.fd); |
| ALOGI("INFO(%s): mFliteNode.width [%d]" , __func__, mFliteNode.width); |
| ALOGI("INFO(%s): mFliteNode.height [%d]" , __func__, mFliteNode.height); |
| ALOGI("INFO(%s): mFliteNode.format [%c%c%c%c]" , __func__, mFliteNode.format, |
| mFliteNode.format >> 8, mFliteNode.format >> 16, mFliteNode.format >> 24); |
| ALOGI("INFO(%s): mFliteNode.planes [%d]" , __func__, mFliteNode.planes); |
| ALOGI("INFO(%s): mFliteNode.buffers[%d]" , __func__, mFliteNode.buffers); |
| ALOGI("INFO(%s): mFliteNode.memory [%d]" , __func__, mFliteNode.memory); |
| ALOGI("INFO(%s): mFliteNode.type [%d]" , __func__, mFliteNode.type); |
| ALOGI("INFO(%s): mFliteNode.ionClient [%d]", __func__, mFliteNode.ionClient); |
| |
| #ifdef USE_USERPTR |
| /* For FLITE buffer */ |
| for (i = 0; i < FLITE_BUF_CNT; i++) { |
| mFliteNode.buffer[i] = nullBuf; |
| /* YUV size */ |
| getAlignedYUVSize(mFliteFormat, mFLiteSize.width, mFLiteSize.height, &mFliteNode.buffer[i]); |
| if (allocMem(mIonCameraClient, &mFliteNode.buffer[i], 0) == false) { |
| ALOGE("ERR(%s):mFliteNode allocMem() fail", __func__); |
| return UNKNOWN_ERROR; |
| } else { |
| ALOGV("DEBUG(%s): mFliteNode allocMem(%d) adr(%p), size(%d), ion(%d)", __FUNCTION__, |
| i, mFliteNode.buffer[i].virt.extP[0], mFliteNode.buffer[i].size.extS[0], mIonCameraClient); |
| memset(mFliteNode.buffer[i].virt.extP[0], 0, mFliteNode.buffer[i].size.extS[0]); |
| } |
| } |
| #else |
| /* loop for buffer count */ |
| for (int i = 0; i < mFliteNode.buffers; i++) { |
| err = mFlite.querybuf2(i, mFliteNode.planes, &mFliteNode.buffer[i]); |
| CHECK_ERR_N(err, ("nativeStartPreviewZoom: error, mFlite.querybuf2")); |
| } |
| #endif |
| ALOGV("DEBUG(%s): mMsgEnabled(%d)", __FUNCTION__, mMsgEnabled); |
| |
| /* allocate preview callback buffer */ |
| /* check the Samsung app condition for CTS_Verifier */ |
| if (ISecCameraHardware::IsSamsungApp()) { |
| mPreviewFrameSize = getAlignedYUVSize(mPreviewFormat, mPreviewSize.width, mPreviewSize.height, NULL); |
| ALOGV("DEBUG(%s): mPreviewFrameSize(%d)(%dx%d) for callback", __FUNCTION__, |
| mPreviewFrameSize, mPreviewSize.width, mPreviewSize.height); |
| } else { |
| mPreviewFrameSize = getAlignedYUVSize(mPreviewFormat, mOrgPreviewSize.width, mOrgPreviewSize.height, NULL); |
| ALOGV("DEBUG(%s): mPreviewFrameSize(%d)(%dx%d) for callback", __FUNCTION__, |
| mPreviewFrameSize, mOrgPreviewSize.width, mOrgPreviewSize.height); |
| } |
| if (!allocatePreviewHeap()) { |
| ALOGE("ERR(%s)(%d): allocatePreviewHeap() fail", __FUNCTION__, __LINE__); |
| goto DESTROYMEM; |
| } |
| |
| mPreviewZoomRect.x = 0; |
| mPreviewZoomRect.y = 0; |
| mPreviewZoomRect.w = mFLiteSize.width; |
| mPreviewZoomRect.h = mFLiteSize.height; |
| |
| for (int i = 0; i < FLITE_BUF_CNT; i++) { |
| err = mFlite.qbuf2(&(mFliteNode), i); |
| CHECK_ERR_GOTO(DESTROYMEM, err, ("nativeStartPreviewZoom: error %d, mFlite.qbuf(%d)", err, i)); |
| } |
| |
| #if !defined(USE_USERPTR) |
| /* export FD */ |
| for (int i = 0; i < mFliteNode.buffers; i++) { |
| err = mFlite.expBuf(i, mFliteNode.planes, &mFliteNode.buffer[i]); |
| CHECK_ERR_N(err, ("nativeStartPreviewZoom: error, mFlite.expBuf")); |
| } |
| #endif |
| err = mFlite.stream(true); |
| CHECK_ERR_GOTO(DESTROYMEM, err, ("nativeStartPreviewZoom: error %d, mFlite.stream", err)); |
| |
| if (mCameraId == CAMERA_FACING_FRONT) { |
| int val; |
| val = mParameters.getInt(CameraParameters::KEY_EXPOSURE_COMPENSATION); |
| err = nativeSetParameters(CAM_CID_BRIGHTNESS, val); |
| CHECK_ERR_GOTO(DESTROYMEM, err, ("nativeStartPreviewZoom: error %d, nativeSetParameters", err)); |
| |
| val = mParameters.getInt("blur"); |
| if (val >= 0) { |
| err = nativeSetParameters(CAM_CID_BLUR, val); |
| CHECK_ERR_GOTO(DESTROYMEM, err, ("nativeStartPreviewZoom: error %d, nativeSetParameters", err)); |
| } |
| } |
| |
| ALOGV("nativeStartPreviewZoom X"); |
| return NO_ERROR; |
| |
| DESTROYMEM: |
| #ifdef USE_USERPTR |
| /* flite buffer free */ |
| for (i = 0; i < FLITE_BUF_CNT; i++) { |
| freeMem(&mFliteNode.buffer[i]); |
| mFliteNode.buffer[i] = nullBuf; |
| } |
| #else |
| if (mFlite.reqBufZero(&mFliteNode) < 0) |
| ALOGE("ERR(%s): mFlite.reqBufZero() fail", __func__); |
| for (i = 0; i < FLITE_BUF_CNT; i++) |
| mFliteNode.buffer[i] = nullBuf; |
| #endif |
| return UNKNOWN_ERROR; |
| } |
| |
| int SecCameraHardware::nativeGetPreview() |
| { |
| int index = -1; |
| int retries, retries2; |
| int ret = -1; |
| |
| retries = 10; |
| /* All buffers are empty. Request a frame to the device */ |
| retry: |
| #ifndef FPOLLING |
| if (mFlite.polling(isFactoryTest()) == 0) { |
| #endif |
| if (mFastCaptureCalled) { |
| return -1; |
| } |
| #ifndef APPLY_ESD |
| if (retries-- <= 0) |
| return -1; |
| |
| ALOGE("nativeGetPreview: no first frame!"); |
| nativeStopPreview(); |
| |
| if (mEnableDZoom) |
| ret = nativeStartPreviewZoom(); |
| else |
| ret = nativeStartPreview(); |
| |
| goto retry; |
| #else /* #ifndef APPLY_ESD */ |
| int err = NO_ERROR; |
| #if 1 |
| ALOGE("nativeGetPreview: ERROR. ESD"); |
| //mFlite.stream(false); |
| ALOGE("nativeGetPreview: ERROR. ESD 1"); |
| //nativeStopPreview(); |
| ALOGE("nativeGetPreview: ERROR. ESD 2"); |
| //mFlite.reset(); |
| ALOGE("nativeGetPreview: FliteV4L2.reset. ESD"); |
| |
| if (mCameraId == CAMERA_FACING_BACK) { |
| ALOGE("nativeGetPreview: Before CAM_CID_CAMERA_INIT. ESD"); |
| isResetedByESD = true; |
| mCameraPower = false; |
| nativeSetParameters(CAM_CID_CAMERA_POWER_OFF, 1); |
| //err = nativeSetParameters(CAM_CID_CAMERA_INIT, 2); |
| ALOGE("nativeGetPreview: after CAM_CID_CAMERA_INIT. ESD"); |
| CHECK_ERR_N(err, ("FimcV4l2 init: error %d", err)); |
| } |
| |
| return -1; |
| #else /* #if 1 */ /* ISP RESET TEST CODE */ |
| isp_reset_test_cnt = 0; |
| ALOGE("nativeGetPreview: ERROR. ESD"); |
| //mFlite.stream(false); |
| ALOGE("nativeGetPreview: ERROR. ESD 1"); |
| //nativeStopPreview(); |
| ALOGE("nativeGetPreview: ERROR. ESD 2"); |
| //mFlite.reset(); |
| ALOGE("nativeGetPreview: FliteV4L2.reset. ESD"); |
| |
| if (mCameraId == CAMERA_FACING_BACK) { |
| ALOGE("nativeGetPreview: Before CAM_CID_CAMERA_INIT. ESD"); |
| mCameraPower = false; |
| nativeSetParameters(CAM_CID_CAMERA_POWER_OFF, 1); |
| isResetedByESD = true; |
| //err = nativeSetParameters(CAM_CID_CAMERA_INIT, 2); |
| ALOGE("nativeGetPreview: after CAM_CID_CAMERA_INIT. ESD"); |
| CHECK_ERR_N(err, ("FimcV4l2 init: error %d", err)); |
| } |
| |
| #if 0 |
| if (retries-- <= 0) |
| return -1; |
| |
| ALOGE("nativeGetPreview: no first frame!"); |
| nativeStopPreview(); |
| |
| if (mEnableDZoom) |
| ret = nativeStartPreviewZoom(); |
| else |
| ret = nativeStartPreview(); |
| |
| goto retry; |
| #else /* #if 0 */ |
| return -1; |
| #endif /* #if 0 */ |
| |
| #endif /* #if 1 */ /* ISP RESET TEST CODE */ |
| #endif /* #ifndef APPLY_ESD */ |
| } else { |
| ret = mFlite.dqbuf2(&mFliteNode); |
| index = ret; |
| CHECK_ERR_N(index, ("nativeGetPreview: error, mFlite.dqbuf")); |
| |
| #ifdef APPLY_ESD |
| mFlite.mI2CErr = false; |
| #endif |
| } |
| |
| if (mEnableDZoom) |
| mRecordTimestamp = systemTime(SYSTEM_TIME_MONOTONIC); |
| |
| if (!mPreviewInitialized) { |
| mPreviewInitialized = true; |
| ALOGD("preview started"); |
| } |
| |
| return index; |
| } |
| |
| status_t SecCameraHardware::nativePreviewCallback(int index, ExynosBuffer *grallocBuf) |
| { |
| /* If orginal size and format(defined by app) is different to |
| * changed size and format(defined by hal), do CSC again. |
| * But orginal and changed size and format(defined by app) is same, |
| * just copy to callback buffer from gralloc buf |
| */ |
| |
| ExynosBuffer dstBuf; |
| dstBuf.fd.extFd[0] = mPreviewHeapFd; |
| getAlignedYUVSize(mPreviewFormat, mOrgPreviewSize.width, mOrgPreviewSize.height, &dstBuf); |
| char *srcAdr = NULL; |
| srcAdr = (char *)mPreviewHeap->data; |
| srcAdr += (index * mPreviewFrameSize); |
| |
| if (mPreviewFormat == V4L2_PIX_FMT_NV21 || |
| mPreviewFormat == V4L2_PIX_FMT_NV21M) { |
| dstBuf.virt.extP[0] = srcAdr; |
| dstBuf.virt.extP[1] = dstBuf.virt.extP[0] + dstBuf.size.extS[0]; |
| } else if (mPreviewFormat == V4L2_PIX_FMT_YVU420 || |
| mPreviewFormat == V4L2_PIX_FMT_YVU420M) { |
| dstBuf.virt.extP[0] = srcAdr; |
| dstBuf.virt.extP[1] = dstBuf.virt.extP[0] + dstBuf.size.extS[0]; |
| dstBuf.virt.extP[2] = dstBuf.virt.extP[1] + dstBuf.size.extS[1]; |
| } |
| |
| if (grallocBuf == NULL || |
| mOrgPreviewSize.width != mPreviewSize.width || |
| mOrgPreviewSize.height != mPreviewSize.height || |
| HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP != V4L2_PIX_2_HAL_PIXEL_FORMAT(mPreviewFormat)) { |
| |
| /* csc start flite(s) -> fimc0 -> callback(d) */ |
| if (mFimc2CSC) { |
| /* src : FLite */ |
| csc_set_src_format(mFimc2CSC, |
| mFLiteSize.width, mFLiteSize.height, |
| mPreviewZoomRect.x, mPreviewZoomRect.y, |
| mPreviewZoomRect.w, mPreviewZoomRect.h, |
| V4L2_PIX_2_HAL_PIXEL_FORMAT(mFliteNode.format), |
| 0); |
| |
| #ifdef USE_USERPTR |
| csc_set_src_buffer(mFimc2CSC, (void **)mFliteNode.buffer[index].virt.extP, CSC_MEMORY_USERPTR); |
| #else |
| csc_set_dst_buffer(mFimc2CSC, (void **)mFliteNode.buffer[index].fd.extFd, CSC_MEMORY_DMABUF); |
| #endif |
| |
| /* dst : callback buffer(MHB) */ |
| csc_set_dst_format(mFimc2CSC, |
| mOrgPreviewSize.width, mOrgPreviewSize.height, |
| 0, 0, |
| mOrgPreviewSize.width, mOrgPreviewSize.height, |
| V4L2_PIX_2_HAL_PIXEL_FORMAT(mPreviewFormat), |
| 0); |
| |
| csc_set_dst_buffer(mFimc2CSC, |
| (void **)dstBuf.virt.extP, CSC_MEMORY_USERPTR); |
| |
| mFimc2CSCLock.lock(); |
| if (csc_convert(mFimc2CSC) != 0) { |
| ALOGE("ERR(%s):csc_convert(mFimc1CSC) fail", __func__); |
| mFimc2CSCLock.unlock(); |
| return false; |
| } |
| mFimc2CSCLock.unlock(); |
| } else { |
| ALOGE("ERR(%s): mFimc1CSC == NULL", __func__); |
| return false; |
| } |
| } else { |
| for (int plane = 0; plane < 2; plane++) { |
| /* just memcpy only */ |
| char *srcAddr = NULL; |
| char *dstAddr = NULL; |
| srcAddr = grallocBuf->virt.extP[plane]; |
| dstAddr = dstBuf.virt.extP[plane]; |
| memcpy(dstAddr, srcAddr, dstBuf.size.extS[plane]); |
| } |
| } |
| /* mSaveDump("/data/camera_preview%d.yuv", &dstBuf, index); */ |
| |
| return NO_ERROR; |
| } |
| |
| |
| int SecCameraHardware::nativeReleasePreviewFrame(int index) |
| { |
| #ifdef FAKE_SENSOR |
| return mFlite.fakeQbuf2(&mFliteNode, index); |
| #else |
| return mFlite.qbuf2(&mFliteNode, index); |
| #endif |
| } |
| |
| void SecCameraHardware::nativeStopPreview(void) |
| { |
| int err = 0; |
| int i = 0; |
| ExynosBuffer nullBuf; |
| |
| err = mFlite.stream(false); |
| if (CC_UNLIKELY(err < 0)) |
| ALOGE("nativeStopPreview: error, mFlite.stream"); |
| |
| #ifdef USE_USERPTR |
| /* flite buffer free */ |
| for (i = 0; i < FLITE_BUF_CNT; i++) { |
| freeMem(&mFliteNode.buffer[i]); |
| mFliteNode.buffer[i] = nullBuf; |
| } |
| #else |
| for (i = 0; i < FLITE_BUF_CNT; i++) { |
| for (int j = 0; j < mFliteNode.planes; j++) { |
| munmap((void *)mFliteNode.buffer[i].virt.extP[j], |
| mFliteNode.buffer[i].size.extS[j]); |
| ion_free(mFliteNode.buffer[i].fd.extFd[j]); |
| } |
| mFliteNode.buffer[i] = nullBuf; |
| } |
| |
| if (mFlite.reqBufZero(&mFliteNode) < 0) |
| ALOGE("ERR(%s): mFlite.reqBufZero() fail", __func__); |
| #endif |
| ALOGD("nativeStopPreview EX"); |
| } |
| |
| bool SecCameraHardware::allocateRecordingHeap() |
| { |
| int framePlaneSize1 = ALIGN(mVideoSize.width, 16) * ALIGN(mVideoSize.height, 16) + MFC_7X_BUFFER_OFFSET; |
| int framePlaneSize2 = ALIGN(mVideoSize.width, 16) * ALIGN(mVideoSize.height / 2, 16) + MFC_7X_BUFFER_OFFSET;; |
| |
| if (mRecordingHeap != NULL) { |
| mRecordingHeap->release(mRecordingHeap); |
| mRecordingHeap = 0; |
| mRecordHeapFd = -1; |
| } |
| |
| #ifdef BOARD_USE_MHB_ION |
| mRecordingHeap = mGetMemoryCb(-1, sizeof(struct addrs), REC_BUF_CNT, &mRecordHeapFd); |
| if (mRecordingHeap == NULL || mRecordHeapFd < 0) { |
| ALOGE("ERR(%s): mGetMemoryCb(mRecordingHeap(%d), size(%d) fail [Heap %p, Fd %d]",\ |
| __func__, REC_BUF_CNT, sizeof(struct addrs), mRecordingHeap, mRecordHeapFd); |
| return false; |
| } |
| #else |
| mRecordingHeap = mGetMemoryCb(-1, sizeof(struct addrs), REC_BUF_CNT, 0); |
| if (mRecordingHeap == NULL) { |
| ALOGE("ERR(%s): mGetMemoryCb(mRecordingHeap(%d), size(%d) fail [Heap %p]",\ |
| __func__, REC_BUF_CNT, sizeof(struct addrs), mRecordingHeap); |
| return false; |
| } |
| #endif |
| |
| for (int i = 0; i < REC_BUF_CNT; i++) { |
| #ifdef BOARD_USE_MHB_ION |
| for (int j = 0; j < REC_PLANE_CNT; j++) { |
| if (mRecordDstHeap[i][j] != NULL) { |
| mRecordDstHeap[i][j]->release(mRecordDstHeap[i][j]); |
| mRecordDstHeap[i][j] = 0; |
| mRecordDstHeapFd[i][j] = -1; |
| } |
| } |
| |
| mRecordDstHeap[i][0] = mGetMemoryCb(-1, framePlaneSize1, 1, &(mRecordDstHeapFd[i][0])); |
| mRecordDstHeap[i][1] = mGetMemoryCb(-1, framePlaneSize2, 1, &(mRecordDstHeapFd[i][1])); |
| ALOGV("DEBUG(%s): mRecordDstHeap[%d][0] adr(%p), fd(%d)", __func__, i, mRecordDstHeap[i][0]->data, mRecordDstHeapFd[i][0]); |
| ALOGV("DEBUG(%s): mRecordDstHeap[%d][1] adr(%p), fd(%d)", __func__, i, mRecordDstHeap[i][1]->data, mRecordDstHeapFd[i][1]); |
| |
| if (mRecordDstHeap[i][0] == NULL || mRecordDstHeapFd[i][0] <= 0 || |
| mRecordDstHeap[i][1] == NULL || mRecordDstHeapFd[i][1] <= 0) { |
| ALOGE("ERR(%s): mGetMemoryCb(mRecordDstHeap[%d] size(%d/%d) fail",\ |
| __func__, i, framePlaneSize1, framePlaneSize2); |
| goto error; |
| } |
| |
| #ifdef NOTDEFINED |
| if (mRecordDstHeap[i][j] == NULL) { |
| ALOGE("ERR(%s): mGetMemoryCb(mRecordDstHeap[%d][%d], size(%d) fail",\ |
| __func__, i, j, framePlaneSize); |
| goto error; |
| } |
| #endif |
| #else |
| freeMem(&mRecordingDstBuf[i]); |
| |
| mRecordingDstBuf[i].size.extS[0] = framePlaneSize1; |
| mRecordingDstBuf[i].size.extS[1] = framePlaneSize2; |
| |
| if (allocMem(mIonCameraClient, &mRecordingDstBuf[i], ((1 << 1) | 1)) == false) { |
| ALOGE("ERR(%s):allocMem(mRecordingDstBuf() fail", __func__); |
| goto error; |
| } |
| #endif |
| } |
| |
| ALOGD("DEBUG(%s): %dx%d, frame plane (%d/%d)x%d", __func__, |
| ALIGN(mVideoSize.width, 16), ALIGN(mVideoSize.height, 2), framePlaneSize1, framePlaneSize2, REC_BUF_CNT); |
| |
| return true; |
| |
| error: |
| if (mRecordingHeap == NULL) { |
| mRecordingHeap->release(mRecordingHeap); |
| mRecordingHeap = NULL; |
| } |
| |
| for (int i = 0; i < REC_BUF_CNT; i++) { |
| for (int j = 0; j < REC_PLANE_CNT; j++) { |
| if (mRecordDstHeap[i][j] != NULL) { |
| mRecordDstHeap[i][j]->release(mRecordDstHeap[i][j]); |
| mRecordDstHeap[i][j] = 0; |
| } |
| } |
| |
| freeMem(&mRecordingDstBuf[i]); |
| } |
| |
| return false; |
| } |
| |
| bool SecCameraHardware::allocateRecordingSnapshotHeap() |
| { |
| /* init jpeg heap */ |
| if (mJpegHeap) { |
| mJpegHeap->release(mJpegHeap); |
| mJpegHeap = NULL; |
| } |
| |
| #ifdef BOARD_USE_MHB_ION |
| int jpegHeapFd = -1; |
| mJpegHeap = mGetMemoryCb(-1, mRecordingPictureFrameSize, 1, jpegHeapFd); |
| if (mJpegHeap == NULL || jpegHeapFd < 0) { |
| ALOGE("allocateRecordingSnapshotHeap: error, fail to create jpeg heap"); |
| return UNKNOWN_ERROR; |
| } |
| #else |
| mJpegHeap = mGetMemoryCb(-1, mRecordingPictureFrameSize, 1, 0); |
| if (mJpegHeap == NULL) { |
| ALOGE("allocateRecordingSnapshotHeap: error, fail to create jpeg heap"); |
| return UNKNOWN_ERROR; |
| } |
| #endif |
| |
| ALOGD("allocateRecordingSnapshotHeap: jpeg %dx%d, size %d", |
| mPreviewSize.width, mPreviewSize.height, mPreviewFrameSize); |
| |
| return true; |
| } |
| |
| status_t SecCameraHardware::nativeStartRecording(void) |
| { |
| ALOGD("nativeStartRecording E"); |
| #ifdef NOTDEFINED |
| if (mMirror) { |
| nativeSetParameters(CAM_CID_HFLIP, 1, 0); |
| nativeSetParameters(CAM_CID_HFLIP, 1, 1); |
| } else { |
| nativeSetParameters(CAM_CID_HFLIP, 0, 0); |
| nativeSetParameters(CAM_CID_HFLIP, 0, 1); |
| } |
| |
| uint32_t recordingTotalFrameSize; |
| mFimc1.querybuf(&recordingTotalFrameSize); |
| if (recordingTotalFrameSize == 0) { |
| ALOGE("nativeStartPreview: error, mFimc1.querybuf"); |
| return UNKNOWN_ERROR; |
| } |
| |
| if (!allocateRecordingHeap()) { |
| ALOGE("nativeStartRecording: error, allocateRecordingHeap"); |
| return NO_MEMORY; |
| } |
| |
| for (int i = 0; i < REC_BUF_CNT; i++) { |
| err = mFimc1.qbuf(i); |
| CHECK_ERR_N(err, ("nativeStartRecording: error, mFimc1.qbuf(%d)", i)); |
| } |
| |
| err = mFimc1.stream(true); |
| CHECK_ERR_N(err, ("nativeStartRecording: error, mFimc1.stream")); |
| #endif |
| ALOGD("nativeStartRecording X"); |
| return NO_ERROR; |
| } |
| |
| /* for zoom recording */ |
| status_t SecCameraHardware::nativeStartRecordingZoom(void) |
| { |
| int err; |
| Mutex::Autolock lock(mNativeRecordLock); |
| |
| ALOGD("nativeStartRecordingZoom E (%d/%d)", mVideoSize.width, mVideoSize.height); |
| |
| /* 1. init zoom size info */ |
| mRecordZoomRect.x = 0; |
| mRecordZoomRect.y = 0; |
| mRecordZoomRect.w = mVideoSize.width; |
| mRecordZoomRect.h = mVideoSize.height; |
| |
| /* 2. init buffer var src and dst */ |
| mInitRecSrcQ(); |
| mInitRecDstBuf(); |
| |
| /* 3. alloc MHB for recording dst */ |
| if (!allocateRecordingHeap()) { |
| ALOGE("nativeStartPostRecording: error, allocateRecordingHeap"); |
| goto destroyMem; |
| } |
| |
| ALOGD("nativeStartRecordingZoom X"); |
| return NO_ERROR; |
| |
| destroyMem: |
| mInitRecSrcQ(); |
| mInitRecDstBuf(); |
| return UNKNOWN_ERROR; |
| } |
| |
| #ifdef NOTDEFINED |
| int SecCameraHardware::nativeGetRecording() |
| { |
| int index; |
| phyaddr_t y, cbcr; |
| int err, retries = 3; |
| |
| retry: |
| #ifndef FPOLLING |
| err = mFimc1.polling(isFactoryTest(), true); |
| #endif |
| if (CC_UNLIKELY(err <= 0)) { |
| if (mFimc1.getStreamStatus()) { |
| if (!err && (retries > 0)) { |
| ALOGW("nativeGetRecording: warning, wait for input (%d)", retries); |
| usleep(300000); |
| retries--; |
| goto retry; |
| } |
| ALOGE("nativeGetRecording: error, mFimc1.polling err=%d cnt=%d", err, retries); |
| } else { |
| ALOGV("nativeGetRecording: stop getting a frame"); |
| } |
| return UNKNOWN_ERROR; |
| } |
| |
| index = mFimc1.dqbuf(); |
| CHECK_ERR_N(index, ("nativeGetRecording: error, mFimc1.dqbuf")); |
| |
| /* get fimc capture physical addr */ |
| err = mFimc1.getYuvPhyaddr(index, &y, &cbcr); |
| CHECK_ERR_N(err, ("nativeGetRecording: error, mFimc1.getYuvPhyaddr")); |
| |
| Mutex::Autolock lock(mNativeRecordLock); |
| |
| if (!mRecordingHeap) |
| return NO_MEMORY; |
| |
| struct record_heap *heap = (struct record_heap *)mRecordingHeap->data; |
| heap[index].type = kMetadataBufferTypeCameraSource; |
| heap[index].y = y; |
| heap[index].cbcr = cbcr; |
| heap[index].buf_index = index; |
| |
| return index; |
| } |
| |
| int SecCameraHardware::nativeReleaseRecordingFrame(int index) |
| { |
| return mFimc1.qbuf(index); |
| } |
| |
| int SecCameraHardware::nativeReleasePostRecordingFrame(int index) |
| { |
| return NO_ERROR; |
| } |
| void SecCameraHardware::nativeStopPostRecording() |
| { |
| Mutex::Autolock lock(mNativeRecordLock); |
| |
| ALOGD("nativeStopPostRecording EX"); |
| } |
| #endif |
| |
| void SecCameraHardware::nativeStopRecording() |
| { |
| Mutex::Autolock lock(mNativeRecordLock); |
| |
| mInitRecSrcQ(); |
| mInitRecDstBuf(); |
| |
| ALOGD("nativeStopRecording EX"); |
| } |
| |
| bool SecCameraHardware::getCropRect(unsigned int src_w, unsigned int src_h, unsigned int dst_w, unsigned int dst_h, unsigned int *crop_x, unsigned int *crop_y, unsigned int *crop_w, unsigned int *crop_h, int align_w, int align_h, int zoom) |
| { |
| bool flag = true; |
| *crop_w = src_w; |
| *crop_h = src_h; |
| |
| if (src_w == 0 || src_h == 0 || dst_w == 0 || dst_h == 0) { |
| ALOGE("ERR(%s):width or height valuse is 0, src(%dx%d), dst(%dx%d)", |
| __func__, src_w, src_h, dst_w, dst_h); |
| return false; |
| } |
| |
| /* Calculation aspect ratio */ |
| if (src_w != dst_w |
| || src_h != dst_h) { |
| float src_ratio = 1.0f; |
| float dst_ratio = 1.0f; |
| |
| /* ex : 1024 / 768 */ |
| src_ratio = (float)src_w / (float)src_h; |
| |
| /* ex : 352 / 288 */ |
| dst_ratio = (float)dst_w / (float)dst_h; |
| |
| if (dst_ratio <= src_ratio) { |
| /* shrink w */ |
| *crop_w = src_h * dst_ratio; |
| *crop_h = src_h; |
| } else { |
| /* shrink h */ |
| *crop_w = src_w; |
| *crop_h = src_w / dst_ratio; |
| } |
| } |
| |
| flag = getRectZoomAlign(src_w, src_h, dst_w, dst_h, crop_x, crop_y, crop_w, crop_h, align_w, align_h,zoom); |
| if(false == flag) { |
| ALOGE("ERR(%s):src_w = %u src_h = %u dst_w = %u dst_h = %u crop_x = %u crop_y = %u crop_w = %u crop_h = %u align_w = %d align_h = %d zoom = %d", __func__, src_w, src_h, dst_w, dst_h, *crop_x, *crop_y, *crop_w, *crop_h, align_w, align_h,zoom); |
| } |
| |
| return true; |
| } |
| |
| bool SecCameraHardware::getRectZoomAlign(unsigned int src_w, unsigned int src_h, unsigned int dst_w, unsigned int dst_h, unsigned int *crop_x, unsigned int *crop_y, unsigned int *crop_w, unsigned int *crop_h, int align_w, int align_h, int zoom) |
| { |
| int x = 0; |
| int y = 0; |
| |
| if (zoom != 0) { |
| /* calculation zoom */ |
| float zoomLevel; |
| zoomLevel = (zoom); |
| *crop_w = (*crop_w * 10 / zoomLevel); |
| *crop_h = (*crop_h * 10 / zoomLevel); |
| } |
| |
| /* Alignment by desired size */ |
| unsigned int w_remain = (*crop_w & (align_w - 1)); |
| if (w_remain != 0) { |
| if ( (unsigned int)(align_w >> 1) <= w_remain |
| && (unsigned int)(*crop_w + (align_w - w_remain)) <= src_w) { |
| *crop_w += (align_w - w_remain); |
| } |
| else |
| *crop_w -= w_remain; |
| } |
| |
| unsigned int h_remain = (*crop_h & (align_h - 1)); |
| if (h_remain != 0) { |
| if ( (unsigned int)(align_h >> 1) <= h_remain |
| && (unsigned int)(*crop_h + (align_h - h_remain)) <= src_h) { |
| *crop_h += (align_h - h_remain); |
| } |
| else |
| *crop_h -= h_remain; |
| } |
| |
| x = ((int)src_w - (int)*crop_w) >> 1; |
| y = ((int)src_h - (int)*crop_h) >> 1; |
| |
| if (x < 0 || y < 0) { |
| ALOGE("ERR(%s):crop size too big (%u, %u, %u, %u)", |
| __func__, *crop_x, *crop_y, *crop_w, *crop_h); |
| return false; |
| } |
| |
| *crop_x = x; |
| *crop_y = y; |
| |
| return true; |
| } |
| |
| status_t SecCameraHardware::nativeCSCPreview(int index, int type) |
| { |
| ExynosBuffer dstBuf; |
| char *dstAdr = NULL; |
| dstAdr = (char *)mPreviewHeap->data; |
| dstAdr += (index * mPreviewFrameSize); |
| |
| if (mFimc1CSC) { |
| /* set zoom info */ |
| mPreviewZoomRect.w = ALIGN_DOWN((mFLiteSize.width * 10 / mZoomValue), 2); |
| mPreviewZoomRect.h = ALIGN_DOWN((mFLiteSize.height * 10 / mZoomValue), 2); |
| |
| mPreviewZoomRect.x = ALIGN_DOWN(((mFLiteSize.width - mPreviewZoomRect.w) / 2), 2); |
| mPreviewZoomRect.y = ALIGN_DOWN(((mFLiteSize.height - mPreviewZoomRect.h) / 2), 2); |
| |
| /* src : FLite */ |
| csc_set_src_format(mFimc1CSC, |
| mFLiteSize.width, mFLiteSize.height, |
| mPreviewZoomRect.x, mPreviewZoomRect.y, |
| mPreviewZoomRect.w, mPreviewZoomRect.h, |
| V4L2_PIX_2_HAL_PIXEL_FORMAT(mFliteNode.format), |
| 0); |
| |
| if (type == CAMERA_HEAP_POSTVIEW) { |
| csc_set_src_buffer(mFimc1CSC, (void **)mPictureBufDummy[0].virt.extP, CSC_MEMORY_USERPTR); |
| } else { |
| csc_set_src_buffer(mFimc1CSC, (void **)mFliteNode.buffer[index].virt.extP, CSC_MEMORY_USERPTR); |
| } |
| |
| /* mSaveDump("/data/camera_preview%d.yuv", &mFliteNode.buffer[index], index); */ |
| |
| int halPixelFormat = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL; |
| |
| /* dst : GRALLOC */ |
| csc_set_dst_format(mFimc1CSC, |
| mPreviewSize.width, mPreviewSize.height, |
| 0, 0, |
| mPreviewSize.width, mPreviewSize.height, |
| halPixelFormat, |
| 0); |
| |
| dstBuf.fd.extFd[0] = mPreviewHeapFd; |
| dstBuf.virt.extP[0] = dstAdr; |
| dstBuf.size.extS[0] = mPreviewSize.width * mPreviewSize.height; |
| dstBuf.virt.extP[1] = dstBuf.virt.extP[0] + dstBuf.size.extS[0]; |
| dstBuf.size.extS[1] = mPreviewSize.width * mPreviewSize.height / 2; |
| |
| csc_set_dst_buffer(mFimc1CSC, (void **) dstBuf.virt.extP, CSC_MEMORY_USERPTR); |
| |
| mFimc1CSCLock.lock(); |
| if (csc_convert(mFimc1CSC) != 0) { |
| ALOGE("ERR(%s):csc_convert(mFimc1CSC) fail", __func__); |
| mFimc1CSCLock.unlock(); |
| return false; |
| } |
| mFimc1CSCLock.unlock(); |
| } |
| return true; |
| } |
| |
| status_t SecCameraHardware::nativeCSCRecording(rec_src_buf_t *srcBuf, int dstIdx) |
| { |
| Mutex::Autolock lock(mNativeRecordLock); |
| |
| /* csc start flite(s) -> fimc1 -> callback(d) */ |
| if (mFimc2CSC) { |
| struct addrs *addrs; |
| bool flag; |
| /* set zoom info */ |
| flag = getCropRect(mFLiteSize.width, mFLiteSize.height, mVideoSize.width, mVideoSize.height, &mRecordZoomRect.x, &mRecordZoomRect.y, &mRecordZoomRect.w, &mRecordZoomRect.h, 2, 2, mZoomValue); |
| if(false == flag) { |
| ALOGE("ERR(%s):mFLiteSize.width = %u mFLiteSize.height = %u mVideoSize.width = %u mVideoSize.height = %u ", __func__, mFLiteSize.width, mFLiteSize.height, mVideoSize.width, mVideoSize.height); |
| ALOGE("ERR(%s):Recording CropRect failed X = %u Y = %u W = %u H = %u ", __func__, mRecordZoomRect.x, mRecordZoomRect.y, mRecordZoomRect.w, mRecordZoomRect.h); |
| } |
| |
| #ifdef DEBUG_RECORDING |
| ALOGD("DEBUG(%s) (%d): src(%d,%d,%d,%d,%d,%d), dst(%d,%d) %d", __func__, __LINE__ |
| , mFLiteSize.width |
| , mFLiteSize.height |
| , mRecordZoomRect.x |
| , mRecordZoomRect.y |
| , mRecordZoomRect.w |
| , mRecordZoomRect.h |
| , mVideoSize.width |
| , mVideoSize.height |
| , dstIdx |
| ); |
| #endif |
| /* src : FLite */ |
| csc_set_src_format(mFimc2CSC, |
| mFLiteSize.width, mFLiteSize.height, |
| mRecordZoomRect.x, mRecordZoomRect.y, |
| mRecordZoomRect.w, mRecordZoomRect.h, |
| V4L2_PIX_2_HAL_PIXEL_FORMAT(mFliteNode.format), |
| 0); |
| |
| csc_set_src_buffer(mFimc2CSC, (void **)srcBuf->buf->fd.extFd, CSC_MEMORY_DMABUF); |
| //csc_set_src_buffer(mFimc2CSC, (void **)srcBuf->buf->virt.extP, CSC_MEMORY_USERPTR); |
| |
| /* dst : MHB(callback */ |
| csc_set_dst_format(mFimc2CSC, |
| mVideoSize.width, mVideoSize.height, |
| 0, 0, mVideoSize.width, mVideoSize.height, |
| V4L2_PIX_2_HAL_PIXEL_FORMAT(mRecordingFormat), |
| /* HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP, */ |
| 0); |
| |
| ExynosBuffer dstBuf; |
| getAlignedYUVSize(mRecordingFormat, mVideoSize.width, mVideoSize.height, &dstBuf); |
| for (int i = 0; i < REC_PLANE_CNT; i++) { |
| #if defined(ALLOCATION_REC_BUF_BY_MEM_CB) |
| dstBuf.virt.extP[i] = (char *)mRecordDstHeap[dstIdx][i]->data; |
| dstBuf.fd.extFd[i] = mRecordDstHeapFd[dstIdx][i]; |
| #else |
| dstBuf.virt.extP[i] = (char *)mRecordingDstBuf[dstIdx].virt.extP[i]; |
| dstBuf.fd.extFd[i] = mRecordingDstBuf[dstIdx].fd.extFd[i]; |
| #endif |
| } |
| |
| #ifdef DEBUG_RECORDING |
| ALOGD("DEBUG(%s) (%d): dst(%d,%d,%p,%p,%d,%d) index(%d)", __func__, __LINE__ |
| , dstBuf.fd.extFd[0] |
| , dstBuf.fd.extFd[1] |
| , dstBuf.virt.extP[0] |
| , dstBuf.virt.extP[1] |
| , dstBuf.size.extS[0] |
| , dstBuf.size.extS[1] |
| , dstIdx |
| ); |
| #endif |
| csc_set_dst_buffer(mFimc2CSC, (void **)dstBuf.fd.extFd, CSC_MEMORY_DMABUF); |
| |
| mFimc2CSCLock.lock(); |
| if (csc_convert(mFimc2CSC) != 0) { |
| ALOGE("ERR(%s):csc_convert(mFimc2CSC) fail", __func__); |
| mFimc2CSCLock.unlock(); |
| return false; |
| } |
| mFimc2CSCLock.unlock(); |
| |
| addrs = (struct addrs *)mRecordingHeap->data; |
| addrs[dstIdx].type = kMetadataBufferTypeCameraSource; |
| addrs[dstIdx].fd_y = (unsigned int)dstBuf.fd.extFd[0]; |
| addrs[dstIdx].fd_cbcr = (unsigned int)dstBuf.fd.extFd[1]; |
| addrs[dstIdx].buf_index = dstIdx; |
| /* ALOGV("DEBUG(%s): After CSC Camera Meta index %d fd(%d, %d)", __func__, dstIdx, addrs[dstIdx].fd_y, addrs[dstIdx].fd_cbcr); */ |
| /* mSaveDump("/data/camera_recording%d.yuv", &dstBuf, dstIdx); */ |
| } else { |
| ALOGE("ERR(%s): mFimc2CSC == NULL", __func__); |
| return false; |
| } |
| return true; |
| } |
| |
| status_t SecCameraHardware::nativeCSCCapture(ExynosBuffer *srcBuf, ExynosBuffer *dstBuf) |
| { |
| if (mFimc1CSC) { |
| /* set zoom info */ |
| mPictureZoomRect.w = ALIGN_DOWN((mFLiteCaptureSize.width * 10 / mZoomValue), 2); |
| mPictureZoomRect.h = ALIGN_DOWN((mFLiteCaptureSize.height * 10 / mZoomValue), 2); |
| |
| mPictureZoomRect.x = ALIGN_DOWN(((mFLiteCaptureSize.width - mPictureZoomRect.w) / 2), 2); |
| mPictureZoomRect.y = ALIGN_DOWN(((mFLiteCaptureSize.height - mPictureZoomRect.h) / 2), 2); |
| |
| #ifdef DEBUG_CAPTURE |
| ALOGD("DEBUG(%s) (%d): (%d, %d), (%d, %d), (%d, %d, %d, %d)", __func__, __LINE__ |
| , mFLiteCaptureSize.width |
| , mFLiteCaptureSize.height |
| , mPictureSize.width |
| , mPictureSize.height |
| , mPictureZoomRect.x |
| , mPictureZoomRect.y |
| , mPictureZoomRect.w |
| , mPictureZoomRect.h |
| ); |
| #endif |
| /* src : FLite */ |
| csc_set_src_format(mFimc1CSC, |
| mFLiteCaptureSize.width, mFLiteCaptureSize.height, |
| mPictureZoomRect.x, mPictureZoomRect.y, |
| mPictureZoomRect.w, mPictureZoomRect.h, |
| V4L2_PIX_2_HAL_PIXEL_FORMAT(mFliteNode.format), |
| 0); |
| |
| csc_set_src_buffer(mFimc1CSC, (void **)srcBuf->virt.extP, CSC_MEMORY_USERPTR); |
| |
| /* dst : buffer */ |
| csc_set_dst_format(mFimc1CSC, |
| mPictureSize.width, mPictureSize.height, |
| 0, 0, mPictureSize.width, mPictureSize.height, |
| V4L2_PIX_2_HAL_PIXEL_FORMAT(mFliteNode.format), |
| 0); |
| |
| csc_set_dst_buffer(mFimc1CSC, (void **)dstBuf->fd.extFd, CSC_MEMORY_DMABUF); |
| |
| mFimc1CSCLock.lock(); |
| if (csc_convert(mFimc1CSC) != 0) { |
| ALOGE("ERR(%s):csc_convert(mFimc1CSC) fail", __func__); |
| mFimc1CSCLock.unlock(); |
| return false; |
| } |
| mFimc1CSCLock.unlock(); |
| /* mSaveDump("/data/camera_recording%d.yuv", &dstBuf, dstIdx); */ |
| } else { |
| ALOGE("ERR(%s): mFimc1CSC == NULL", __func__); |
| return false; |
| } |
| return true; |
| } |
| |
| status_t SecCameraHardware::nativeCSCRecordingCapture(ExynosBuffer *srcBuf, ExynosBuffer *dstBuf) |
| { |
| if (mFimc1CSC) { |
| ALOGD("DEBUG(%s) (%d) src : mFLiteSize(%d x %d), mPreviewZoomRect(%d, %d, %d, %d)", __FUNCTION__, __LINE__, |
| mFLiteSize.width, |
| mFLiteSize.height, |
| mPreviewZoomRect.x, |
| mPreviewZoomRect.y, |
| mPreviewZoomRect.w, |
| mPreviewZoomRect.h); |
| |
| ALOGD("DEBUG(%s) (%d) dst : (%d x %d)", __FUNCTION__, __LINE__, |
| mPreviewSize.width, mPreviewSize.height); |
| |
| int dstW = mPreviewSize.width; |
| int dstH = mPreviewSize.height; |
| |
| /* src : FLite */ |
| csc_set_src_format(mFimc1CSC, |
| mFLiteSize.width, mFLiteSize.height, |
| mPreviewZoomRect.x, mPreviewZoomRect.y, |
| mPreviewZoomRect.w, mPreviewZoomRect.h, |
| V4L2_PIX_2_HAL_PIXEL_FORMAT(mFliteNode.format), |
| 0); |
| |
| csc_set_src_buffer(mFimc1CSC, (void **)srcBuf->virt.extP, CSC_MEMORY_USERPTR); |
| |
| /* dst : buffer */ |
| csc_set_dst_format(mFimc1CSC, |
| dstW, dstH, |
| 0, 0, dstW, dstH, |
| V4L2_PIX_2_HAL_PIXEL_FORMAT(mFliteNode.format), |
| 0); |
| |
| csc_set_dst_buffer(mFimc1CSC, (void **)dstBuf->fd.extFd, CSC_MEMORY_DMABUF); |
| |
| mFimc1CSCLock.lock(); |
| if (csc_convert(mFimc1CSC) != 0) { |
| ALOGE("ERR(%s):csc_convert(mFimc1CSC) fail", __func__); |
| mFimc1CSCLock.unlock(); |
| return INVALID_OPERATION; |
| } |
| mFimc1CSCLock.unlock(); |
| /* mSaveDump("/data/camera_recording%d.yuv", &dstBuf, dstIdx); */ |
| } else { |
| ALOGE("ERR(%s): mFimc1CSC == NULL", __func__); |
| return INVALID_OPERATION; |
| } |
| return NO_ERROR; |
| } |
| |
| int SecCameraHardware::nativegetWBcustomX() |
| { |
| int x_value, err; |
| |
| err = mFlite.gctrl(V4L2_CID_CAMERA_WB_CUSTOM_X, &x_value); |
| CHECK_ERR(err, ("nativegetWBcustomX: error [%d]", x_value)); |
| |
| ALOGV("%s res[%d]", __func__, x_value); |
| |
| return x_value; |
| } |
| |
| int SecCameraHardware::nativegetWBcustomY() |
| { |
| int y_value, err; |
| |
| err = mFlite.gctrl(V4L2_CID_CAMERA_WB_CUSTOM_Y, &y_value); |
| CHECK_ERR(err, ("nativegetWBcustomY: error [%d]", y_value)); |
| |
| ALOGV("%s res[%d]", __func__, y_value); |
| |
| return y_value; |
| } |
| |
| |
| |
| status_t SecCameraHardware::nativeSetZoomRatio(int value) |
| { |
| /* Calculation of the crop information */ |
| int Zoom = value + 10; |
| ALOGD("%s: Zoomlevel = %d, Zoom coeficient = %d", __FUNCTION__, value, Zoom); |
| |
| mZoomValue = Zoom; |
| |
| /* ALOGD("x = %d, y = %d, w = %d, h = %d", mPreviewZoomRect.x, mPreviewZoomRect.y, mPreviewZoomRect.w, mPreviewZoomRect.h); */ |
| |
| return NO_ERROR; |
| } |
| |
| #ifdef NOTDEFINED |
| int SecCameraHardware::nativePostPreview(int index) |
| { |
| /* ALOGD("x = %d, y = %d, w = %d, h = %d", mPreviewZoomRect.x, mPreviewZoomRect.y, mPreviewZoomRect.w, mPreviewZoomRect.h); */ |
| mPreviewZoomRect.w = mCameraSize.width * 10 / mZoomValue; |
| mPreviewZoomRect.h = mCameraSize.height * 10 / mZoomValue; |
| |
| if (mPreviewZoomRect.w % 2) |
| mPreviewZoomRect.w -= 1; |
| |
| if (mPreviewZoomRect.h % 2) |
| mPreviewZoomRect.h -= 1; |
| |
| mPreviewZoomRect.x = (mCameraSize.width - mPreviewZoomRect.w) / 2; |
| mPreviewZoomRect.y = (mCameraSize.height - mPreviewZoomRect.h) / 2; |
| |
| if (mPreviewZoomRect.x % 2) |
| mPreviewZoomRect.x -= 1; |
| |
| if (mPreviewZoomRect.y % 2) |
| mPreviewZoomRect.y -= 1; |
| |
| int paddr[3]; |
| paddr[0] = mPostPhyAddr + mPreviewFrameSize * index; |
| |
| if (mPreviewFormat == CAM_PIXEL_FORMAT_YVU420P) { |
| paddr[2] = paddr[0] + mPreviewSize.width * mPreviewSize.height; |
| paddr[1] = paddr[2] + mPreviewSize.width * mPreviewSize.height / 4; |
| } else if (mPreviewFormat == CAM_PIXEL_FORMAT_YUV420SP) { |
| paddr[1] = paddr[0] + mPreviewSize.width * mPreviewSize.height; |
| paddr[2] = 0; |
| } else { |
| ALOGE("unsupported preview format (%c%c%c%c)", mPreviewFormat, |
| mPreviewFormat >> 8, mPreviewFormat >> 16, mPreviewFormat >> 24); |
| return BAD_VALUE; |
| } |
| |
| return NO_ERROR; |
| } |
| |
| int SecCameraHardware::nativePostRecord(int index) |
| { |
| int err; |
| |
| Mutex::Autolock lock(mNativeRecordLock); |
| |
| mRecordZoomRect.w = mCameraSize.width * 10 / mZoomValue; |
| mRecordZoomRect.h = mCameraSize.height * 10 / mZoomValue; |
| |
| if (mRecordZoomRect.w % 2) |
| mRecordZoomRect.w -= 1; |
| |
| if (mRecordZoomRect.h % 2) |
| mRecordZoomRect.h -= 1; |
| |
| mRecordZoomRect.x = (mCameraSize.width - mRecordZoomRect.w) / 2; |
| mRecordZoomRect.y = (mCameraSize.height - mRecordZoomRect.h) / 2; |
| |
| if (mRecordZoomRect.x % 2) |
| mRecordZoomRect.x -= 1; |
| |
| if (mRecordZoomRect.y % 2) |
| mRecordZoomRect.y -= 1; |
| |
| int paddr[3]; |
| paddr[0] = mPostRecPhyAddr[index]; |
| paddr[1] = paddr[0] + ALIGN(mVideoSize.width * mVideoSize.height, 64*1024); |
| |
| struct record_heap *heap = (struct record_heap *)mRecordingHeap->data; |
| heap[index].type = kMetadataBufferTypeCameraSource; |
| heap[index].y = paddr[0]; |
| heap[index].cbcr = paddr[1]; |
| heap[index].buf_index = index; |
| |
| return NO_ERROR; |
| } |
| #endif |
| |
| bool SecCameraHardware::nativeGetRecordingJpeg(ExynosBuffer *yuvBuf, uint32_t width, uint32_t height) |
| { |
| bool ret = false; |
| |
| Exif exif(mCameraId); |
| |
| uint8_t *outBuf; |
| int jpegSize = 0; |
| int thumbSize = 0; |
| uint32_t exifSize = 0; |
| |
| ExynosBuffer jpegBuf; |
| jpegBuf.size.extS[0] = width * height * 2; |
| |
| ExynosBuffer exifBuf; |
| exifBuf.size.extS[0] = EXIF_MAX_LEN; |
| |
| ExynosBuffer thumbnailYuvBuf; |
| thumbnailYuvBuf.size.extS[0] = mThumbnailSize.width * mThumbnailSize.height * 2; |
| |
| bool thumbnail = false; |
| |
| /* Thumbnail */ |
| LOG_PERFORMANCE_START(1); |
| |
| /* use for both thumbnail and main jpeg */ |
| if (allocMem(mIonCameraClient, &jpegBuf, 1 << 1) == false) { |
| ALOGE("ERR(%s):(%d)allocMem(jpegBuf) fail", __func__, __LINE__); |
| goto jpeg_encode_done; |
| } |
| |
| if (mThumbnailSize.width == 0 || mThumbnailSize.height == 0) |
| goto encode_jpeg; |
| |
| if (allocMem(mIonCameraClient, &thumbnailYuvBuf, 1 << 1) == false) { |
| ALOGE("ERR(%s):(%d)allocMem(thumbnailYuvBuf) fail", __func__, __LINE__); |
| goto encode_jpeg; |
| } |
| |
| LOG_PERFORMANCE_START(3); |
| |
| scaleDownYuv422((uint8_t *)yuvBuf->virt.extP[0], (int)width, (int)height, |
| (uint8_t *)thumbnailYuvBuf.virt.extP[0], (int)mThumbnailSize.width, (int)mThumbnailSize.height); |
| |
| LOG_PERFORMANCE_END(3, "scaleDownYuv422"); |
| |
| if (this->EncodeToJpeg(&thumbnailYuvBuf, &jpegBuf, |
| mThumbnailSize.width, mThumbnailSize.height, |
| CAM_PIXEL_FORMAT_YUV422I, |
| &thumbSize, |
| JPEG_THUMBNAIL_QUALITY) != NO_ERROR) { |
| ALOGE("ERR(%s):(%d)EncodeToJpeg", __func__, __LINE__); |
| goto encode_jpeg; |
| } |
| |
| outBuf = (uint8_t *)jpegBuf.virt.extP[0]; |
| |
| thumbnail = true; |
| |
| LOG_PERFORMANCE_END(1, "encode thumbnail"); |
| |
| encode_jpeg: |
| /* EXIF */ |
| setExifChangedAttribute(); |
| |
| if (allocMem(mIonCameraClient, &exifBuf, 1 << 1) == false) { |
| ALOGE("ERR(%s):(%d)allocMem(exifBuf) fail", __func__, __LINE__); |
| goto jpeg_encode_done; |
| } |
| |
| if (CC_LIKELY(thumbnail)) |
| exifSize = exif.make(exifBuf.virt.extP[0], &mExifInfo, exifBuf.size.extS[0], outBuf, thumbSize); |
| else |
| exifSize = exif.make(exifBuf.virt.extP[0], &mExifInfo); |
| |
| if (CC_UNLIKELY(!exifSize)) { |
| ALOGE("getJpeg: error, fail to make EXIF"); |
| goto jpeg_encode_done; |
| } |
| |
| /* Jpeg */ |
| LOG_PERFORMANCE_START(2); |
| |
| if (this->EncodeToJpeg(yuvBuf, &jpegBuf, |
| width, height, |
| CAM_PIXEL_FORMAT_YUV422I, |
| &jpegSize, |
| mJpegQuality) != NO_ERROR) { |
| ALOGE("ERR(%s):(%d)EncodeToJpeg", __func__, __LINE__); |
| goto jpeg_encode_done; |
| } |
| |
| outBuf = (uint8_t *)jpegBuf.virt.extP[0]; |
| |
| LOG_PERFORMANCE_END(2, "encode jpeg"); |
| |
| LOG_PERFORMANCE_START(4); |
| mRecordingPictureFrameSize = jpegSize + exifSize; |
| /* picture frame size is should be calculated before call allocateSnapshotHeap */ |
| if (!allocateRecordingSnapshotHeap()) { |
| ALOGE("getJpeg: error, allocateSnapshotHeap"); |
| return UNKNOWN_ERROR; |
| } |
| |
| memcpy(mJpegHeap->data, outBuf, 2); |
| memcpy((uint8_t *)mJpegHeap->data + 2, exifBuf.virt.extP[0], exifSize); |
| memcpy((uint8_t *)mJpegHeap->data + 2 + exifSize, outBuf + 2, jpegSize - 2); |
| LOG_PERFORMANCE_END(4, "jpeg + exif"); |
| |
| ret = true; |
| |
| jpeg_encode_done: |
| |
| freeMem(&thumbnailYuvBuf); |
| freeMem(&exifBuf); |
| freeMem(&jpegBuf); |
| |
| return ret; |
| } |
| |
| #if IS_FW_DEBUG |
| int SecCameraHardware::nativeGetDebugAddr(unsigned int *vaddr) |
| { |
| int err; |
| int paddr; |
| *vaddr = 0; |
| |
| err = mFlite.gctrl(V4L2_CID_IS_FW_DEBUG_REGION_ADDR, &paddr); |
| CHECK_ERR_N(err, ("nativeGetDebugAddr: error %d", err)); |
| |
| if (paddr <= 0) { |
| ALOGE("nativeGetDebugAddr V4L2_CID_IS_FW_DEBUG_REGION_ADDR failed.."); |
| return NO_MEMORY; |
| } |
| ALOGD("nativeGetDebugAddr paddr = 0x%x", paddr); |
| |
| m_mem_fd = open(EXYNOS_MEM_DEVICE_DEV_NAME, O_RDWR); |
| if (m_mem_fd < 0) { |
| ALOGE("ERR(%s):Cannot open %s (error : %s)", __func__, EXYNOS_MEM_DEVICE_DEV_NAME, strerror(errno)); |
| return NO_MEMORY; |
| } |
| |
| *vaddr = (unsigned int)mmap(0, FIMC_IS_FW_MMAP_REGION_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, m_mem_fd, paddr); |
| |
| return 0; |
| } |
| #endif |
| |
| #if FRONT_ZSL |
| bool SecCameraHardware::allocateFullPreviewHeap() |
| { |
| if (mFullPreviewHeap) { |
| mFullPreviewHeap->release(mFullPreviewHeap); |
| mFullPreviewHeap = NULL; |
| } |
| |
| mFullPreviewHeap = mGetMemoryCb((int)mFimc1.getfd(), |
| mFullPreviewFrameSize, kBufferZSLCount, 0); |
| if (!mFullPreviewHeap || mFullPreviewHeap->data == MAP_FAILED) { |
| ALOGE("ERR(%s): heap creation fail", __func__); |
| return false; |
| } |
| |
| ALOGD("allocateFullPreviewHeap: %dx%d, frame %dx%d", |
| mPictureSize.width, mPictureSize.height, mFullPreviewFrameSize, kBufferZSLCount); |
| |
| return true; |
| } |
| |
| status_t SecCameraHardware::nativeStartFullPreview(void) |
| { |
| ALOGD("nativeStartFullPreview E"); |
| |
| int err; |
| cam_pixel_format captureFormat = CAM_PIXEL_FORMAT_YUV422I; |
| |
| err = mFimc1.startCapture(&mPictureSize, captureFormat, kBufferZSLCount, 0); |
| CHECK_ERR_N(err, ("nativeStartFullPreview: error, mFimc1.start")); |
| |
| mFimc1.querybuf(&mFullPreviewFrameSize); |
| if (mFullPreviewFrameSize == 0) { |
| ALOGE("nativeStartFullPreview: error, mFimc1.querybuf"); |
| return UNKNOWN_ERROR; |
| } |
| |
| if (!allocateFullPreviewHeap()) { |
| ALOGE("nativeStartFullPreview: error, allocateFullPreviewHeap"); |
| return NO_MEMORY; |
| } |
| |
| for (int i = 0; i < kBufferZSLCount; i++) { |
| err = mFimc1.qbuf(i); |
| CHECK_ERR_N(err, ("nativeStartFullPreview: error, mFimc1.qbuf(%d)", i)); |
| } |
| |
| rawImageMem = new MemoryHeapBase(mFullPreviewFrameSize); |
| |
| err = mFimc1.stream(true); |
| CHECK_ERR_N(err, ("nativeStartFullPreview: error, mFimc1.stream")); |
| |
| ALOGD("nativeStartFullPreview X"); |
| return NO_ERROR; |
| } |
| |
| int SecCameraHardware::nativeGetFullPreview() |
| { |
| int index; |
| phyaddr_t y, cbcr; |
| int err; |
| |
| #ifndef FPOLLING |
| err = mFimc1.polling(isFactoryTest()); |
| #endif |
| CHECK_ERR_N(err, ("nativeGetFullPreview: error, mFimc1.polling")); |
| |
| index = mFimc1.dqbuf(); |
| CHECK_ERR_N(index, ("nativeGetFullPreview: error, mFimc1.dqbuf")); |
| |
| mJpegIndex = index; |
| |
| return index; |
| } |
| |
| int SecCameraHardware::nativeReleaseFullPreviewFrame(int index) |
| { |
| return mFimc1.qbuf(index); |
| } |
| |
| void SecCameraHardware::nativeStopFullPreview() |
| { |
| if (mFimc1.stream(false) < 0) |
| ALOGE("nativeStopFullPreview X: error, mFimc1.stream(0)"); |
| |
| if (mFullPreviewHeap) { |
| mFullPreviewHeap->release(mFullPreviewHeap); |
| mFullPreviewHeap = NULL; |
| } |
| |
| rawImageMem.clear(); |
| |
| ALOGD("nativeStopFullPreview EX"); |
| } |
| |
| void SecCameraHardware::nativeForceStopFullPreview() |
| { |
| mFimc1.forceStop(); |
| } |
| |
| bool SecCameraHardware::getZSLJpeg() |
| { |
| int ret; |
| |
| ALOGE("%s:: mJpegIndex : %d", __func__, mJpegIndex); |
| |
| memcpy( (unsigned char *)rawImageMem->base(), |
| (unsigned char *)((unsigned int)mFullPreviewHeap->data + mJpegIndex * mFullPreviewFrameSize), |
| mFullPreviewFrameSize ); |
| |
| sp<MemoryHeapBase> thumbnailJpeg; |
| sp<MemoryHeapBase> rawThumbnail; |
| |
| unsigned char *thumb; |
| int thumbSize = 0; |
| |
| bool thumbnail = false; |
| /* Thumbnail */ |
| LOG_PERFORMANCE_START(1); |
| |
| if (mThumbnailSize.width == 0 || mThumbnailSize.height == 0) |
| goto encode_jpeg; |
| |
| rawThumbnail = new MemoryHeapBase(mThumbnailSize.width * mThumbnailSize.height * 2); |
| |
| LOG_PERFORMANCE_START(3); |
| #ifdef USE_HW_SCALER |
| ret = scaleDownYUVByFIMC((unsigned char *)rawImageMem->base(), |
| (int)mPictureSize.width, |
| (int)mPictureSize.height, |
| (unsigned char *)rawThumbnail->base(), |
| (int)mThumbnailSize.width, |
| (int)mThumbnailSize.height, |
| CAM_PIXEL_FORMAT_YUV422I); |
| |
| if (!ret) { |
| ALOGE("Fail to scale down YUV data for thumbnail!\n"); |
| goto encode_jpeg; |
| } |
| #else |
| ret = scaleDownYuv422((unsigned char *)rawImageMem->base(), |
| (int)mPictureSize.width, |
| (int)mPictureSize.height, |
| (unsigned char *)rawThumbnail->base(), |
| (int)mThumbnailSize.width, |
| (int)mThumbnailSize.height); |
| |
| if (!ret) { |
| ALOGE("Fail to scale down YUV data for thumbnail!\n"); |
| goto encode_jpeg; |
| } |
| #endif |
| LOG_PERFORMANCE_END(3, "scaleDownYuv422"); |
| |
| thumbnailJpeg = new MemoryHeapBase(mThumbnailSize.width * mThumbnailSize.height * 2); |
| |
| #ifdef CHG_ENCODE_JPEG |
| ret = EncodeToJpeg((unsigned char*)rawThumbnail->base(), |
| mThumbnailSize.width, |
| mThumbnailSize.height, |
| CAM_PIXEL_FORMAT_YUV422I, |
| (unsigned char*)thumbnailJpeg->base(), |
| &thumbSize, |
| JPEG_THUMBNAIL_QUALITY); |
| |
| if (ret != NO_ERROR) { |
| ALOGE("thumbnail:EncodeToJpeg failed\n"); |
| goto encode_jpeg; |
| } |
| #endif |
| if (thumbSize > MAX_THUMBNAIL_SIZE) { |
| ALOGE("thumbnail size is over limit\n"); |
| goto encode_jpeg; |
| } |
| |
| thumb = (unsigned char *)thumbnailJpeg->base(); |
| thumbnail = true; |
| |
| LOG_PERFORMANCE_END(1, "encode thumbnail"); |
| |
| encode_jpeg: |
| |
| /* EXIF */ |
| setExifChangedAttribute(); |
| |
| Exif exif(mCameraId); |
| uint32_t exifSize; |
| |
| unsigned char *jpeg; |
| int jpegSize = 0; |
| int jpegQuality = mParameters.getInt(CameraParameters::KEY_JPEG_QUALITY); |
| |
| sp<MemoryHeapBase> JpegHeap = new MemoryHeapBase(mPictureSize.width * mPictureSize.height * 2); |
| sp<MemoryHeapBase> exifHeap = new MemoryHeapBase(EXIF_MAX_LEN); |
| if (!initialized(exifHeap)) { |
| ALOGE("getJpeg: error, could not initialize Camera exif heap"); |
| return false; |
| } |
| |
| if (!thumbnail) |
| exifSize = exif.make(exifHeap->base(), &mExifInfo); |
| else |
| exifSize = exif.make(exifHeap->base(), &mExifInfo, exifHeap->getSize(), thumb, thumbSize); |
| |
| #ifdef CHG_ENCODE_JPEG |
| ret = EncodeToJpeg((unsigned char*)rawImageMem->base(), |
| mPictureSize.width, |
| mPictureSize.height, |
| CAM_PIXEL_FORMAT_YUV422I, |
| (unsigned char*)JpegHeap->base(), |
| &jpegSize, |
| mJpegQuality); |
| |
| if (ret != NO_ERROR) { |
| ALOGE("EncodeToJpeg failed\n"); |
| return false; |
| } |
| #endif |
| mPictureFrameSize = jpegSize + exifSize; |
| |
| /* picture frame size is should be calculated before call allocateSnapshotHeap */ |
| if (!allocateSnapshotHeap()) { |
| ALOGE("getJpeg: error, allocateSnapshotHeap"); |
| return false; |
| } |
| |
| jpeg = (unsigned char *)JpegHeap->base(); |
| memcpy((unsigned char *)mJpegHeap->data, jpeg, 2); |
| memcpy((unsigned char *)mJpegHeap->data + 2, exifHeap->base(), exifSize); |
| memcpy((unsigned char *)mJpegHeap->data + 2 + exifSize, jpeg + 2, jpegSize - 2); |
| |
| return true; |
| } |
| #endif |
| |
| bool SecCameraHardware::allocatePostviewHeap() |
| { |
| cam_pixel_format postviewFmt; |
| |
| ALOGD("E"); |
| if ( mPostviewHeap && mPostviewHeap->size == mPostviewFrameSize ) |
| return true; |
| |
| if (mPostviewHeap) { |
| mPostviewHeap->release(mPostviewHeap); |
| mPostviewHeap = 0; |
| } |
| |
| if (mPostviewHeapTmp) { |
| mPostviewHeapTmp->release(mPostviewHeapTmp); |
| mPostviewHeapTmp = NULL; |
| } |
| |
| if (mPASMMode == MODE_MAGIC) { |
| postviewFmt = CAM_PIXEL_FORMAT_YUV420SP; |
| ALOGD("Postview format = YUV420SP"); |
| } else { |
| postviewFmt = CAM_PIXEL_FORMAT_YUV422I; |
| ALOGD("Postview format = YUV422I"); |
| } |
| |
| mPostviewFrameSize = getAlignedYUVSize(postviewFmt, mPostviewSize.width, mPostviewSize.height, NULL); |
| mPostviewHeap = mGetMemoryCb(-1, mPostviewFrameSize, 1, &mPostviewHeapFd); |
| if (!mPostviewHeap || mPostviewHeap->data == MAP_FAILED) { |
| ALOGE("ERR(%s): Virtual postview heap creation fail", __func__); |
| return false; |
| } |
| |
| mPostviewHeapTmp = mGetMemoryCb(-1, mPostviewFrameSize, 1, &mPostviewHeapTmpFd); |
| if (!mPostviewHeapTmp || mPostviewHeapTmp->data == MAP_FAILED) { |
| ALOGE("ERR(%s): Virtual postview heap creation fail", __func__); |
| return false; |
| } |
| |
| ALOGD("allocatePostviewHeap: postview %dx%d, frame %d", |
| mPostviewSize.width, mPostviewSize.height, mPostviewFrameSize); |
| |
| return true; |
| } |
| |
| bool SecCameraHardware::allocateSnapshotHeap() |
| { |
| /* init jpeg heap */ |
| if (mJpegHeap) { |
| mJpegHeap->release(mJpegHeap); |
| mJpegHeap = 0; |
| } |
| |
| mJpegHeap = mGetMemoryCb(-1, mPictureFrameSize, 1, &mJpegHeapFd); |
| |
| ALOGD("allocateSnapshotHeap: jpeg %dx%d, size %d", |
| mPictureSize.width, mPictureSize.height, mPictureFrameSize); |
| |
| #if 0 |
| /* RAW_IMAGE or POSTVIEW_FRAME heap */ |
| if ((mMsgEnabled & CAMERA_MSG_RAW_IMAGE) || (mMsgEnabled & CAMERA_MSG_POSTVIEW_FRAME)) { |
| mRawFrameSize = getAlignedYUVSize(mFliteFormat, mRawSize.width, mRawSize.height, NULL); |
| mRawHeap = mGetMemoryCb(-1, mRawFrameSize, 1, &mRawHeapFd); |
| |
| ALOGD("allocateSnapshotHeap: postview %dx%d, frame %d", |
| mRawSize.width, mRawSize.height, mRawFrameSize); |
| } |
| #endif |
| |
| return true; |
| } |
| |
| bool SecCameraHardware::allocateHDRHeap() |
| { |
| /* init postview heap */ |
| if (mHDRHeap) { |
| mHDRHeap->release(mHDRHeap); |
| mHDRHeap = NULL; |
| } |
| |
| mRawSize = mPictureSize; |
| mHDRFrameSize = mRawSize.width*mRawSize.height*2; |
| mHDRHeap = mGetMemoryCb(-1, mHDRFrameSize, 1, &mHDRHeapFd); |
| if (!mHDRHeap || mHDRHeap->data == MAP_FAILED) { |
| ALOGE("ERR(%s): HDR heap creation fail", __func__); |
| goto out; |
| } |
| |
| return true; |
| |
| out: |
| |
| if (mHDRHeap) { |
| mHDRHeap->release(mHDRHeap); |
| mHDRHeap = NULL; |
| } |
| |
| return false; |
| } |
| |
| #ifndef RCJUNG |
| bool SecCameraHardware::allocateYUVHeap() |
| { |
| /* init YUV main image heap */ |
| if (mYUVHeap) { |
| mYUVHeap->release(mYUVHeap); |
| mYUVHeap = 0; |
| } |
| |
| mYUVHeap = mGetMemoryCb(-1, mRawFrameSize, 1, 0); |
| if (!mYUVHeap || mYUVHeap->data == MAP_FAILED) { |
| ALOGE("ERR(%s): YUV heap creation fail", __func__); |
| goto out; |
| } |
| |
| ALOGD("allocateYUVHeap: YUV %dx%d, frame %d", |
| mOrgPreviewSize.width, mOrgPreviewSize.height, mRawFrameSize); |
| |
| return true; |
| |
| out: |
| |
| if (mYUVHeap) { |
| mYUVHeap->release(mYUVHeap); |
| mYUVHeap = NULL; |
| } |
| |
| return false; |
| } |
| #endif |
| |
| void SecCameraHardware::nativeMakeJpegDump() |
| { |
| int postviewOffset; |
| ALOGV("DEBUG(%s): (%d)", __FUNCTION__, __LINE__); |
| ExynosBuffer jpegBuf; |
| ALOGV("DEBUG(%s): (%d)", __FUNCTION__, __LINE__); |
| if (getJpegOnBack(&postviewOffset) >= 0) { |
| ALOGV("DEBUG(%s): (%d)", __FUNCTION__, __LINE__); |
| jpegBuf.size.extS[0] = mPictureFrameSize; |
| jpegBuf.virt.extP[0] = (char *)mJpegHeap->data; |
| ALOGV("DEBUG(%s): (%d)", __FUNCTION__, __LINE__); |
| mSaveDump("/data/camera_%d.jpeg", &jpegBuf, 0); |
| ALOGV("DEBUG(%s): (%d)", __FUNCTION__, __LINE__); |
| } else { |
| ALOGV("DEBUG(%s): (%d) fail!!!!", __FUNCTION__, __LINE__); |
| } |
| } |
| |
| bool SecCameraHardware::nativeStartPostview() |
| { |
| ALOGD("nativeStartPostview E"); |
| |
| int err; |
| int nBufs = 1; |
| int i; |
| |
| /* For YUV postview */ |
| cam_pixel_format captureFormat = CAM_PIXEL_FORMAT_YUV422I; |
| #if 0 |
| if (mCaptureMode == RUNNING_MODE_BURST ) |
| captureFormat = CAM_PIXEL_FORMAT_YUV420SP; |
| #endif |
| |
| if ( captureFormat==CAM_PIXEL_FORMAT_YUV422I ) |
| mPostviewFrameSize = mPostviewSize.width * mPostviewSize.height * 2; /* yuv422I */ |
| else if ( captureFormat == CAM_PIXEL_FORMAT_YUV420SP ) |
| mPostviewFrameSize = mPostviewSize.width * mPostviewSize.height * 1.5; /* yuv420sp */ |
| |
| ALOGD("Postview size : width = %d, height = %d, frame size = %d", |
| mPostviewSize.width, mPostviewSize.height, mPreviewFrameSize); |
| err = mFlite.startCapture(&mPostviewSize, captureFormat, nBufs, START_CAPTURE_POSTVIEW); |
| CHECK_ERR(err, ("nativeStartPostview: error, mFlite.start")); |
| |
| ALOGD("nativeStartPostview GC"); |
| |
| getAlignedYUVSize(captureFormat, mPostviewSize.width, mPostviewSize.height, &mPictureBuf); |
| if (allocMem(mIonCameraClient, &mPictureBuf, 1 << 1) == false) { |
| ALOGE("ERR(%s):mPictureBuf allocMem() fail", __func__); |
| return UNKNOWN_ERROR; |
| } else { |
| ALOGV("DEBUG(%s): mPictureBuf allocMem adr(%p), size(%d), ion(%d) w/h(%d/%d)", __FUNCTION__, |
| mPictureBuf.virt.extP[0], mPictureBuf.size.extS[0], mIonCameraClient, |
| mPostviewSize.width, mPostviewSize.height); |
| memset(mPictureBuf.virt.extP[0], 0, mPictureBuf.size.extS[0]); |
| } |
| |
| #ifdef USE_USERPTR |
| for (i = 0; i < SKIP_CAPTURE_CNT; i++) { |
| getAlignedYUVSize(captureFormat, mPostviewSize.width, mPostviewSize.height, &mPictureBufDummy[i]); |
| if (allocMem(mIonCameraClient, &mPictureBufDummy[i], 1 << 1) == false) { |
| ALOGE("ERR(%s):mPictureBuf dummy allocMem() fail", __func__); |
| return UNKNOWN_ERROR; |
| } else { |
| ALOGV("DEBUG(%s): mPictureBuf dummy allocMem adr(%p), size(%d), ion(%d) w/h(%d/%d)", __FUNCTION__, |
| mPictureBufDummy[i].virt.extP[0], mPictureBufDummy[i].size.extS[0], mIonCameraClient, |
| mPostviewSize.width, mPostviewSize.height); |
| memset(mPictureBufDummy[i].virt.extP[0], 0, mPictureBufDummy[i].size.extS[0]); |
| } |
| } |
| #else |
| for (i = 0; i < SKIP_CAPTURE_CNT; i++) { |
| err = mFlite.querybuf2(i, mFliteNode.planes, &mPictureBufDummy[i]); |
| CHECK_ERR_N(err, ("nativeStartPreviewZoom: error, mFlite.querybuf2")); |
| } |
| #endif |
| |
| /* qbuf dummy buffer for skip */ |
| for (i = 0; i < SKIP_CAPTURE_CNT; i++) { |
| err = mFlite.qbufForCapture(&mPictureBufDummy[i], i); |
| CHECK_ERR(err, ("nativeStartPostview: error, mFlite.qbuf(%d)", i)); |
| } |
| |
| ALOGD("Normal Capture Stream on"); |
| err = mFlite.stream(true); |
| CHECK_ERR(err, ("nativeStartPostview: error, mFlite.stream")); |
| |
| if ( mCaptureMode == RUNNING_MODE_SINGLE ) { |
| // PlayShutterSound(); |
| // Fimc_stream_true_part2(); |
| } |
| |
| ALOGD("nativeStartPostview X"); |
| return true; |
| } |
| |
| bool SecCameraHardware::nativePrepareYUVSnapshot() |
| { |
| ALOGD("nativePrepareYUVSnapshot E"); |
| |
| mRawSize = mPictureSize; |
| mHDRFrameSize = mRawSize.width*mRawSize.height*2; |
| |
| if (!allocateHDRHeap()) { |
| ALOGE("nativePrepareYUVSnapshot: error, allocateHDRHeap"); |
| return false; |
| } |
| |
| ALOGD("nativePrepareYUVSnapshot : HDR Total Frame Size(mHDRFrameSize) = [%d]", mHDRFrameSize * 3); |
| ALOGD("nativePrepareYUVSnapshot X"); |
| return true; |
| } |
| |
| bool SecCameraHardware::nativeStartYUVSnapshot() |
| { |
| ALOGD("nativeStartYUVSnapshot E"); |
| |
| int err; |
| int nBufs = 1; |
| int i = 0; |
| ExynosBuffer nullBuf; |
| |
| cam_pixel_format captureFormat = CAM_PIXEL_FORMAT_YUV422I; |
| |
| err = mFlite.startCapture(&mFLiteCaptureSize, captureFormat, nBufs, START_CAPTURE_YUV_MAIN); |
| CHECK_ERR(err, ("nativeStartYUVSnapshot: error, mFlite.start")); |
| |
| #ifdef USE_USERPTR |
| for (i = 0; i < SKIP_CAPTURE_CNT; i++) { |
| getAlignedYUVSize(captureFormat, mFLiteCaptureSize.width, mFLiteCaptureSize.height, &mPictureBufDummy[i]); |
| if (allocMem(mIonCameraClient, &mPictureBufDummy[i], 1 << 1) == false) { |
| ALOGE("ERR(%s):mPictureBuf dummy allocMem() fail", __func__); |
| return UNKNOWN_ERROR; |
| } else { |
| ALOGV("DEBUG(%s): mPictureBuf dummy allocMem adr(%p), size(%d), ion(%d) w/h(%d/%d)", __FUNCTION__, |
| mPictureBufDummy[i].virt.extP[0], mPictureBufDummy[i].size.extS[0], mIonCameraClient, |
| mFLiteCaptureSize.width, mFLiteCaptureSize.height); |
| memset(mPictureBufDummy[i].virt.extP[0], 0, mPictureBufDummy[i].size.extS[0]); |
| } |
| } |
| #else |
| for (i = 0; i < SKIP_CAPTURE_CNT; i++) { |
| err = mFlite.querybuf2(i, mFliteNode.planes, &mPictureBufDummy[i]); |
| CHECK_ERR_N(err, ("nativeStartYUVSnapshot: error, mFlite.querybuf2")); |
| } |
| #endif |
| |
| /* qbuf dummy buffer for skip */ |
| for (i = 0; i < SKIP_CAPTURE_CNT; i++) { |
| err = mFlite.qbufForCapture(&mPictureBufDummy[i], i); |
| CHECK_ERR(err, ("nativeStartYUVSnapshot: error, mFlite.qbuf(%d)", i)); |
| } |
| |
| err = mFlite.stream(true); |
| CHECK_ERR(err, ("nativeStartYUVSnapshot: error, mFlite.stream")); |
| |
| if ( mCaptureMode == RUNNING_MODE_SINGLE ) { |
| // PlayShutterSound(); |
| // Fimc_stream_true_part2(); |
| } |
| |
| ALOGD("nativeStartYUVSnapshot X"); |
| return true; |
| } |
| |
| bool SecCameraHardware::nativeGetYUVSnapshot(int numF, int *postviewOffset) |
| { |
| ALOGD("nativeGetYUVSnapshot E"); |
| |
| int err; |
| int i = 0; |
| |
| retry: |
| |
| err = mFlite.sctrl(CAM_CID_TRANSFER, numF); |
| CHECK_ERR(err, ("nativeGetYUVSnapshot: error, capture start")) |
| /* |
| * Put here if Capture Start Command code is additionally needed |
| * in case of ISP. |
| */ |
| |
| /* |
| * Waiting for frame(stream) to be input. |
| * ex) poll() |
| */ |
| #ifndef FPOLLING |
| err = mFlite.polling(isFactoryTest()); |
| #endif |
| if (CC_UNLIKELY(err <= 0)) { |
| LOG_FATAL("nativeGetYUVSnapshot: fail to get a frame!"); |
| return false; |
| } |
| ALOGV("DEBUG(%s): (%d) nativeGetYUVSnapshot dq start", __FUNCTION__, __LINE__); |
| |
| for (i = 0; i < SKIP_CAPTURE_CNT; i++) { |
| int ret = mFlite.dqbufForCapture(&mPictureBufDummy[i]); |
| ALOGV("DEBUG(%s) (%d): dqbufForCapture dq(%d), ret = %d", __FUNCTION__, __LINE__, i, ret); |
| } |
| |
| /* Stop capturing stream(or frame) data. */ |
| err = mFlite.stream(false); |
| CHECK_ERR(err, ("nativeGetYUVSnapshot: error, mFlite.stream")); |
| |
| #ifdef SAVE_DUMP |
| #if 0 |
| save_dump_path((uint8_t*)mPictureBufDummy[0].virt.extP[0], |
| mPictureBufDummy[0].size.extS[0], "/data/dump_jpeg_only.jpg"); |
| #endif |
| #endif |
| |
| if (!allocateHDRHeap()) { |
| ALOGE("getEncodedJpeg: error, allocateSnapshotHeap"); |
| return false; |
| } |
| memcpy((char *)mHDRHeap->data, (uint8_t *)mPictureBufDummy[0].virt.extP[0], mHDRFrameSize); |
| ALOGD("%s: mHDRHeap memcpy end size (mHDRFrameSize) = %d", __func__, mHDRFrameSize); |
| //mGetMemoryCb(mPictureBufDummy[0].fd.extFd[0], mHDRFrameSize, 1, mCallbackCookie); |
| |
| #if 0 |
| err = getYUV(numF); |
| if (mCaptureMode == RUNNING_MODE_HDR) { |
| if (numF == 1) { |
| struct record_heap *scrab_heap = (struct record_heap *)mHDRHeap->data; |
| |
| scrab_heap[3].type = kMetadataBufferTypeCameraSource; |
| scrab_heap[3].buf_index = 3; |
| scrab_heap[3].reserved = (uint32_t)mPictureBufDummy[0].virt.extP[0]; |
| ALOGE("Scrab memory set to ION. scrab_heap[3].reserved = %08x", scrab_heap[3].reserved); |
| } |
| } |
| CHECK_ERR(err, ("nativeGetYUVSnapshot: error, getYUV")); |
| #endif |
| ALOGD("nativeGetYUVSnapshot X"); |
| return true; |
| } |
| |
| #ifndef RCJUNG |
| bool SecCameraHardware::nativeGetSnapshotMainSeq(uint32_t mode, int numf) |
| { |
| int err; |
| |
| ALOGD("nativeGetSnapshotMainSeq E"); |
| |
| retry: |
| |
| /* |
| * Put here if Capture Start Command code is needed in addition */ |
| if (mCameraId == CAMERA_FACING_BACK) { |
| err = mFlite.sctrl(mode, numf); |
| CHECK_ERR(err, ("nativeGetSnapshotMainSeq: error, capture start")); |
| } |
| |
| /* |
| * Waiting for frame(stream) to be input. |
| * ex) poll() |
| */ |
| #ifndef FPOLLING |
| err = mFlite.polling(isFactoryTest(), false);//isFactoryTest()); |
| #endif |
| if (CC_UNLIKELY(err <= 0)) { |
| LOG_FATAL("nativeGetYUVSnapshot: fail to get a frame!"); |
| return false; |
| } |
| ALOGV("DEBUG(%s): (%d) nativeGetSnapshotMainSeq dq start", __FUNCTION__, __LINE__); |
| |
| int ret = mFlite.dqbufForCapture(&mPictureBufDummy[0]); |
| ALOGV("DEBUG(%s) (%d): dqbufForCapture dq(0), ret = %d", __FUNCTION__, __LINE__, ret); |
| |
| /* last capture was stored dummy buffer due to zoom. |
| * and zoom applied to capture image by fimc */ |
| err = nativeCSCCapture(&mPictureBufDummy[0], &mPictureBuf); |
| CHECK_ERR_N(err, ("nativeGetYUVSnapshot: error, nativeCSCCapture")); |
| |
| /* |
| * Stop capturing stream(or frame) data. */ |
| err = mFlite.stream(false); |
| CHECK_ERR(err, ("nativeGetSnapshotMainSeq: error, mFimc.stream")); |
| |
| /* |
| * Get out a filled buffer from driver's queue. */ |
| |
| ALOGD("nativeGetSnapshotMainSeq X"); |
| return true; |
| } |
| |
| bool SecCameraHardware::nativeGetOneYUVSnapshot() |
| { |
| int err = false; |
| |
| ALOGD("nativeGetOneYUVSnapshot E"); |
| |
| if (false == nativeGetSnapshotMainSeq(CAM_CID_TRANSFER, 1)) { |
| return false; |
| } |
| |
| if (mCameraId == CAMERA_FACING_BACK) { |
| ALOGD("nativeGetOneYUVSnapshot: getYUV"); |
| err = getOneYUV(); |
| } |
| |
| #ifdef SAVE_DUMP |
| // save_dump((uint8_t *)mRawHeap->base()/*(uint8_t *)mPostviewHeap->data*/, mRawFrameSize, numF); |
| #endif |
| |
| ALOGD("nativeGetOneYUVSnapshot X"); |
| return err; |
| } |
| |
| bool SecCameraHardware::nativeDumpYUV() |
| { |
| FILE *fp = NULL; |
| char filename[100] = "/data/media/0/camera_dump1.yuv"; |
| |
| char *buffer = NULL; |
| uint8_t *real_data = (uint8_t *)mYUVHeap->data; |
| int data_size = mRawFrameSize; |
| |
| fp = fopen(filename, "wb"); |
| |
| if (fp == NULL) { |
| ALOGE("Save dump image open error"); |
| return false; |
| } |
| |
| ALOGV("%s: real_data size ========> %d", __func__, data_size); |
| buffer = (char *) malloc(data_size); |
| if (buffer == NULL) { |
| ALOGE("Save buffer alloc failed"); |
| if (fp) |
| fclose(fp); |
| |
| return false; |
| } |
| |
| memcpy(buffer, real_data, data_size); |
| fflush(stdout); |
| fwrite(buffer, 1, data_size, fp); |
| fflush(fp); |
| |
| if (fp) |
| fclose(fp); |
| if (buffer) |
| free(buffer); |
| |
| ALOGE("save dump X"); |
| |
| return true; |
| } |
| #endif |
| |
| /* --3 */ |
| bool SecCameraHardware::nativeStartSnapshot() |
| { |
| ALOGD("nativeStartSnapshot E"); |
| |
| int err; |
| int nBufs = 1; |
| int i = 0; |
| ExynosBuffer nullBuf; |
| |
| #if !defined(REAR_USE_YUV_CAPTURE) |
| cam_pixel_format captureFormat = ((mCameraId == CAMERA_FACING_BACK) ? |
| mPictureFormat : CAM_PIXEL_FORMAT_YUV422I); |
| #else |
| cam_pixel_format captureFormat = CAM_PIXEL_FORMAT_YUV422I; |
| #endif |
| |
| #if FRONT_ZSL |
| if (mCameraId == CAMERA_FACING_FRONT && ISecCameraHardware::mFullPreviewRunning) |
| return true; |
| #endif |
| /* This is for VT test mode (SelfTest Mode) */ |
| if ((mVtMode > 0) && mFlite.mIsInternalISP && !mFullPreviewRunning) |
| nativeSetParameters(CAM_CID_VT_MODE, mVtMode); |
| |
| #if VENDOR_FEATURE |
| if (mPASMMode == MODE_MAGIC) { |
| err = mFlite.startCapture(&mFLiteCaptureSize, captureFormat, nBufs, START_CAPTURE_COMBINED); |
| CHECK_ERR(err, ("nativeStartSnapshot: error, mFlite.start")); |
| } else { |
| err = mFlite.startCapture(&mPictureSize, captureFormat, nBufs, START_CAPTURE_JPEG_MAIN); |
| CHECK_ERR(err, ("nativeStartSnapshot: error, mFlite.start")); |
| } |
| #else |
| err = mFlite.startCapture(&mFLiteCaptureSize, captureFormat, nBufs, START_CAPTURE_YUV_MAIN); |
| CHECK_ERR(err, ("nativeStartSnapshot: error, mFlite.start")); |
| #endif |
| |
| /* |
| TODO : The only one buffer should be used |
| between mPictureBuf and mPictureBufDummy in case of jpeg capture |
| */ |
| /* For picture buffer */ |
| getAlignedYUVSize(captureFormat, mPictureSize.width, mPictureSize.height, &mPictureBuf); |
| if (allocMem(mIonCameraClient, &mPictureBuf, 1 << 1) == false) { |
| ALOGE("ERR(%s):mPictureBuf allocMem() fail", __func__); |
| return UNKNOWN_ERROR; |
| } else { |
| ALOGV("DEBUG(%s): mPictureBuf allocMem adr(%p), size(%d), ion(%d) w/h(%d/%d)", __FUNCTION__, |
| mPictureBuf.virt.extP[0], mPictureBuf.size.extS[0], mIonCameraClient, |
| mPictureSize.width, mPictureSize.height); |
| memset(mPictureBuf.virt.extP[0], 0, mPictureBuf.size.extS[0]); |
| } |
| |
| #ifdef USE_USERPTR |
| for (i = 0; i < SKIP_CAPTURE_CNT; i++) { |
| getAlignedYUVSize(captureFormat, mFLiteCaptureSize.width, mFLiteCaptureSize.height, &mPictureBufDummy[i]); |
| if (allocMem(mIonCameraClient, &mPictureBufDummy[i], 1 << 1) == false) { |
| ALOGE("ERR(%s):mPictureBuf dummy allocMem() fail", __func__); |
| return UNKNOWN_ERROR; |
| } else { |
| ALOGV("DEBUG(%s): mPictureBuf dummy allocMem adr(%p), size(%d), ion(%d) w/h(%d/%d)", __FUNCTION__, |
| mPictureBufDummy[i].virt.extP[0], mPictureBufDummy[i].size.extS[0], mIonCameraClient, |
| mPictureSize.width, mPictureSize.height); |
| memset(mPictureBufDummy[i].virt.extP[0], 0, mPictureBufDummy[i].size.extS[0]); |
| } |
| } |
| #else |
| for (i = 0; i < SKIP_CAPTURE_CNT; i++) { |
| err = mFlite.querybuf2(i, mFliteNode.planes, &mPictureBufDummy[i]); |
| CHECK_ERR_N(err, ("nativeStartPreviewZoom: error, mFlite.querybuf2")); |
| } |
| #endif |
| |
| /* qbuf dummy buffer for skip */ |
| for (i = 0; i < SKIP_CAPTURE_CNT; i++) { |
| err = mFlite.qbufForCapture(&mPictureBufDummy[i], i); |
| CHECK_ERR(err, ("nativeStartSnapshot: error, mFlite.qbuf(%d)", i)); |
| } |
| |
| #if !defined(USE_USERPTR) |
| /* export FD */ |
| for (int i = 0; i < SKIP_CAPTURE_CNT; i++) { |
| err = mFlite.expBuf(i, mFliteNode.planes, &mPictureBufDummy[i]); |
| CHECK_ERR_N(err, ("nativeStartSnapshot: error, mFlite.expBuf")); |
| } |
| #endif |
| |
| err = mFlite.stream(true); |
| CHECK_ERR(err, ("nativeStartSnapshot: error, mFlite.stream")); |
| |
| if ( mCaptureMode == RUNNING_MODE_SINGLE ) { |
| // PlayShutterSound(); |
| // Fimc_stream_true_part2(); |
| } |
| |
| ALOGD("nativeStartSnapshot X"); |
| return true; |
| } |
| |
| bool SecCameraHardware::nativeGetPostview(int numF) |
| { |
| int err; |
| int i = 0; |
| |
| ALOGD("nativeGetPostview E"); |
| retry: |
| |
| /* |
| * Put here if Capture Start Command code is needed in addition */ |
| if (mCameraId == CAMERA_FACING_BACK) { |
| err = mFlite.sctrl(CAM_CID_POSTVIEW_TRANSFER, numF); |
| CHECK_ERR(err, ("nativeGetPostview: error, capture start")); |
| } |
| |
| /* |
| * Waiting for frame(stream) to be input. |
| * ex) poll() |
| */ |
| #ifndef FPOLLING |
| err = mFlite.polling(isFactoryTest()); |
| #endif |
| if (CC_UNLIKELY(err <= 0)) { |
| #ifdef ISP_LOGWRITE |
| ALOGE("polling error - SEC_ISP_DBG_logwrite = %s", __func__); |
| SEC_ISP_DBG_logwrite(); |
| #endif |
| #if 0 |
| if (!retryDone) { |
| ALOGW("nativeGetPostview: warning. Reset the camera device"); |
| mFimc.stream(false); |
| nativeStopSnapshot(); |
| mFimc.reset(); |
| |
| /* read thermistor value from sysfs */ |
| #ifdef THERMISTOR_VAL_SUPPORT |
| if (mCameraId == CAMERA_FACING_BACK) { |
| uint32_t thermistor_val; |
| nativeReadThermistorVal(&thermistor_val); |
| /* for Post init */ |
| err = nativeSetParameters(CAM_CID_CAMERA_INIT, 0); |
| CHECK_ERR_N(err, ("FimcV4l2 init: error %d", err)); |
| /* set thermistor value to ISP */ |
| err = nativeSetParameters(CAM_CID_CAMERA_POST_INIT, thermistor_val); |
| CHECK_ERR_N(err, ("FimcV4l2 post init: error %d", err)); |
| } |
| #endif |
| nativeStartSnapshot(); |
| retryDone = true; |
| goto retry; |
| } |
| #endif |
| ALOGE("nativeGetPostview: error, mFlite.polling"); |
| return false; |
| } |
| |
| /* |
| * Get out a filled buffer from driver's queue. */ |
| for (i = 0; i < SKIP_CAPTURE_CNT; i++) { |
| int ret = mFlite.dqbufForCapture(&mPictureBufDummy[i]); |
| ALOGV("DEBUG(%s) (%d): dqbufForCapture dq(%d), ret = %d", __FUNCTION__, __LINE__, i, ret); |
| } |
| |
| /* |
| * Stop capturing stream(or frame) data. */ |
| err = mFlite.stream(false); |
| CHECK_ERR(err, ("nativeGetPostview: error, mFlite.stream")); |
| |
| if (mCameraId == CAMERA_FACING_BACK) { |
| err = getPostview(numF); |
| CHECK_ERR(err, ("nativeGetPostview: error, getPostview")); |
| } |
| |
| ALOGD("nativeGetPostview X"); |
| return true; |
| } |
| |
| /* --4 */ |
| bool SecCameraHardware::nativeGetSnapshot(int numF, int *postviewOffset) |
| { |
| ALOGD("nativeGetSnapshot E"); |
| |
| int err; |
| int i = 0; |
| bool retryDone = false; |
| |
| #if FRONT_ZSL |
| if (mCameraId == CAMERA_FACING_FRONT && ISecCameraHardware::mFullPreviewRunning) |
| return getZSLJpeg(); |
| #endif |
| |
| retry: |
| |
| #if VENDOR_FEATURE |
| err = mFlite.sctrl(CAM_CID_TRANSFER, numF); |
| CHECK_ERR(err, ("nativeGetSnapshot: error, capture start")) |
| #endif |
| /* |
| * Put here if Capture Start Command code is additionally needed |
| * in case of ISP. |
| */ |
| |
| /* |
| * Waiting for frame(stream) to be input. |
| * ex) poll() |
| */ |
| #ifndef FPOLLING |
| err = mFlite.polling(isFactoryTest()); |
| #endif |
| if (CC_UNLIKELY(err <= 0)) { |
| #ifdef DEBUG_CAPTURE_RETRY |
| LOG_FATAL("nativeGetSnapshot: fail to get a frame!"); |
| #else |
| if (!retryDone) { |
| ALOGW("nativeGetSnapshot: warning. Reset the camera device"); |
| mFlite.stream(false); |
| nativeStopSnapshot(); |
| mFlite.reset(); |
| nativeStartSnapshot(); |
| retryDone = true; |
| goto retry; |
| } |
| ALOGE("nativeGetSnapshot: error, mFlite.polling"); |
| #endif |
| return false; |
| } |
| ALOGV("DEBUG(%s): (%d) nativeGetSnapshot dq start", __FUNCTION__, __LINE__); |
| |
| for (i = 0; i < SKIP_CAPTURE_CNT; i++) { |
| int ret = mFlite.dqbufForCapture(&mPictureBufDummy[i]); |
| ALOGV("DEBUG(%s) (%d): dqbufForCapture dq(%d), ret = %d", __FUNCTION__, __LINE__, i, ret); |
| } |
| |
| #if VENDOR_FEATURE |
| #else |
| /* last capture was stored dummy buffer due to zoom. |
| * and zoom applied to capture image by fimc */ |
| err = nativeCSCCapture(&mPictureBufDummy[i-1], &mPictureBuf); |
| CHECK_ERR_N(err, ("nativeGetSnapshot: error, nativeCSCCapture")); |
| #endif |
| |
| /* Stop capturing stream(or frame) data. */ |
| err = mFlite.stream(false); |
| CHECK_ERR(err, ("nativeGetSnapshot: error, mFlite.stream")); |
| |
| #ifdef SAVE_DUMP |
| #if 0 |
| save_dump_path((uint8_t*)mPictureBufDummy[0].virt.extP[0], |
| mPictureBufDummy[0].size.extS[0], "/data/dump_jpeg_only.jpg"); |
| #endif |
| #endif |
| |
| if (numF == 0 && mCaptureMode == RUNNING_MODE_RAW ) { //(mCaptureMode == RUNNING_MODE_RAW ) { |
| int jpegSize; |
| nativeGetParameters(CAM_CID_JPEG_MAIN_SIZE, &jpegSize ); |
| mPictureFrameSize = (uint32_t)jpegSize; |
| allocateSnapshotHeap(); |
| } else { |
| /* Get Jpeg image including EXIF. */ |
| if (mCameraId == CAMERA_FACING_BACK) |
| err = getJpegOnBack(postviewOffset); |
| else |
| err = getJpegOnFront(postviewOffset); |
| |
| CHECK_ERR(err, ("nativeGetSnapshot: error, getJpeg")); |
| } |
| |
| #if 0 |
| if ((mMsgEnabled & CAMERA_MSG_RAW_IMAGE) || (mMsgEnabled & CAMERA_MSG_POSTVIEW_FRAME)) { |
| int copySize = mRawFrameSize; |
| if (mPictureBuf.size.extS[0] < copySize) |
| copySize = mPictureBuf.size.extS[0]; |
| |
| memcpy((char *)mRawHeap->data, mPictureBuf.virt.extP[0], copySize); |
| ALOGV("DEBUG(%s): (%d) copied mRawHeap", __FUNCTION__, __LINE__); |
| } |
| #endif |
| |
| #ifdef DUMP_JPEG_FILE |
| ExynosBuffer jpegBuf; |
| ALOGV("DEBUG(%s): (%d) %d", __FUNCTION__, __LINE__, mPictureFrameSize); |
| jpegBuf.size.extS[0] = mPictureFrameSize; |
| jpegBuf.virt.extP[0] = (char *)mJpegHeap->data; |
| ALOGV("DEBUG(%s): (%d)", __FUNCTION__, __LINE__); |
| mSaveDump("/data/camera_capture%d.jpg", &jpegBuf, 1); |
| ALOGV("DEBUG(%s): (%d)", __FUNCTION__, __LINE__); |
| #endif |
| |
| ALOGD("nativeGetSnapshot X"); |
| return true; |
| } |
| |
| bool SecCameraHardware::nativeStartDualCapture(int numF) |
| { |
| int err; |
| |
| ALOGD("nativeStartDualCapture E - frame: %d", numF); |
| err = mFlite.sctrl(V4L2_CID_CAMERA_SET_DUAL_CAPTURE, numF); |
| CHECK_ERR(err, ("nativeStartDualCapture: error, capture start")); |
| |
| ALOGD("nativeStartDualCapture X"); |
| |
| return true; |
| } |
| |
| int SecCameraHardware::getYUV(int fnum) |
| { |
| ALOGE("%s: start, fnum = %d", __func__, fnum); |
| |
| struct record_heap *heap = (struct record_heap *)mHDRHeap->data; |
| int nAddr; |
| |
| nAddr = mPictureBufDummy[0].phys.extP[0]; |
| |
| heap[fnum - 1].type = kMetadataBufferTypeCameraSource; |
| heap[fnum - 1].y = nAddr; |
| heap[fnum - 1].cbcr = nAddr + (mRawSize.width * mRawSize.height); |
| heap[fnum - 1].buf_index = fnum - 1; |
| /* |
| Just 2 buffer of ION memories are allocated for HDR. |
| Fimc0 memory is used for last one buffer to reduce |
| the number of ION memory to 2 from 3. |
| In case of 16M camera, 64M HDR memory is needed instead of 96M. |
| */ |
| |
| ALOGE("Fnum = %d, ION memory using", fnum); |
| heap[fnum - 1].reserved = (uint32_t)mPictureBufDummy[0].virt.extP[0]; |
| |
| #if 0 |
| if (fnum <= 2) { |
| ALOGE("Fnum = %d, ION memory using", fnum); |
| heap[fnum - 1].reserved = (uint32_t*)mPictureBufDummy[0].virt.extP[0]; |
| } else { |
| uint32_t last_frame = (uint32_t)mRawHeap->base(); |
| heap[fnum - 1].reserved = last_frame; |
| ALOGE("Fnum = %d, Fimc0 memory using", fnum); |
| } |
| #endif |
| |
| ALOGE("getYUV hdrheappointer(ion) : %x, mHDRFrameSize = %d", heap[fnum - 1].reserved, mHDRFrameSize); |
| |
| /* Note : Sensor return main image size, not only JPEG but also YUV. */ |
| //err = mFlite.gctrl(V4L2_CID_CAM_JPEG_MAIN_SIZE, &yuvSize); |
| //CHECK_ERR(err, ("getYUV: error %d, jpeg size", err)); |
| //mRawFrameSize = yuvSize; |
| mRawFrameSize = mRawSize.width*mRawSize.height*2; /* yuv422I */ |
| |
| /* picture frame size is should be calculated before call allocatePostviewHeap */ |
| uint8_t *postview = (uint8_t *)mPictureBufDummy[0].virt.extP[0]; |
| |
| memcpy((void*)heap[fnum - 1].reserved , postview, mRawFrameSize); |
| |
| #if 0 /* FIMC output data */ |
| if (fnum == 1) |
| save_dump_path(postview, mRawFrameSize, "/data/dump_HDR1.yuv"); |
| if (fnum == 2) |
| save_dump_path(postview, mRawFrameSize, "/data/dump_HDR2.yuv"); |
| if (fnum == 3) |
| save_dump_path(postview, mRawFrameSize, "/data/dump_HDR3.yuv"); |
| #endif |
| #if 0 /* ION memory data */ |
| if (fnum == 1) |
| save_dump_path((uint8_t*)mPictureBufDummy[0].virt.extP[0], mHDRFrameSize, "/data/dump_HDR1.yuv"); |
| if (fnum == 2) |
| save_dump_path((uint8_t*)mPictureBufDummy[0].virt.extP[0], mHDRFrameSize, "/data/dump_HDR2.yuv"); |
| if (fnum == 3) |
| save_dump_path((uint8_t*)mPictureBufDummy[0].virt.extP[0], mHDRFrameSize, "/data/dump_HDR3.yuv"); |
| #endif |
| #if 0 /* ION memory data through mHDRHeap pointer */ |
| if (fnum == 1) |
| save_dump_path((uint8_t*)(((struct record_heap *)mHDRHeap->data)[fnum - 1].reserved), mHDRFrameSize, "/data/dump_HDR1.yuv"); |
| if (fnum == 2) |
| save_dump_path((uint8_t*)(((struct record_heap *)mHDRHeap->data)[fnum - 1].reserved), mHDRFrameSize, "/data/dump_HDR2.yuv"); |
| if (fnum == 3) |
| save_dump_path((uint8_t*)(((struct record_heap *)mHDRHeap->data)[fnum - 1].reserved), mHDRFrameSize, "/data/dump_HDR3.yuv"); |
| #endif |
| |
| ALOGD("%s: mPostviewHeap memcpy end size (mRawFrameSize) = %d", __func__, mRawFrameSize); |
| |
| return 0; |
| } |
| |
| #ifndef RCJUNG |
| int SecCameraHardware::getOneYUV() |
| { |
| ALOGE("%s: start", __func__); |
| |
| int yuvSize = 0; |
| int err; |
| |
| /* Note : Sensor return main image size, not only JPEG but also YUV. */ |
| err = mFlite.gctrl(V4L2_CID_CAM_JPEG_MAIN_SIZE, &yuvSize); |
| CHECK_ERR(err, ("getYUV: error %d, jpeg size", err)); |
| |
| /* picture frame size is should be calculated before call allocateYUVHeap */ |
| mRawSize = mPictureSize; |
| mRawFrameSize = mRawSize.width * mRawSize.height * 2; /* yuv422I */ |
| |
| setExifChangedAttribute(); |
| |
| uint8_t *YUVmain = (uint8_t *)mPictureBufDummy[0].virt.extP[0]; |
| |
| if (!allocateYUVHeap()) { |
| ALOGE("getYUV: error, allocateYUVHeap"); |
| return false; |
| } |
| |
| memcpy(mYUVHeap->data, YUVmain, mRawFrameSize); |
| |
| ALOGD("%s: mYUVHeap memcpy end size (mRawFrameSize) = %d", __func__, mRawFrameSize); |
| |
| return true; |
| } |
| #endif |
| |
| int SecCameraHardware::getPostview(int num) |
| { |
| ALOGD("%s: start", __func__); |
| |
| /* picture frame size is should be calculated before call allocatePostviewHeap */ |
| if (!allocatePostviewHeap()) { |
| ALOGE("getPostview: error, allocatePostviewHeap"); |
| return UNKNOWN_ERROR; |
| } |
| |
| uint8_t *postview = (uint8_t *)mPictureBufDummy[0].virt.extP[0]; |
| |
| memcpy((char *)mPostviewHeap->data, postview, mPostviewFrameSize); |
| |
| #ifdef SAVE_DUMP |
| #if 0 |
| char *fileName = NULL; |
| sprintf(fileName, "%s_%d.yuv%c", "/data/dump_postview_yuv", num, NULL); |
| ALOGD("getPostview: dump postview image = %s", fileName); |
| save_dump_path((uint8_t *)mPictureBufDummy[0].virt.extP[0], mPictureBufDummy[0].size.extS[0], fileName); |
| #endif |
| #endif |
| |
| ALOGE("%s: Postview memcpy end size = %d", __func__, mPostviewFrameSize); |
| |
| return 0; |
| } |
| |
| inline int SecCameraHardware::getJpegOnBack(int *postviewOffset) |
| { |
| status_t ret; |
| |
| #if !defined(REAR_USE_YUV_CAPTURE) |
| if (mCaptureMode == RUNNING_MODE_RAW) |
| return internalGetJpegForRawWithZoom(postviewOffset); |
| else if (mPASMMode == MODE_MAGIC) |
| return getCombinedJpeg(postviewOffset); |
| else |
| return internalGetJpegForSocYuvWithZoom(postviewOffset); |
| #else |
| if (mEnableDZoom) |
| ret = internalGetJpegForSocYuvWithZoom(postviewOffset); |
| else |
| ret = internalGetJpegForSocYuv(postviewOffset); |
| |
| return ret; |
| #endif |
| } |
| |
| inline int SecCameraHardware::getJpegOnFront(int *postviewOffset) |
| { |
| status_t ret; |
| ret = internalGetJpegForSocYuvWithZoom(postviewOffset); |
| return ret; |
| } |
| |
| void SecCameraHardware::nativeStopSnapshot() |
| { |
| ExynosBuffer nullBuf; |
| int i = 0; |
| |
| if (mRawHeap != NULL) { |
| mRawHeap->release(mRawHeap); |
| mRawHeap = 0; |
| } |
| |
| freeMem(&mPictureBuf); |
| |
| #ifdef USE_USERPTR |
| /* capture buffer free */ |
| for (i = 0; i < SKIP_CAPTURE_CNT; i++) { |
| freeMem(&mPictureBufDummy[i]); |
| mPictureBufDummy[i] = nullBuf; |
| } |
| #else |
| for (i = 0; i < SKIP_CAPTURE_CNT; i++) { |
| for (int j = 0; j < mFliteNode.planes; j++) { |
| munmap((void *)mPictureBufDummy[i].virt.extP[j], |
| mPictureBufDummy[i].size.extS[j]); |
| ion_free(mPictureBufDummy[i].fd.extFd[j]); |
| } |
| mPictureBufDummy[i] = nullBuf; |
| } |
| |
| if (mFlite.reqBufZero(&mFliteNode) < 0) |
| ALOGE("ERR(%s): mFlite.reqBufZero() fail", __func__); |
| #endif |
| |
| |
| mPictureBuf = nullBuf; |
| ALOGD("nativeStopSnapshot EX"); |
| } |
| |
| bool SecCameraHardware::nativeSetAutoFocus() |
| { |
| ALOGV("nativeSetAutofocus E"); |
| |
| int i, waitUs = 10000, tryCount = (900 * 1000) / waitUs; |
| for (i = 1; i <= tryCount; i++) { |
| if (mPreviewInitialized) |
| break; |
| else |
| usleep(waitUs); |
| |
| if (!(i % 40)) |
| ALOGD("AF: waiting for preview\n"); |
| } |
| |
| if (CC_UNLIKELY(i > tryCount)) |
| ALOGI("cancelAutoFocus: cancel timeout"); |
| |
| int err = mFlite.sctrl(V4L2_CID_CAM_SINGLE_AUTO_FOCUS, AUTO_FOCUS_ON); |
| CHECK_ERR(err, ("nativeSetAutofocus X: error, mFlite.sctrl")) |
| |
| ALOGV("nativeSetAutofocus X"); |
| |
| return true; |
| } |
| |
| int SecCameraHardware::nativeGetPreAutoFocus() |
| { |
| ALOGV("nativeGetPreAutofocus E"); |
| int status, i; |
| |
| const int tryCount = 500; |
| |
| usleep(150000); |
| |
| for (i = 0 ; i < tryCount ; i ++) { |
| int err; |
| err = mFlite.gctrl(V4L2_CID_CAM_AUTO_FOCUS_RESULT, &status); |
| CHECK_ERR_N(err, ("nativeGetPreAutoFocus: error %d", err)) |
| //if (status != AF_STATUS_FOCUSING) |
| if (status != 0x1000) |
| break; |
| |
| usleep(10000); |
| } |
| |
| ALOGV("nativeGetPreAutofocus X %d", status); |
| return status; |
| } |
| |
| int SecCameraHardware::nativeGetAutoFocus() |
| { |
| ALOGV("nativeGetAutofocus E"); |
| int status, i; |
| /* AF completion takes more much time in case of night mode. |
| So be careful if you modify tryCount. */ |
| const int tryCount = 300; |
| |
| for (i = 0; i < tryCount; i ++) { |
| int err; |
| usleep(20000); |
| err = mFlite.gctrl(V4L2_CID_CAMERA_AUTO_FOCUS_DONE, &status); |
| CHECK_ERR_N(err, ("nativeGetAutofocus: error %d", err)); |
| if (status != 0x0) break; |
| } |
| |
| if (i == tryCount) |
| ALOGE("nativeGetAutoFocus: error, AF hasn't been finished yet."); |
| |
| ALOGV("nativeGetAutofocus X"); |
| return status; |
| } |
| |
| status_t SecCameraHardware::nativeCancelAutoFocus() |
| { |
| ALOGV("nativeCancelAutofocus E1"); |
| //#if NOTDEFINED |
| int err = mFlite.sctrl(V4L2_CID_CAMERA_SET_AUTO_FOCUS, AUTO_FOCUS_OFF); |
| CHECK_ERR(err, ("nativeCancelAutofocus: error, mFlite.sctrl")) |
| //#endif |
| ALOGV("nativeCancelAutofocus X2"); |
| return NO_ERROR; |
| } |
| |
| #ifndef FCJUNG |
| int SecCameraHardware::nativeGetFactoryOISDecenter() |
| { |
| ALOGD("nativeGetFactoryOISDecenter E"); |
| int check_done, i, err; |
| |
| err = NO_ERROR; |
| check_done = 0; |
| |
| for (i = 0 ; i < 500 ; i ++) { |
| usleep(10000); |
| err = mFlite.gctrl(V4L2_CID_CAMERA_FACTORY_OIS_DECENTER, &check_done); |
| CHECK_ERR_N(err, ("nativeGetFactoryOISDecenter: error %d", err)) |
| if (check_done != 0) |
| break; |
| } |
| |
| ALOGD("nativeGetFactoryOISDecenter X %d", check_done); |
| return check_done; |
| } |
| |
| int SecCameraHardware::nativeGetFactoryDownResult() |
| { |
| int factory_down_res, err; |
| |
| err = mFlite.gctrl(V4L2_CID_CAMERA_FACTORY_DOWN_RESULT, &factory_down_res); |
| CHECK_ERR(err, ("GetFactoryEndResult: error [%d]", factory_down_res)); |
| |
| ALOGD("%s res[%d]", __func__, factory_down_res); |
| |
| return factory_down_res; |
| } |
| |
| int SecCameraHardware::nativeGetFactoryEndResult() |
| { |
| int factory_end_res, err; |
| |
| err = mFlite.gctrl(V4L2_CID_CAMERA_FACTORY_END_RESULT, &factory_end_res); |
| CHECK_ERR(err, ("GetFactoryEndResult: error [%d]", factory_end_res)); |
| |
| ALOGD("%s res[%d]", __func__, factory_end_res); |
| |
| return factory_end_res; |
| } |
| |
| int SecCameraHardware::nativeGetFactoryIspFwVerData() |
| { |
| int err; |
| int factory_ver_res; |
| |
| err = mFlite.gctrl(V4L2_CID_CAMERA_FACTORY_ISP_FW_CHECK, &factory_ver_res); |
| CHECK_ERR(err, ("nativeGetFactoryIspFwVerData: error [%d]", factory_ver_res)); |
| |
| ALOGD("%s res[%d]", __func__, factory_ver_res); |
| |
| return factory_ver_res; |
| } |
| |
| int SecCameraHardware::nativeGetFactoryOisVerData() |
| { |
| int err; |
| int factory_ver_res; |
| |
| err = mFlite.gctrl(V4L2_CID_CAMERA_FACTORY_OIS_VER_CHECK, &factory_ver_res); |
| CHECK_ERR(err, ("nativeGetFactoryIspFwVerData: error [%d]", factory_ver_res)); |
| |
| ALOGD("%s res[%d]", __func__, factory_ver_res); |
| |
| return factory_ver_res; |
| |
| } |
| |
| int SecCameraHardware::nativeGetFactoryAFIntResult() |
| { |
| int factory_af_int_res, err; |
| |
| err = mFlite.gctrl(V4L2_CID_CAMERA_FACTORY_AF_INT_RESULT, &factory_af_int_res); |
| CHECK_ERR(err, ("GetFactoryEndResult: error [%d]", factory_af_int_res)); |
| |
| ALOGD("%s res[%d]", __func__, factory_af_int_res); |
| |
| return factory_af_int_res; |
| } |
| |
| int SecCameraHardware::nativeGetFactoryFlashCharge() |
| { |
| int flash_charge, err; |
| |
| err = mFlite.gctrl(V4L2_CID_CAMERA_FACTORY_FLASH_CHARGE, &flash_charge); |
| CHECK_ERR(err, ("GetFactoryEndResult: error [%d]", flash_charge)); |
| |
| ALOGD("%s res[%d]", __func__, flash_charge); |
| |
| return flash_charge; |
| } |
| #endif |
| |
| inline status_t SecCameraHardware::nativeSetParameters(cam_control_id id, int value, bool recordingMode) |
| { |
| int err = NO_ERROR; |
| |
| if (CC_LIKELY(!recordingMode)) |
| err = mFlite.sctrl(id, value); |
| else { |
| if (mCameraId == CAMERA_FACING_FRONT) |
| err = mFlite.sctrl(id, value); |
| } |
| |
| #if IS_FW_DEBUG |
| if (err < 0 && mCameraId == CAMERA_FACING_FRONT) |
| ISecCameraHardware::printDebugFirmware(); |
| #endif |
| |
| #if VENDOR_FEATURE |
| CHECK_ERR_N(err, ("nativeSetParameters X: error %d", err)) |
| #endif |
| |
| return NO_ERROR; |
| } |
| |
| inline status_t SecCameraHardware::nativeGetParameters(cam_control_id id, int *value, bool recordingMode) |
| { |
| int err = NO_ERROR; |
| |
| #ifdef APPLY_ESD |
| if(isResetedByESD == true) { |
| return NO_ERROR; |
| } |
| #endif |
| |
| if (CC_LIKELY(!recordingMode)) |
| err = mFlite.gctrl(id, value); |
| |
| CHECK_ERR_N(err, ("nativeGetParameters X: error %d", err)) |
| |
| return NO_ERROR; |
| } |
| |
| inline status_t SecCameraHardware::nativeGetNotiParameters(cam_control_id id, int *read_val) |
| { |
| int err; |
| |
| err = mFlite.notictrl(id, read_val); |
| |
| if (err < 0) { |
| ALOGD("nativeGetNotiParameters X: waiting timeout. NO ERROR %d", err); |
| } |
| |
| return err; |
| } |
| |
| #ifndef FCJUNG |
| inline status_t SecCameraHardware::nativeSetExtParameters(cam_control_id id, char *value, int size, bool recordingMode) |
| { |
| int err = NO_ERROR; |
| |
| if (CC_LIKELY(!recordingMode)) |
| err = mFlite.sctrl(id, value, size); |
| else |
| err = mFimc1.sctrl(id, value, size); |
| |
| CHECK_ERR_N(err, ("nativeSetParameters X: error %d", err)) |
| |
| return NO_ERROR; |
| } |
| |
| inline status_t SecCameraHardware::nativeGetExtParameters(cam_control_id id, char *value, int size, bool recordingMode) |
| { |
| int err = NO_ERROR; |
| |
| if (CC_LIKELY(!recordingMode)) |
| err = mFlite.gctrl(id, value, size); |
| else |
| err = mFimc1.gctrl(id, value, size); |
| |
| CHECK_ERR_N(err, ("nativeGetParameters X: error %d", err)) |
| |
| return NO_ERROR; |
| } |
| #endif |
| |
| void SecCameraHardware::setExifFixedAttribute() |
| { |
| CLEAR(mExifInfo); |
| /* 0th IFD TIFF Tags */ |
| /* Maker */ |
| strncpy((char *)mExifInfo.maker, Exif::DEFAULT_MAKER, sizeof(mExifInfo.maker) - 1); |
| |
| #if 0 |
| /* Model */ |
| property_get("ro.product.model", (char *)mExifInfo.model, Exif::DEFAULT_MODEL); |
| /* Software */ |
| property_get("ro.build.PDA", (char *)mExifInfo.software, Exif::DEFAULT_SOFTWARE); |
| #else |
| strcpy((char *)mExifInfo.model, "MODEL_NONE"); |
| strcpy((char *)mExifInfo.software, "SOFTWARE_NONE"); |
| #endif |
| |
| /* YCbCr Positioning */ |
| mExifInfo.ycbcr_positioning = Exif::DEFAULT_YCBCR_POSITIONING; |
| |
| /* 0th IFD Exif Private Tags */ |
| /* F Number */ |
| if (mCameraId == CAMERA_FACING_BACK) { |
| mExifInfo.fnumber.num = Exif::DEFAULT_BACK_FNUMBER_NUM; |
| mExifInfo.fnumber.den = Exif::DEFAULT_BACK_FNUMBER_DEN; |
| } else { |
| mExifInfo.fnumber.num = Exif::DEFAULT_FRONT_FNUMBER_NUM; |
| mExifInfo.fnumber.den = Exif::DEFAULT_FRONT_FNUMBER_DEN; |
| } |
| /* Exposure Program */ |
| mExifInfo.exposure_program = Exif::DEFAULT_EXPOSURE_PROGRAM; |
| /* Exif Version */ |
| memcpy(mExifInfo.exif_version, Exif::DEFAULT_EXIF_VERSION, sizeof(mExifInfo.exif_version)); |
| /* Aperture */ |
| double av = APEX_FNUM_TO_APERTURE((double)mExifInfo.fnumber.num/mExifInfo.fnumber.den); |
| mExifInfo.aperture.num = av*Exif::DEFAULT_APEX_DEN; |
| mExifInfo.aperture.den = Exif::DEFAULT_APEX_DEN; |
| /* Maximum lens aperture */ |
| mExifInfo.max_aperture.num = mExifInfo.aperture.num; |
| mExifInfo.max_aperture.den = mExifInfo.aperture.den; |
| /* Lens Focal Length */ |
| if (mCameraId == CAMERA_FACING_BACK) { |
| mExifInfo.focal_length.num = Exif::DEFAULT_BACK_FOCAL_LEN_NUM; |
| mExifInfo.focal_length.den = Exif::DEFAULT_BACK_FOCAL_LEN_DEN; |
| } else { |
| mExifInfo.focal_length.num = Exif::DEFAULT_FRONT_FOCAL_LEN_NUM; |
| mExifInfo.focal_length.den = Exif::DEFAULT_FRONT_FOCAL_LEN_DEN; |
| } |
| /* Color Space information */ |
| mExifInfo.color_space = Exif::DEFAULT_COLOR_SPACE; |
| /* Exposure Mode */ |
| mExifInfo.exposure_mode = Exif::DEFAULT_EXPOSURE_MODE; |
| |
| /* Sensing Method */ |
| mExifInfo.sensing_method = Exif::DEFAULT_SENSING_METHOD; |
| |
| /* 0th IFD GPS Info Tags */ |
| unsigned char gps_version[4] = {0x02, 0x02, 0x00, 0x00}; |
| memcpy(mExifInfo.gps_version_id, gps_version, sizeof(gps_version)); |
| |
| /* 1th IFD TIFF Tags */ |
| mExifInfo.compression_scheme = Exif::DEFAULT_COMPRESSION; |
| mExifInfo.x_resolution.num = Exif::DEFAULT_RESOLUTION_NUM; |
| mExifInfo.x_resolution.den = Exif::DEFAULT_RESOLUTION_DEN; |
| mExifInfo.y_resolution.num = Exif::DEFAULT_RESOLUTION_NUM; |
| mExifInfo.y_resolution.den = Exif::DEFAULT_RESOLUTION_DEN; |
| mExifInfo.resolution_unit = Exif::DEFAULT_RESOLUTION_UNIT; |
| } |
| |
| int SecCameraHardware::findMinFnumber(int value) |
| { |
| int f_num = 0; |
| switch(value) { |
| case 0: |
| f_num = 310; break; |
| case 1: |
| f_num = 330; break; |
| case 2: |
| f_num = 350; break; |
| case 3: |
| f_num = 370; break; |
| case 4: |
| f_num = 390; break; |
| case 5: |
| f_num = 440; break; |
| case 6: |
| f_num = 490; break; |
| case 7: |
| f_num = 540; break; |
| case 8: |
| f_num = 580; break; |
| case 9: |
| f_num = 630; break; |
| case 10: |
| f_num = 630; break; |
| default: |
| ALOGE("Invalid MinFnumber level = %d", value); |
| break; |
| } |
| |
| return f_num; |
| } |
| |
| int SecCameraHardware::findFocalLength(int value) |
| { |
| int fl = 0; |
| switch(value) { |
| case 0: |
| fl = 4300; break; |
| case 1: |
| fl = 5100; break; |
| case 2: |
| fl = 5800; break; |
| case 3: |
| fl = 6700; break; |
| case 4: |
| fl = 7600; break; |
| case 5: |
| fl = 9600; break; |
| case 6: |
| fl = 13200; break; |
| case 7: |
| fl = 17900; break; |
| case 8: |
| fl = 24100; break; |
| case 9: |
| fl = 33800; break; |
| case 10: |
| fl = 43000; break; |
| default: |
| ALOGE("Invalid FocalLength level = %d", value); |
| break; |
| } |
| |
| return fl; |
| } |
| |
| int SecCameraHardware::findFocalLength35mm(int value) |
| { |
| int fl_35 = 0; |
| switch(value) { |
| case 0: |
| fl_35 = 2400; break; |
| case 1: |
| fl_35 = 2800; break; |
| case 2: |
| fl_35 = 3300; break; |
| case 3: |
| fl_35 = 3700; break; |
| case 4: |
| fl_35 = 4300; break; |
| case 5: |
| fl_35 = 5400; break; |
| case 6: |
| fl_35 = 7400; break; |
| case 7: |
| fl_35 = 10000; break; |
| case 8: |
| fl_35 = 13500; break; |
| case 9: |
| fl_35 = 18900; break; |
| case 10: |
| fl_35 = 24000; break; |
| default: |
| ALOGE("Invalid 35mm level = %d", value); |
| break; |
| } |
| |
| return fl_35; |
| } |
| |
| void SecCameraHardware::findRTShutterSpeed(int32_t *rt_num, int32_t *rt_den, int *index) |
| { |
| int32_t ss_num_table[] = { |
| 16, 13, 10, 8, 6, 5, 4, 32, 25, 2, |
| 16, 13, 1, 8, 6, 5, 4, 1, 1, 1, |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 1, 1, 1, 1, 1, 1, |
| }; |
| |
| int32_t ss_den_table[] = { |
| 1, 1, 1, 1, 1, 1, 1, 10, 10, 1, |
| 10, 10, 1, 10, 10, 10, 10, 3, 4, 5, |
| 6, 8, 10, 13, 15, 20, 25, 30, 40, 50, |
| 60, 80, 100, 125, 160, 200, 250, 320, 400, 500, |
| 640, 800, 1000, 1250, 1600, 2000, |
| }; |
| |
| *rt_num = ss_num_table[*index]; |
| *rt_den = ss_den_table[*index]; |
| ALOGD("Shutter speed: index = %d, rt_num = %d, rt_den = %d", |
| *index, *rt_num, *rt_den); |
| |
| return; |
| } |
| |
| void SecCameraHardware::setExifChangedAttribute() |
| { |
| /* 0th IFD TIFF Tags */ |
| /* Width, Height */ |
| if (!mMovieMode) { |
| mExifInfo.width = mPictureSize.width; |
| mExifInfo.height = mPictureSize.height; |
| } else { |
| mExifInfo.width = mVideoSize.width; |
| mExifInfo.height = mVideoSize.height; |
| } |
| |
| /* ISP firmware version */ |
| char unique_id[12] = {'\0',}; |
| |
| mFlite.gctrl(V4L2_CID_CAM_SENSOR_FW_VER, unique_id, 12); |
| ALOGD("Exif: unique_id = %s", unique_id); |
| |
| memset(mExifInfo.unique_id, 0, sizeof(mExifInfo.unique_id)); |
| memcpy(mExifInfo.unique_id, unique_id, sizeof(mExifInfo.unique_id)-1); |
| |
| /* Orientation */ |
| switch (mParameters.getInt(CameraParameters::KEY_ROTATION)) { |
| case 0: |
| mExifInfo.orientation = EXIF_ORIENTATION_UP; |
| break; |
| case 90: |
| mExifInfo.orientation = EXIF_ORIENTATION_90; |
| break; |
| case 180: |
| mExifInfo.orientation = EXIF_ORIENTATION_180; |
| break; |
| case 270: |
| mExifInfo.orientation = EXIF_ORIENTATION_270; |
| break; |
| default: |
| mExifInfo.orientation = EXIF_ORIENTATION_UP; |
| break; |
| } |
| ALOGD("Exif: setRotation = %d, orientation = %d", mParameters.getInt(CameraParameters::KEY_ROTATION), mExifInfo.orientation); |
| |
| /* Date time */ |
| time_t rawtime; |
| struct tm *timeinfo; |
| time(&rawtime); |
| timeinfo = localtime(&rawtime); |
| strftime((char *)mExifInfo.date_time, 20, "%Y:%m:%d %H:%M:%S", timeinfo); |
| |
| /* 0th IFD Exif Private Tags */ |
| /* Exposure Time */ |
| int err; |
| int exposureTimeNum; |
| int exposureTimeDen; |
| int rt_num, rt_den; |
| |
| if (mFlite.mIsInternalISP) { |
| err = mFlite.gctrl(V4L2_CID_IS_CAMERA_EXIF_SHUTTERSPEED, &exposureTimeDen); |
| mExifInfo.exposure_time.den = exposureTimeDen; |
| mExifInfo.exposure_time.num = 1; |
| } else { |
| err = mFlite.gctrl(V4L2_CID_EXIF_EXPOSURE_TIME_NUM, &exposureTimeNum); |
| if (err < 0) |
| ALOGE("setExifChangedAttribute: exposure time num err = %d", err); |
| err = mFlite.gctrl(V4L2_CID_EXIF_EXPOSURE_TIME_DEN, &exposureTimeDen); |
| if (err < 0) |
| ALOGE("setExifChangedAttribute: exposure time den err = %d", err); |
| |
| mExifInfo.exposure_time.num = exposureTimeNum; |
| mExifInfo.exposure_time.den = exposureTimeDen; |
| ALOGD("Exif: exposure time num = %d, den = %d", exposureTimeNum, exposureTimeDen); |
| } |
| |
| /* Shutter Speed */ |
| int tv; |
| err = mFlite.gctrl(V4L2_CID_EXIF_SHUTTER_SPEED_NUM, &tv); |
| if (err < 0) |
| ALOGE("setExifChangedAttribute: shutter speed num err = %d", err); |
| mExifInfo.shutter_speed.num = tv; |
| mExifInfo.shutter_speed.den = Exif::DEFAULT_APEX_DEN; |
| ALOGD("Exif: shutter speed num = %d, den = %d", mExifInfo.shutter_speed.num, mExifInfo.shutter_speed.den); |
| |
| /* Flash */ |
| if (mCameraId == CAMERA_FACING_BACK) { |
| err = mFlite.gctrl(V4L2_CID_CAMERA_EXIF_FLASH, (int *)&mExifInfo.flash); |
| if (err < 0) |
| ALOGE("setExifChangedAttribute: Flash value err = %d", err); |
| ALOGD("mEixfInfo.flash = %x", mExifInfo.flash); |
| } |
| |
| /* Color Space information */ |
| mExifInfo.color_space = Exif::DEFAULT_COLOR_SPACE; |
| |
| /* User Comments */ |
| strncpy((char *)mExifInfo.user_comment, Exif::DEFAULT_USERCOMMENTS, sizeof(mExifInfo.user_comment) - 1); |
| /* ISO Speed Rating */ |
| err = mFlite.gctrl(V4L2_CID_CAMERA_EXIF_ISO, (int *)&mExifInfo.iso_speed_rating); |
| if (err < 0) |
| ALOGE("setExifChangedAttribute: ISO Speed Rating err = %d", err); |
| |
| /* Brightness */ |
| int bv; |
| err = mFlite.gctrl(V4L2_CID_CAMERA_EXIF_BV, &bv); |
| if (err < 0) |
| ALOGE("setExifChangedAttribute: Brightness value err = %d", err); |
| mExifInfo.brightness.num = bv; |
| mExifInfo.brightness.den = Exif::DEFAULT_APEX_DEN; |
| |
| /* Aperture */ |
| if (mCameraId == CAMERA_FACING_BACK) { |
| int av; |
| err = mFlite.gctrl(V4L2_CID_CAMERA_EXIF_AV, &av); |
| mExifInfo.aperture.num = av; |
| mExifInfo.aperture.den = Exif::DEFAULT_APEX_DEN; |
| ALOGD("Exif aperture num = %d", av); |
| } else { |
| double av = APEX_FNUM_TO_APERTURE((double)mExifInfo.fnumber.num/mExifInfo.fnumber.den); |
| mExifInfo.aperture.num = av*Exif::DEFAULT_APEX_DEN; |
| mExifInfo.aperture.den = Exif::DEFAULT_APEX_DEN; |
| } |
| |
| /* F Number */ |
| if (mCameraId == CAMERA_FACING_BACK) { |
| int fnumber; |
| err = mFlite.gctrl(V4L2_CID_EXIF_F_NUMBER, &fnumber); |
| if (err < 0) |
| ALOGE("setExifChangedAttribute: F Number err = %d", err); |
| mExifInfo.fnumber.num = fnumber; |
| mExifInfo.fnumber.den = Exif::DEFAULT_APEX_DEN; |
| } else if (mCameraId == CAMERA_FACING_FRONT) { |
| mExifInfo.fnumber.num = Exif::DEFAULT_FRONT_FNUMBER_NUM; |
| mExifInfo.fnumber.den = Exif::DEFAULT_FRONT_FNUMBER_DEN; |
| } |
| |
| /* Lens Focal Length */ |
| if (mCameraId == CAMERA_FACING_BACK) { |
| int focal_length; |
| err = mFlite.gctrl(V4L2_CID_CAMERA_EXIF_FL, &focal_length); |
| if (err < 0) |
| ALOGE("setExifChangedAttribute: Focal length err = %d", err); |
| mExifInfo.focal_length.num = focal_length; |
| mExifInfo.focal_length.den = Exif::DEFAULT_BACK_FOCAL_LEN_DEN; |
| } else if (mCameraId == CAMERA_FACING_FRONT) { |
| mExifInfo.focal_length.num = Exif::DEFAULT_FRONT_FOCAL_LEN_NUM; |
| mExifInfo.focal_length.den = Exif::DEFAULT_FRONT_FOCAL_LEN_DEN; |
| } |
| ALOGD("Exif num = %d, den = %d", mExifInfo.focal_length.num, mExifInfo.focal_length.den); |
| |
| /* Lens Focal Length in 35mm film*/ |
| if (mCameraId == CAMERA_FACING_BACK) { |
| int focal_35mm_length; |
| err = mFlite.gctrl(V4L2_CID_CAMERA_EXIF_FL_35mm, &focal_35mm_length); |
| if (err < 0) |
| ALOGE("setExifChangedAttribute: Focal length 35mm err = %d", err); |
| mExifInfo.focal_35mm_length = focal_35mm_length; |
| ALOGD("Exif focal length 35mm = %d", mExifInfo.focal_35mm_length); |
| } |
| |
| /* Maximum lens aperture = Minimum F number */ |
| //ALOGD("Exif mZoomCurrLevel = %d", mZoomCurrLevel); |
| double max_av; |
| max_av = 326;//(2 * EXIF_LOG2((double)findMinFnumber(mZoomCurrLevel)/Exif::DEFAULT_APEX_DEN)) * Exif::DEFAULT_APEX_DEN; |
| ALOGD("Exif max av = %f, Exif max av = %d", max_av, (int)max_av); |
| mExifInfo.max_aperture.num = (int)max_av; |
| mExifInfo.max_aperture.den = Exif::DEFAULT_APEX_DEN; |
| |
| /* Exposure Bias */ |
| int ebv; |
| err = mFlite.gctrl(V4L2_CID_CAMERA_EXIF_EBV, &ebv); |
| /* Exposure Bias Value quantization */ |
| // if (mPASMMode == MODE_SNOW) |
| // ebv = 100; |
| // else if (mPASMMode == MODE_BEACH) |
| // ebv = 70; |
| // else if (mPASMMode == MODE_CANDLE) |
| // ebv = -100; |
| // else |
| ebv = 10 * (int)(ROUND(((double)ebv / 10), 0)); |
| mExifInfo.exposure_bias.num = ebv; |
| mExifInfo.exposure_bias.den = Exif::DEFAULT_APEX_DEN; |
| ALOGD("Exif exposure bias value = %d", ebv); |
| |
| /* Metering Mode */ |
| if (mFlite.mIsInternalISP) { |
| mExifInfo.metering_mode = EXIF_METERING_AVERAGE; |
| } else { |
| const char *metering = mParameters.get("metering"); |
| if (!metering || !strcmp(metering, "center")) |
| mExifInfo.metering_mode = EXIF_METERING_CENTER; |
| else if (!strcmp(metering, "spot")) |
| mExifInfo.metering_mode = EXIF_METERING_SPOT; |
| else if (!strcmp(metering, "matrix")) |
| mExifInfo.metering_mode = EXIF_METERING_AVERAGE; |
| } |
| |
| /* White Balance */ |
| const char *wb = mParameters.get(CameraParameters::KEY_WHITE_BALANCE); |
| if (!wb || !strcmp(wb, CameraParameters::WHITE_BALANCE_AUTO)) |
| mExifInfo.white_balance = EXIF_WB_AUTO; |
| else |
| mExifInfo.white_balance = EXIF_WB_MANUAL; |
| |
| /* Scene Capture Type */ |
| switch (mSceneMode) { |
| case SCENE_MODE_PORTRAIT: |
| mExifInfo.scene_capture_type = EXIF_SCENE_PORTRAIT; |
| break; |
| case SCENE_MODE_LANDSCAPE: |
| mExifInfo.scene_capture_type = EXIF_SCENE_LANDSCAPE; |
| break; |
| case SCENE_MODE_NIGHTSHOT: |
| mExifInfo.scene_capture_type = EXIF_SCENE_NIGHT; |
| break; |
| default: |
| mExifInfo.scene_capture_type = EXIF_SCENE_STANDARD; |
| break; |
| } |
| |
| /* Light Source */ |
| switch (mExifLightSource) { |
| case V4L2_WHITE_BALANCE_AUTO: |
| mExifInfo.light_source = 0; |
| break; |
| case V4L2_WHITE_BALANCE_SUNNY: |
| mExifInfo.light_source = 1; |
| break; |
| case V4L2_WHITE_BALANCE_CLOUDY: |
| mExifInfo.light_source = 10; |
| break; |
| case V4L2_WHITE_BALANCE_FLUORESCENT_H: |
| mExifInfo.light_source = 2; |
| break; |
| case V4L2_WHITE_BALANCE_FLUORESCENT_L: |
| mExifInfo.light_source = 2; |
| break; |
| case V4L2_WHITE_BALANCE_TUNGSTEN: |
| mExifInfo.light_source = 3; |
| break; |
| case V4L2_WHITE_BALANCE_CUSTOM: |
| case V4L2_WHITE_BALANCE_K: |
| default: |
| mExifInfo.light_source = 0; |
| break; |
| } |
| ALOGD("mExifLightSource = %d, mExifInfo.light_source = %d", mExifLightSource, mExifInfo.light_source); |
| |
| /* Digital Zoom Ratio */ |
| mExifInfo.digital_zoom_ratio.num = 100; |
| mExifInfo.digital_zoom_ratio.den = Exif::DEFAULT_APEX_DEN; |
| |
| /* 0th IFD GPS Info Tags */ |
| const char *strLatitude = mParameters.get(CameraParameters::KEY_GPS_LATITUDE); |
| const char *strLogitude = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE); |
| const char *strAltitude = mParameters.get(CameraParameters::KEY_GPS_ALTITUDE); |
| |
| if (strLatitude != NULL && strLogitude != NULL && strAltitude != NULL) { |
| if (atof(strLatitude) > 0) |
| strncpy((char *)mExifInfo.gps_latitude_ref, "N", sizeof(mExifInfo.gps_latitude_ref)); |
| else |
| strncpy((char *)mExifInfo.gps_latitude_ref, "S", sizeof(mExifInfo.gps_latitude_ref)); |
| |
| if (atof(strLogitude) > 0) |
| strncpy((char *)mExifInfo.gps_longitude_ref, "E", sizeof(mExifInfo.gps_longitude_ref)); |
| else |
| strncpy((char *)mExifInfo.gps_longitude_ref, "W", sizeof(mExifInfo.gps_longitude_ref)); |
| |
| if (atof(strAltitude) > 0) |
| mExifInfo.gps_altitude_ref = 0; |
| else |
| mExifInfo.gps_altitude_ref = 1; |
| |
| double latitude = fabs(atof(strLatitude)); |
| double longitude = fabs(atof(strLogitude)); |
| double altitude = fabs(atof(strAltitude)); |
| |
| mExifInfo.gps_latitude[0].num = (uint32_t)latitude; |
| mExifInfo.gps_latitude[0].den = 1; |
| mExifInfo.gps_latitude[1].num = (uint32_t)((latitude - mExifInfo.gps_latitude[0].num) * 60); |
| mExifInfo.gps_latitude[1].den = 1; |
| mExifInfo.gps_latitude[2].num = (uint32_t)(round((((latitude - mExifInfo.gps_latitude[0].num) * 60) - |
| mExifInfo.gps_latitude[1].num) * 60)); |
| mExifInfo.gps_latitude[2].den = 1; |
| |
| mExifInfo.gps_longitude[0].num = (uint32_t)longitude; |
| mExifInfo.gps_longitude[0].den = 1; |
| mExifInfo.gps_longitude[1].num = (uint32_t)((longitude - mExifInfo.gps_longitude[0].num) * 60); |
| mExifInfo.gps_longitude[1].den = 1; |
| mExifInfo.gps_longitude[2].num = (uint32_t)(round((((longitude - mExifInfo.gps_longitude[0].num) * 60) - |
| mExifInfo.gps_longitude[1].num) * 60)); |
| mExifInfo.gps_longitude[2].den = 1; |
| |
| mExifInfo.gps_altitude.num = (uint32_t)altitude; |
| mExifInfo.gps_altitude.den = 1; |
| |
| const char *strTimestamp = mParameters.get(CameraParameters::KEY_GPS_TIMESTAMP); |
| long timestamp = 0; |
| if (strTimestamp) |
| timestamp = atol(strTimestamp); |
| |
| struct tm tm_data; |
| gmtime_r(×tamp, &tm_data); |
| mExifInfo.gps_timestamp[0].num = tm_data.tm_hour; |
| mExifInfo.gps_timestamp[0].den = 1; |
| mExifInfo.gps_timestamp[1].num = tm_data.tm_min; |
| mExifInfo.gps_timestamp[1].den = 1; |
| mExifInfo.gps_timestamp[2].num = tm_data.tm_sec; |
| mExifInfo.gps_timestamp[2].den = 1; |
| strftime((char *)mExifInfo.gps_datestamp, sizeof(mExifInfo.gps_datestamp), "%Y:%m:%d", &tm_data); |
| |
| const char *progressingMethod = mParameters.get(CameraParameters::KEY_GPS_PROCESSING_METHOD); |
| if (progressingMethod) { |
| size_t len = strlen(progressingMethod); |
| if (len >= sizeof(mExifInfo.gps_processing_method)) |
| len = sizeof(mExifInfo.gps_processing_method) - 1; |
| |
| CLEAR(mExifInfo.gps_processing_method); |
| strncpy((char *)mExifInfo.gps_processing_method, progressingMethod, len); |
| } |
| |
| mExifInfo.enableGps = true; |
| } else { |
| mExifInfo.enableGps = false; |
| } |
| |
| /* 1th IFD TIFF Tags */ |
| mExifInfo.widthThumb = mThumbnailSize.width; |
| mExifInfo.heightThumb = mThumbnailSize.height; |
| |
| } |
| |
| int SecCameraHardware::internalGetJpegForISP(int *postviewOffset) |
| { |
| int jpegSize = 0; |
| int thumbSize = 0; |
| int jpegOffset; |
| int thumbOffset; |
| int err; |
| |
| err = mFlite.gctrl(V4L2_CID_CAM_JPEG_MAIN_SIZE, &jpegSize); |
| CHECK_ERR(err, ("getJpeg: error %d, jpeg size", err)); |
| |
| err = mFlite.gctrl(V4L2_CID_CAM_JPEG_MAIN_OFFSET, &jpegOffset); |
| CHECK_ERR(err, ("getJpeg: error %d, jpeg offset", err)); |
| |
| err = mFlite.gctrl(V4L2_CID_CAM_JPEG_THUMB_SIZE, &thumbSize); |
| CHECK_ERR(err, ("getJpeg: error %d, thumb size", err)); |
| |
| err = mFlite.gctrl(V4L2_CID_CAM_JPEG_THUMB_OFFSET, &thumbOffset); |
| CHECK_ERR(err, ("getJpeg: error %d, thumb offset", err)); |
| |
| /* EXIF */ |
| LOG_PERFORMANCE_START(1); |
| |
| setExifChangedAttribute(); |
| |
| sp<MemoryHeapBase> exifHeap = new MemoryHeapBase(EXIF_MAX_LEN); |
| if (!initialized(exifHeap)) { |
| ALOGE("getJpeg: error, could not initialize Camera exif heap"); |
| return UNKNOWN_ERROR; |
| } |
| |
| Exif exif(mCameraId); |
| uint32_t exifSize; |
| uint8_t *thumb = (uint8_t *)mRawHeap->data + thumbOffset; |
| if (mThumbnailSize.width == 0 || mThumbnailSize.height == 0) |
| exifSize = exif.make(exifHeap->base(), &mExifInfo); |
| else |
| exifSize = exif.make(exifHeap->base(), &mExifInfo, exifHeap->getSize(),thumb, thumbSize); |
| if (CC_UNLIKELY(!exifSize)) { |
| ALOGE("getJpeg: error, fail to make EXIF"); |
| return UNKNOWN_ERROR; |
| } |
| |
| /* Jpeg */ |
| mPictureFrameSize = jpegSize + exifSize; |
| /* picture frame size is should be calculated before call allocateSnapshotHeap */ |
| if (!allocateSnapshotHeap()) { |
| ALOGE("getJpeg: error, allocateSnapshotHeap"); |
| return UNKNOWN_ERROR; |
| } |
| |
| uint8_t *jpeg = (uint8_t *)mRawHeap->data + jpegOffset; |
| memcpy(mJpegHeap->data, jpeg, 2); |
| memcpy((uint8_t *)mJpegHeap->data + 2, exifHeap->base(), exifSize); |
| memcpy((uint8_t *)mJpegHeap->data + 2 + exifSize, jpeg + 2, jpegSize - 2); |
| |
| LOG_PERFORMANCE_END(1, "jpeg + exif"); |
| |
| /* Postview */ |
| err = mFlite.gctrl(V4L2_CID_CAM_JPEG_POSTVIEW_OFFSET, postviewOffset); |
| CHECK_ERR(err, ("getJpeg: error %d, postview offset", err)); |
| |
| return 0; |
| } |
| |
| #if !defined(REAR_USE_YUV_CAPTURE) |
| int SecCameraHardware::internalGetJpegForSocJpeg(int *postviewOffset) |
| { |
| int32_t maxJpegSize, jpegOffset, rawThumbSize, rawThumbOffset; |
| |
| int err; |
| |
| err = mFlite.gctrl(V4L2_CID_CAM_JPEG_MAIN_SIZE, &maxJpegSize); |
| CHECK_ERR(err, ("getJpeg: error %d, jpeg size", err)); |
| |
| err = mFlite.gctrl(V4L2_CID_CAM_JPEG_MAIN_OFFSET, &jpegOffset); |
| CHECK_ERR(err, ("getJpeg: error %d, jpeg offset", err)); |
| |
| err = mFlite.gctrl(V4L2_CID_CAM_JPEG_THUMB_SIZE, &rawThumbSize); |
| CHECK_ERR(err, ("getJpeg: error %d, thumb size", err)); |
| |
| err = mFlite.gctrl(V4L2_CID_CAM_JPEG_THUMB_OFFSET, &rawThumbOffset); |
| CHECK_ERR(err, ("getJpeg: error %d, thumb offset", err)); |
| |
| #if 0 |
| ALOGV("mRawHeap addr=0x%x size=%d, maxJpegSize=%d, rawThumbSize=%d", (uint32_t)(mRawHeap->data), mRawHeap->getSize(), |
| maxJpegSize, rawThumbSize); |
| #else |
| ALOGV("mRawHeap addr=0x%x size=%d, maxJpegSize=%d, rawThumbSize=%d", (uint32_t)(mRawHeap->data), mRawHeap->size, |
| maxJpegSize, rawThumbSize); |
| #endif |
| sp<MemoryHeapBase> jpegHeap = new MemoryHeapBase(maxJpegSize); |
| sp<MemoryHeapBase> rawThumbnailHeap = new MemoryHeapBase(rawThumbSize); |
| |
| uint32_t jpegSize = maxJpegSize; |
| /* mRawHeap->getSize(); */ |
| err = extractJpegAndRawThumb((uint32_t)jpegOffset, (uint32_t *)&rawThumbSize, (uint32_t)rawThumbOffset, |
| mRawHeap->data, &jpegSize, jpegHeap->base(), rawThumbnailHeap->base()); |
| if (err == false) { |
| ALOGE("getJpeg: error, could not extract Jpeg and YUV"); |
| return UNKNOWN_ERROR; |
| } |
| |
| struct jpeg_encode_param encodeThumbParam; |
| CLEAR(encodeThumbParam); |
| if (!jpegOpenEncoding(encodeThumbParam)) { |
| ALOGE("internalGetJpegForSocJpeg: error, jpegInitEncoding"); |
| return UNKNOWN_ERROR; |
| } |
| |
| encodeThumbParam.srcBuf = rawThumbnailHeap->base(); |
| encodeThumbParam.srcWidth = mThumbnailSize.width; |
| encodeThumbParam.srcHeight = mThumbnailSize.height; |
| encodeThumbParam.srcBufSize = rawThumbSize; |
| encodeThumbParam.srcFormat = V4L2_PIX_FMT_UYVY; |
| #ifdef SAMSUNG_EXYNOS4210 |
| encodeThumbParam.destJpegQuality = QUALITY_LEVEL_4; |
| #else |
| encodeThumbParam.destJpegQuality = ExynosJpegEncoder::QUALITY_LEVEL_4; |
| #endif |
| |
| if (!jpegExecuteEncoding(encodeThumbParam)) { |
| ALOGE("internalGetJpegForSocJpeg: error, jpegStartEncoding"); |
| return UNKNOWN_ERROR; |
| } |
| |
| /* EXIF */ |
| LOG_PERFORMANCE_START(1); |
| |
| setExifChangedAttribute(); |
| |
| sp<MemoryHeapBase> exifHeap = new MemoryHeapBase(EXIF_MAX_LEN); |
| if (!initialized(exifHeap)) { |
| ALOGE("getJpeg: error, could not initialize Camera exif heap"); |
| return UNKNOWN_ERROR; |
| } |
| |
| Exif exif(mCameraId); |
| uint32_t exifSize; |
| if (mThumbnailSize.width == 0 || mThumbnailSize.height == 0) |
| exifSize = exif.make(exifHeap->base(), &mExifInfo); |
| else |
| exifSize = exif.make(exifHeap->base(), &mExifInfo, exifHeap->getSize(), |
| (uint8_t *)encodeThumbParam.destJpegBuf, encodeThumbParam.destJpegSize); |
| if (CC_UNLIKELY(!exifSize)) { |
| ALOGE("getJpeg: error, fail to make EXIF"); |
| return UNKNOWN_ERROR; |
| } |
| |
| jpegCloseEncoding(encodeThumbParam); |
| |
| /* Jpeg */ |
| mPictureFrameSize = jpegSize + exifSize; |
| /* picture frame size is should be calculated before call allocateSnapshotHeap */ |
| if (!allocateSnapshotHeap()) { |
| ALOGE("getJpeg: error, allocateSnapshotHeap"); |
| return UNKNOWN_ERROR; |
| } |
| |
| memcpy(mJpegHeap->data, jpegHeap->base(), 2); |
| memcpy((uint8_t *)(mJpegHeap->data) + 2, exifHeap->base(), exifSize); |
| memcpy((uint8_t *)(mJpegHeap->data) + 2 + exifSize, (uint8_t *)(jpegHeap->base()) + 2, jpegSize - 2); |
| |
| LOG_PERFORMANCE_END(1, "jpeg + exif"); |
| |
| /* Postview */ |
| #ifdef NOTDEFINED |
| err = mFlite.gctrl(V4L2_CID_CAM_JPEG_POSTVIEW_OFFSET, postviewOffset); |
| CHECK_ERR(err, ("getJpeg: error %d, postview offset", err)); |
| #else |
| *postviewOffset = 0; |
| #endif |
| |
| return 0; |
| } |
| #endif |
| |
| #ifdef SAMSUNG_EXYNOS4210 |
| int SecCameraHardware::internalGetJpegForSocYuv(int *postviewOffset) |
| { |
| int jpegFd = api_jpeg_encode_init(); |
| CHECK_ERR_N(jpegFd, ("getEncodedJpeg: error %d, api_jpeg_encode_init", jpegFd)); |
| |
| sp<MemoryHeapBase> rawThumbnail; |
| |
| int jpegSrcFrameSize; |
| uint8_t *inBuf, *outBuf, *jpeg, *thumb; |
| int jpegSize = 0; |
| int thumbSize = 0; |
| struct jpeg_enc_param jpegParam; |
| |
| Exif exif(mCameraId); |
| uint32_t exifSize; |
| |
| bool thumbnail = false; |
| |
| /* Thumbnail */ |
| LOG_PERFORMANCE_START(1); |
| |
| if (mThumbnailSize.width == 0 || mThumbnailSize.height == 0) |
| goto encode_jpeg; |
| |
| jpegSrcFrameSize = mThumbnailSize.width*mThumbnailSize.height * 2; |
| rawThumbnail = new MemoryHeapBase(jpegSrcFrameSize); |
| LOG_PERFORMANCE_START(3); |
| scaleDownYuv422((uint8_t *)mRawHeap->data, (int)mPictureSize.width, (int)mPictureSize.height, |
| (uint8_t *)rawThumbnail->base(), (int)mThumbnailSize.width, (int)mThumbnailSize.height); |
| LOG_PERFORMANCE_END(3, "scaleDownYuv422"); |
| CLEAR(jpegParam); |
| jpegParam.width = mThumbnailSize.width; |
| jpegParam.height = mThumbnailSize.height; |
| jpegParam.in_fmt = YUV_422; |
| jpegParam.out_fmt = JPEG_422; |
| jpegParam.quality = QUALITY_LEVEL_4; |
| api_jpeg_set_encode_param(&jpegParam); |
| |
| inBuf = (uint8_t *)api_jpeg_get_encode_in_buf(jpegFd, jpegSrcFrameSize); |
| if (inBuf == NULL) { |
| ALOGW("getEncodedJpeg: error, thumbnail api_jpeg_get_encode_in_buf"); |
| goto encode_jpeg; |
| } |
| memcpy(inBuf, rawThumbnail->base(), jpegSrcFrameSize); |
| |
| outBuf = (uint8_t *)api_jpeg_get_encode_out_buf(jpegFd); |
| if (outBuf == NULL) { |
| ALOGW("getEncodedJpeg: error, thumbnail api_jpeg_get_encode_out_buf"); |
| goto encode_jpeg; |
| } |
| |
| if (api_jpeg_encode_exe(jpegFd, &jpegParam) != JPEG_ENCODE_OK) { |
| ALOGE("getEncodedJpeg: error, thumbnail api_jpeg_get_encode_in_buf"); |
| goto encode_jpeg; |
| } |
| thumbSize = jpegParam.size; |
| thumbnail = true; |
| |
| LOG_PERFORMANCE_END(1, "encode thumbnail"); |
| |
| encode_jpeg: |
| /* EXIF */ |
| setExifChangedAttribute(); |
| |
| sp<MemoryHeapBase> exifHeap = new MemoryHeapBase(EXIF_MAX_LEN); |
| if (!initialized(exifHeap)) { |
| ALOGE("getJpeg: error, could not initialize Camera exif heap"); |
| return UNKNOWN_ERROR; |
| } |
| |
| if (!thumbnail) |
| exifSize = exif.make(exifHeap->base(), &mExifInfo); |
| else |
| exifSize = exif.make(exifHeap->base(), &mExifInfo, exifHeap->getSize(), outBuf, thumbSize); |
| if (CC_UNLIKELY(!exifSize)) { |
| ALOGE("getJpeg: error, fail to make EXIF"); |
| return UNKNOWN_ERROR; |
| } |
| |
| /* Jpeg */ |
| LOG_PERFORMANCE_START(2); |
| |
| CLEAR(jpegParam); |
| jpegParam.width = mPictureSize.width; |
| jpegParam.height = mPictureSize.height; |
| jpegParam.in_fmt = YUV_422; |
| jpegParam.out_fmt = JPEG_422; |
| jpegParam.quality = QUALITY_LEVEL_1; |
| api_jpeg_set_encode_param(&jpegParam); |
| |
| jpegSrcFrameSize = mPictureSize.width * mPictureSize.height * 2; |
| inBuf = (uint8_t *)api_jpeg_get_encode_in_buf(jpegFd, jpegSrcFrameSize); |
| if (inBuf == NULL) { |
| ALOGW("getEncodedJpeg: error, api_jpeg_get_encode_in_buf"); |
| goto out; |
| } |
| LOG_PERFORMANCE_START(5); |
| memcpy(inBuf, mRawHeap->data, jpegSrcFrameSize); |
| LOG_PERFORMANCE_END(5, "memcpy jpeg"); |
| outBuf = (uint8_t *)api_jpeg_get_encode_out_buf(jpegFd); |
| if (outBuf == NULL) { |
| ALOGW("getEncodedJpeg: error, api_jpeg_get_encode_out_buf"); |
| goto out; |
| } |
| |
| if (api_jpeg_encode_exe(jpegFd, &jpegParam) != JPEG_ENCODE_OK) { |
| ALOGE("getEncodedJpeg: error, api_jpeg_get_encode_in_buf"); |
| goto out; |
| } |
| jpegSize = jpegParam.size; |
| |
| mPictureFrameSize = jpegSize + exifSize; |
| /* picture frame size is should be calculated before call allocateSnapshotHeap */ |
| if (!allocateSnapshotHeap()) |
| ALOGE("getJpeg: error, allocateSnapshotHeap"); |
| return UNKNOWN_ERROR; |
| |
| LOG_PERFORMANCE_END(2, "encode jpeg"); |
| |
| LOG_PERFORMANCE_START(4); |
| jpeg = outBuf; |
| memcpy(mJpegHeap->data, jpeg, 2); |
| memcpy((uint8_t *)mJpegHeap->data + 2, exifHeap->base(), exifSize); |
| memcpy((uint8_t *)mJpegHeap->data + 2 + exifSize, jpeg + 2, jpegSize - 2); |
| LOG_PERFORMANCE_END(4, "jpeg + exif"); |
| |
| /* Postview */ |
| *postviewOffset = 0; |
| |
| api_jpeg_encode_deinit(jpegFd); |
| return 0; |
| |
| out: |
| api_jpeg_encode_deinit(jpegFd); |
| return -1; |
| } |
| #else /* !SAMSUNG_EXYNOS4210 */ |
| |
| int SecCameraHardware::internalGetJpegForSocYuvWithZoom(int *postviewOffset) |
| #if VENDOR_FEATURE |
| { |
| ExynosBuffer thumbnailJpeg; |
| ExynosBuffer rawThumbnail; |
| ExynosBuffer jpegOutBuf; |
| ExynosBuffer exifOutBuf; |
| ExynosBuffer nullBuf; |
| Exif exif(mCameraId); |
| int i; |
| |
| uint8_t *thumb; |
| bool thumbnail = false; |
| int err; |
| int ret = UNKNOWN_ERROR; |
| |
| int32_t jpegSize = -1; |
| int32_t jpegOffset; |
| int32_t thumbSize; |
| int32_t thumbOffset; |
| |
| err = mFlite.gctrl(V4L2_CID_CAM_JPEG_MAIN_SIZE, &jpegSize); |
| CHECK_ERR(err, ("getJpeg: error %d, jpeg size", err)); |
| |
| ALOGD("internalgetJpeg: jpegSize = %d", jpegSize); |
| |
| err = mFlite.gctrl(V4L2_CID_CAM_JPEG_MAIN_OFFSET, &jpegOffset); |
| CHECK_ERR(err, ("getJpeg: error %d, jpeg offset", err)); |
| |
| err = mFlite.gctrl(V4L2_CID_CAM_JPEG_THUMB_SIZE, &thumbSize); |
| CHECK_ERR(err, ("getJpeg: error %d, thumb size", err)); |
| |
| err = mFlite.gctrl(V4L2_CID_CAM_JPEG_THUMB_OFFSET, &thumbOffset); |
| CHECK_ERR(err, ("getJpeg: error %d, thumb offset", err)); |
| |
| s5p_rect zoomRect; |
| ALOGV("DEBUG(%s)(%d): picture size(%d/%d)", __FUNCTION__, __LINE__, mPictureSize.width, mPictureSize.height); |
| ALOGV("DEBUG(%s)(%d): thumbnail size(%d/%d)", __FUNCTION__, __LINE__, mThumbnailSize.width, mThumbnailSize.height); |
| |
| zoomRect.w = mPictureSize.width * 10 / mZoomValue; |
| zoomRect.h = mPictureSize.height * 10 / mZoomValue; |
| |
| if (zoomRect.w % 2) |
| zoomRect.w -= 1; |
| |
| if (zoomRect.h % 2) |
| zoomRect.h -= 1; |
| |
| zoomRect.x = (mPictureSize.width - zoomRect.w) / 2; |
| zoomRect.y = (mPictureSize.height - zoomRect.h) / 2; |
| |
| if (zoomRect.x % 2) |
| zoomRect.x -= 1; |
| |
| if (zoomRect.y % 2) |
| zoomRect.y -= 1; |
| |
| /* Making thumbnail image */ |
| if (mThumbnailSize.width == 0 || mThumbnailSize.height == 0) |
| goto encodeJpeg; |
| |
| /* alloc rawThumbnail */ |
| rawThumbnail.size.extS[0] = mThumbnailSize.width * mThumbnailSize.height * 2; |
| if (allocMem(mIonCameraClient, &rawThumbnail, 1 << 1) == false) { |
| ALOGE("ERR(%s): rawThumbnail allocMem() fail", __func__); |
| goto destroyMem; |
| } else { |
| ALOGV("DEBUG(%s): rawThumbnail allocMem adr(%p), size(%d), ion(%d)", __FUNCTION__, |
| rawThumbnail.virt.extP[0], rawThumbnail.size.extS[0], mIonCameraClient); |
| memset(rawThumbnail.virt.extP[0], 0, rawThumbnail.size.extS[0]); |
| } |
| |
| if (mPictureBufDummy[0].size.extS[0] <= 0) |
| return UNKNOWN_ERROR; |
| |
| LOG_PERFORMANCE_START(3); |
| |
| #if 0 |
| ALOGD("mPostviewFrameSize = %d", mPostviewFrameSize); |
| save_dump_path((uint8_t*)mPostviewHeap->data, |
| mPostviewFrameSize, "/data/dump_postview_yuv.yuv"); |
| #endif |
| |
| scaleDownYuv422((unsigned char *)mPostviewHeap->data, |
| (int)mPostviewSize.width, |
| (int)mPostviewSize.height, |
| (unsigned char *)rawThumbnail.virt.extP[0], |
| (int)mThumbnailSize.width, |
| (int)mThumbnailSize.height); |
| LOG_PERFORMANCE_END(3, "scaleDownYuv422"); |
| |
| /* alloc thumbnailJpeg */ |
| thumbnailJpeg.size.extS[0] = mThumbnailSize.width * mThumbnailSize.height * 2; |
| if (allocMem(mIonCameraClient, &thumbnailJpeg, 1 << 1) == false) { |
| ALOGE("ERR(%s): thumbnailJpeg allocMem() fail", __func__); |
| goto destroyMem; |
| } else { |
| ALOGV("DEBUG(%s): thumbnailJpeg allocMem adr(%p), size(%d), ion(%d)", __FUNCTION__, |
| thumbnailJpeg.virt.extP[0], thumbnailJpeg.size.extS[0], mIonCameraClient); |
| memset(thumbnailJpeg.virt.extP[0], 0, thumbnailJpeg.size.extS[0]); |
| } |
| |
| err = EncodeToJpeg(&rawThumbnail, |
| &thumbnailJpeg, |
| mThumbnailSize.width, |
| mThumbnailSize.height, |
| CAM_PIXEL_FORMAT_YUV422I, |
| &thumbSize, |
| JPEG_THUMBNAIL_QUALITY); |
| CHECK_ERR_GOTO(encodeJpeg, err, ("getJpeg: error, EncodeToJpeg(thumbnail)")); |
| |
| thumb = (uint8_t *)thumbnailJpeg.virt.extP[0]; |
| thumbnail = true; |
| |
| LOG_PERFORMANCE_END(1, "encode thumbnail"); |
| #ifdef SAVE_DUMP |
| #if 0 |
| save_dump_path((uint8_t*)thumbnailJpeg.virt.extP[0], |
| thumbSize, "/data/dump_thumbnail_jpeg.jpg"); |
| #endif |
| #endif |
| |
| encodeJpeg: |
| /* Making EXIF header */ |
| |
| setExifChangedAttribute(); |
| |
| uint32_t exifSize; |
| uint8_t *jpeg; |
| |
| /* alloc exifOutBuf */ |
| exifOutBuf.size.extS[0] = EXIF_MAX_LEN; |
| if (allocMem(mIonCameraClient, &exifOutBuf, 1 << 1) == false) { |
| ALOGE("ERR(%s): exifTmpBuf allocMem() fail", __func__); |
| goto destroyMem; |
| } else { |
| ALOGV("DEBUG(%s): exifTmpBuf allocMem adr(%p), size(%d), ion(%d)", __FUNCTION__, |
| exifOutBuf.virt.extP[0], exifOutBuf.size.extS[0], mIonCameraClient); |
| memset(exifOutBuf.virt.extP[0], 0, exifOutBuf.size.extS[0]); |
| } |
| |
| if (!thumbnail) |
| exifSize = exif.make((void *)exifOutBuf.virt.extP[0], &mExifInfo); |
| else |
| exifSize = exif.make((void *)exifOutBuf.virt.extP[0], &mExifInfo, exifOutBuf.size.extS[0], thumb, thumbSize); |
| if (CC_UNLIKELY(!exifSize)) { |
| ALOGE("ERR(%s): getJpeg: error, fail to make EXIF", __FUNCTION__); |
| goto destroyMem; |
| } |
| |
| /* Finally, Creating Jpeg image file including EXIF */ |
| mPictureFrameSize = jpegSize + exifSize; |
| |
| #ifdef BURST_SHOT_SUPPORT |
| if ( mCaptureMode == RUNNING_MODE_BURST ) { |
| uint8_t *target; |
| ALOGD("BURSTSHOT : jpegSize (%d) = %d, exifSize = %d", mPictureFrameSize, jpegSize, exifSize); |
| |
| target = mBurstShot.malloc(mPictureFrameSize); |
| if (target == NULL) { |
| ALOGE("BURSTSHOT: ERR(%s): malloc failed.", __FUNCTION__); |
| goto destroyMem; |
| } |
| |
| ALOGD("BURSTSHOT: DEBUG(%s): target allocMem adr(%p)", __FUNCTION__, target); |
| |
| jpeg = (unsigned char *)mPictureBufDummy[0].virt.extP[0]; |
| memcpy(target, jpeg, 2); |
| memcpy(target + 2, exifOutBuf.virt.extP[0], exifSize); |
| memcpy(target + 2 + exifSize, jpeg + 2, jpegSize - 2); |
| #ifdef SAVE_DUMP |
| #if 0 |
| save_dump_path((uint8_t*)jpeg, |
| mPictureFrameSize, "/data/dump_full_img.jpg"); |
| #endif |
| #endif |
| } else |
| #endif |
| { |
| ALOGD("jpegSize = %d, exifSize = %d", jpegSize, exifSize); |
| /*note that picture frame size is should be calculated before call allocateSnapshotHeap */ |
| if (!allocateSnapshotHeap()) { |
| ALOGE("getEncodedJpeg: error, allocateSnapshotHeap"); |
| goto destroyMem; |
| } |
| |
| // jpeg = (unsigned char *)jpegOutBuf.virt.extP[0]; |
| jpeg = (unsigned char *)mPictureBufDummy[0].virt.extP[0]; |
| memcpy((unsigned char *)mJpegHeap->data, jpeg, 2); |
| memcpy((unsigned char *)mJpegHeap->data + 2, exifOutBuf.virt.extP[0], exifSize); |
| memcpy((unsigned char *)mJpegHeap->data + 2 + exifSize, jpeg + 2, jpegSize - 2); |
| ALOGD("DEBUG(%s): success making jpeg(%d) and exif(%d)", __FUNCTION__, jpegSize, exifSize); |
| |
| #ifdef SAVE_DUMP |
| #if 0 |
| save_dump_path((uint8_t*)mJpegHeap->data, |
| mPictureFrameSize, "/data/dump_full_img.jpg"); |
| #endif |
| #endif |
| } |
| |
| ret = NO_ERROR; |
| |
| destroyMem: |
| freeMemSinglePlane(&thumbnailJpeg, 0); |
| freeMemSinglePlane(&rawThumbnail, 0); |
| freeMemSinglePlane(&jpegOutBuf, 0); |
| freeMemSinglePlane(&exifOutBuf, 0); |
| |
| return ret; |
| } |
| #else |
| { |
| ExynosBuffer thumbnailJpeg; |
| ExynosBuffer rawThumbnail; |
| ExynosBuffer jpegOutBuf; |
| ExynosBuffer exifOutBuf; |
| ExynosBuffer nullBuf; |
| Exif exif(mCameraId, CAMERA_TYPE_SOC); |
| int i; |
| |
| uint8_t *thumb; |
| int32_t thumbSize; |
| bool thumbnail = false; |
| int err = -1; |
| int ret = UNKNOWN_ERROR; |
| |
| s5p_rect zoomRect; |
| ALOGV("DEBUG(%s)(%d): picture size(%d/%d)", __FUNCTION__, __LINE__, mPictureSize.width, mPictureSize.height); |
| ALOGV("DEBUG(%s)(%d): thumbnail size(%d/%d)", __FUNCTION__, __LINE__, mThumbnailSize.width, mThumbnailSize.height); |
| |
| zoomRect.w = mPictureSize.width * 10 / mZoomValue; |
| zoomRect.h = mPictureSize.height * 10 / mZoomValue; |
| |
| if (zoomRect.w % 2) |
| zoomRect.w -= 1; |
| |
| if (zoomRect.h % 2) |
| zoomRect.h -= 1; |
| |
| zoomRect.x = (mPictureSize.width - zoomRect.w) / 2; |
| zoomRect.y = (mPictureSize.height - zoomRect.h) / 2; |
| |
| if (zoomRect.x % 2) |
| zoomRect.x -= 1; |
| |
| if (zoomRect.y % 2) |
| zoomRect.y -= 1; |
| |
| /* Making thumbnail image */ |
| if (mThumbnailSize.width == 0 || mThumbnailSize.height == 0) |
| goto encodeJpeg; |
| |
| /* alloc rawThumbnail */ |
| rawThumbnail.size.extS[0] = mThumbnailSize.width * mThumbnailSize.height * 2; |
| if (allocMem(mIonCameraClient, &rawThumbnail, 1 << 1) == false) { |
| ALOGE("ERR(%s): rawThumbnail allocMem() fail", __func__); |
| goto destroyMem; |
| } else { |
| ALOGV("DEBUG(%s): rawThumbnail allocMem adr(%p), size(%d), ion(%d)", __FUNCTION__, |
| rawThumbnail.virt.extP[0], rawThumbnail.size.extS[0], mIonCameraClient); |
| memset(rawThumbnail.virt.extP[0], 0, rawThumbnail.size.extS[0]); |
| } |
| |
| if (mPictureBuf.size.extS[0] <= 0) |
| return UNKNOWN_ERROR; |
| |
| LOG_PERFORMANCE_START(3); |
| |
| scaleDownYuv422((unsigned char *)mPictureBuf.virt.extP[0], |
| (int)mPictureSize.width, |
| (int)mPictureSize.height, |
| (unsigned char *)rawThumbnail.virt.extP[0], |
| (int)mThumbnailSize.width, |
| (int)mThumbnailSize.height); |
| LOG_PERFORMANCE_END(3, "scaleDownYuv422"); |
| |
| /* alloc thumbnailJpeg */ |
| thumbnailJpeg.size.extS[0] = mThumbnailSize.width * mThumbnailSize.height * 2; |
| if (allocMem(mIonCameraClient, &thumbnailJpeg, 1 << 1) == false) { |
| ALOGE("ERR(%s): thumbnailJpeg allocMem() fail", __func__); |
| goto destroyMem; |
| } else { |
| ALOGV("DEBUG(%s): thumbnailJpeg allocMem adr(%p), size(%d), ion(%d)", __FUNCTION__, |
| thumbnailJpeg.virt.extP[0], thumbnailJpeg.size.extS[0], mIonCameraClient); |
| memset(thumbnailJpeg.virt.extP[0], 0, thumbnailJpeg.size.extS[0]); |
| } |
| |
| err = EncodeToJpeg(&rawThumbnail, |
| &thumbnailJpeg, |
| mThumbnailSize.width, |
| mThumbnailSize.height, |
| CAM_PIXEL_FORMAT_YUV422I, |
| &thumbSize, |
| JPEG_THUMBNAIL_QUALITY); |
| CHECK_ERR_GOTO(encodeJpeg, err, ("getJpeg: error, EncodeToJpeg(thumbnail)")); |
| |
| thumb = (uint8_t *)thumbnailJpeg.virt.extP[0]; |
| thumbnail = true; |
| |
| LOG_PERFORMANCE_END(1, "encode thumbnail"); |
| |
| encodeJpeg: |
| /* Making EXIF header */ |
| |
| setExifChangedAttribute(); |
| |
| uint32_t exifSize; |
| int32_t jpegSize; |
| uint8_t *jpeg; |
| |
| /* alloc exifOutBuf */ |
| exifOutBuf.size.extS[0] = EXIF_MAX_LEN; |
| if (allocMem(mIonCameraClient, &exifOutBuf, 1 << 1) == false) { |
| ALOGE("ERR(%s): exifTmpBuf allocMem() fail", __func__); |
| goto destroyMem; |
| } else { |
| ALOGV("DEBUG(%s): exifTmpBuf allocMem adr(%p), size(%d), ion(%d)", __FUNCTION__, |
| exifOutBuf.virt.extP[0], exifOutBuf.size.extS[0], mIonCameraClient); |
| memset(exifOutBuf.virt.extP[0], 0, exifOutBuf.size.extS[0]); |
| } |
| |
| if (!thumbnail) |
| exifSize = exif.make((void *)exifOutBuf.virt.extP[0], &mExifInfo); |
| else |
| exifSize = exif.make((void *)exifOutBuf.virt.extP[0], &mExifInfo, exifOutBuf.size.extS[0], thumb, thumbSize); |
| if (CC_UNLIKELY(!exifSize)) { |
| ALOGE("ERR(%s): getJpeg: error, fail to make EXIF", __FUNCTION__); |
| goto destroyMem; |
| } |
| |
| /* alloc jpegOutBuf */ |
| jpegOutBuf.size.extS[0] = mPictureSize.width * mPictureSize.height * 2; |
| if (allocMem(mIonCameraClient, &jpegOutBuf, 1 << 1) == false) { |
| ALOGE("ERR(%s): jpegOutBuf allocMem() fail", __func__); |
| goto destroyMem; |
| } else { |
| ALOGV("DEBUG(%s): jpegOutBuf allocMem adr(%p), size(%d), ion(%d)", __FUNCTION__, |
| jpegOutBuf.virt.extP[0], jpegOutBuf.size.extS[0], mIonCameraClient); |
| memset(jpegOutBuf.virt.extP[0], 0, jpegOutBuf.size.extS[0]); |
| } |
| |
| /* Making main jpeg image */ |
| err = EncodeToJpeg(&mPictureBuf, |
| &jpegOutBuf, |
| mPictureSize.width, |
| mPictureSize.height, |
| CAM_PIXEL_FORMAT_YUV422I, |
| &jpegSize, |
| mJpegQuality); |
| |
| CHECK_ERR_GOTO(destroyMem, err, ("getJpeg: error, EncodeToJpeg(Main)")); |
| |
| /* Finally, Creating Jpeg image file including EXIF */ |
| mPictureFrameSize = jpegSize + exifSize; |
| |
| /*note that picture frame size is should be calculated before call allocateSnapshotHeap */ |
| if (!allocateSnapshotHeap()) { |
| ALOGE("getEncodedJpeg: error, allocateSnapshotHeap"); |
| goto destroyMem; |
| } |
| |
| jpeg = (unsigned char *)jpegOutBuf.virt.extP[0]; |
| memcpy((unsigned char *)mJpegHeap->data, jpeg, 2); |
| memcpy((unsigned char *)mJpegHeap->data + 2, exifOutBuf.virt.extP[0], exifSize); |
| memcpy((unsigned char *)mJpegHeap->data + 2 + exifSize, jpeg + 2, jpegSize - 2); |
| ALOGD("DEBUG(%s): success making jpeg(%d) and exif(%d)", __FUNCTION__, jpegSize, exifSize); |
| |
| ret = NO_ERROR; |
| |
| destroyMem: |
| freeMem(&thumbnailJpeg); |
| freeMem(&rawThumbnail); |
| freeMem(&jpegOutBuf); |
| freeMem(&exifOutBuf); |
| |
| return ret; |
| } |
| #endif |
| |
| int SecCameraHardware::getCombinedJpeg(int *postviewOffset) |
| { |
| ExynosBuffer thumbnailJpeg; |
| ExynosBuffer rawThumbnail; |
| ExynosBuffer jpegOutBuf; |
| ExynosBuffer exifOutBuf; |
| ExynosBuffer nullBuf; |
| Exif exif(mCameraId); |
| int i; |
| |
| uint8_t *thumb; |
| bool thumbnail = false; |
| int err; |
| int ret = UNKNOWN_ERROR; |
| |
| int32_t jpegSize = -1; |
| int32_t jpegOffset; |
| int32_t thumbSize; |
| uint8_t *postview; |
| |
| err = mFlite.gctrl(V4L2_CID_CAM_JPEG_MAIN_SIZE, &jpegSize); |
| CHECK_ERR(err, ("getJpeg: error %d, jpeg size", err)); |
| |
| err = mFlite.gctrl(V4L2_CID_CAM_JPEG_MAIN_OFFSET, &jpegOffset); |
| CHECK_ERR(err, ("getJpeg: error %d, jpeg offset", err)); |
| |
| if (!allocatePostviewHeap()) { |
| ALOGE("getPostview: error, allocatePostviewHeap"); |
| return UNKNOWN_ERROR; |
| } |
| |
| ALOGD("internalgetJpeg: jpegSize = %d, jpegOffset = %d, mPostviewFrameSize = %d", jpegSize, jpegOffset, mPostviewFrameSize); |
| |
| s5p_rect zoomRect; |
| ALOGV("DEBUG(%s)(%d): picture size(%d/%d)", __FUNCTION__, __LINE__, mPictureSize.width, mPictureSize.height); |
| ALOGV("DEBUG(%s)(%d): thumbnail size(%d/%d)", __FUNCTION__, __LINE__, mThumbnailSize.width, mThumbnailSize.height); |
| |
| zoomRect.w = mPictureSize.width * 10 / mZoomValue; |
| zoomRect.h = mPictureSize.height * 10 / mZoomValue; |
| |
| if (zoomRect.w % 2) |
| zoomRect.w -= 1; |
| |
| if (zoomRect.h % 2) |
| zoomRect.h -= 1; |
| |
| zoomRect.x = (mPictureSize.width - zoomRect.w) / 2; |
| zoomRect.y = (mPictureSize.height - zoomRect.h) / 2; |
| |
| if (zoomRect.x % 2) |
| zoomRect.x -= 1; |
| |
| if (zoomRect.y % 2) |
| zoomRect.y -= 1; |
| |
| postview = (unsigned char *)mPictureBufDummy[0].virt.extP[0]; |
| memcpy((unsigned char *)mPostviewHeap->data, postview, mPostviewFrameSize); |
| |
| #ifdef SAVE_DUMP |
| #if 1 |
| ALOGD("mPostviewFrameSize = %d", mPostviewFrameSize); |
| save_dump_path((uint8_t*)mPostviewHeap->data, |
| mPostviewFrameSize, "/data/dump_postview_yuv.yuv"); |
| #endif |
| #endif |
| |
| #if 0 |
| /* Making thumbnail image */ |
| /* In case of YUV420 skip thumbnail encoding. */ |
| if (mThumbnailSize.width == 0 || mThumbnailSize.height == 0) { |
| ALOGE("mThumbnailSize width/height = 0 skip encodeJpeg"); |
| goto encodeJpeg; |
| } |
| |
| /* alloc rawThumbnail */ |
| rawThumbnail.size.extS[0] = mThumbnailSize.width * mThumbnailSize.height * 2; |
| if (allocMem(mIonCameraClient, &rawThumbnail, 1 << 1) == false) { |
| ALOGE("ERR(%s): rawThumbnail allocMem() fail", __func__); |
| goto destroyMem; |
| } else { |
| ALOGV("DEBUG(%s): rawThumbnail allocMem adr(%p), size(%d), ion(%d)", __FUNCTION__, |
| rawThumbnail.virt.extP[0], rawThumbnail.size.extS[0], mIonCameraClient); |
| memset(rawThumbnail.virt.extP[0], 0, rawThumbnail.size.extS[0]); |
| } |
| |
| if (mPictureBufDummy[0].size.extS[0] <= 0) |
| return UNKNOWN_ERROR; |
| |
| LOG_PERFORMANCE_START(3); |
| |
| scaleDownYuv422((unsigned char *)mPostviewHeap->data, |
| (int)mPostviewSize.width, |
| (int)mPostviewSize.height, |
| (unsigned char *)rawThumbnail.virt.extP[0], |
| (int)mThumbnailSize.width, |
| (int)mThumbnailSize.height); |
| LOG_PERFORMANCE_END(3, "scaleDownYuv422"); |
| |
| /* alloc thumbnailJpeg */ |
| thumbnailJpeg.size.extS[0] = mThumbnailSize.width * mThumbnailSize.height * 2; |
| if (allocMem(mIonCameraClient, &thumbnailJpeg, 1 << 1) == false) { |
| ALOGE("ERR(%s): thumbnailJpeg allocMem() fail", __func__); |
| goto destroyMem; |
| } else { |
| ALOGV("DEBUG(%s): thumbnailJpeg allocMem adr(%p), size(%d), ion(%d)", __FUNCTION__, |
| thumbnailJpeg.virt.extP[0], thumbnailJpeg.size.extS[0], mIonCameraClient); |
| memset(thumbnailJpeg.virt.extP[0], 0, thumbnailJpeg.size.extS[0]); |
| } |
| |
| err = EncodeToJpeg(&rawThumbnail, |
| &thumbnailJpeg, |
| mThumbnailSize.width, |
| mThumbnailSize.height, |
| CAM_PIXEL_FORMAT_YUV422I, |
| &thumbSize, |
| JPEG_THUMBNAIL_QUALITY); |
| CHECK_ERR_GOTO(encodeJpeg, err, ("getJpeg: error, EncodeToJpeg(thumbnail)")); |
| |
| thumb = (uint8_t *)thumbnailJpeg.virt.extP[0]; |
| thumbnail = true; |
| |
| LOG_PERFORMANCE_END(1, "encode thumbnail"); |
| #ifdef SAVE_DUMP |
| #if 0 |
| save_dump_path((uint8_t*)thumbnailJpeg.virt.extP[0], |
| thumbSize, "/data/dump_thumbnail_jpeg.jpg"); |
| #endif |
| #endif |
| #endif |
| |
| encodeJpeg: |
| /* Making EXIF header */ |
| |
| setExifChangedAttribute(); |
| |
| uint32_t exifSize; |
| uint8_t *jpeg; |
| |
| /* alloc exifOutBuf */ |
| exifOutBuf.size.extS[0] = EXIF_MAX_LEN; |
| if (allocMem(mIonCameraClient, &exifOutBuf, 1 << 1) == false) { |
| ALOGE("ERR(%s): exifTmpBuf allocMem() fail", __func__); |
| goto destroyMem; |
| } else { |
| ALOGV("DEBUG(%s): exifTmpBuf allocMem adr(%p), size(%d), ion(%d)", __FUNCTION__, |
| exifOutBuf.virt.extP[0], exifOutBuf.size.extS[0], mIonCameraClient); |
| memset(exifOutBuf.virt.extP[0], 0, exifOutBuf.size.extS[0]); |
| } |
| |
| if (!thumbnail) |
| exifSize = exif.make((void *)exifOutBuf.virt.extP[0], &mExifInfo); |
| else |
| exifSize = exif.make((void *)exifOutBuf.virt.extP[0], &mExifInfo, exifOutBuf.size.extS[0], thumb, thumbSize); |
| if (CC_UNLIKELY(!exifSize)) { |
| ALOGE("ERR(%s): getJpeg: error, fail to make EXIF", __FUNCTION__); |
| goto destroyMem; |
| } |
| |
| /* Finally, Creating Jpeg image file including EXIF */ |
| mPictureFrameSize = jpegSize + exifSize; |
| |
| #ifdef BURST_SHOT_SUPPORT |
| if (mPASMMode == MODE_MAGIC) { |
| uint8_t *target; |
| ALOGD("BURSTSHOT : jpegSize (%d) = %d, exifSize = %d", mPictureFrameSize, jpegSize, exifSize); |
| |
| target = mBurstShot.malloc(mPictureFrameSize); |
| if (target == NULL) { |
| ALOGE("BURSTSHOT: ERR(%s): malloc failed.", __FUNCTION__); |
| goto destroyMem; |
| } |
| |
| ALOGD("BURSTSHOT: DEBUG(%s): target allocMem adr(%p)", __FUNCTION__, target); |
| |
| jpeg = (unsigned char *)mPictureBufDummy[0].virt.extP[0] + mPostviewFrameSize; |
| memcpy(target, jpeg, 2); |
| memcpy(target + 2, exifOutBuf.virt.extP[0], exifSize); |
| memcpy(target + 2 + exifSize, jpeg + 2, jpegSize - 2); |
| #ifdef SAVE_DUMP |
| #if 0 |
| save_dump_path((uint8_t*)jpeg, |
| mPictureFrameSize, "/data/dump_full_img.jpg"); |
| #endif |
| #endif |
| } else |
| #endif |
| { |
| ALOGD("jpegSize = %d, exifSize = %d", jpegSize, exifSize); |
| /*note that picture frame size is should be calculated before call allocateSnapshotHeap */ |
| if (!allocateSnapshotHeap()) { |
| ALOGE("getEncodedJpeg: error, allocateSnapshotHeap"); |
| goto destroyMem; |
| } |
| |
| // jpeg = (unsigned char *)jpegOutBuf.virt.extP[0]; |
| jpeg = (unsigned char *)mPictureBufDummy[0].virt.extP[0]; |
| memcpy((unsigned char *)mJpegHeap->data, jpeg, 2); |
| memcpy((unsigned char *)mJpegHeap->data + 2, exifOutBuf.virt.extP[0], exifSize); |
| memcpy((unsigned char *)mJpegHeap->data + 2 + exifSize, jpeg + 2, jpegSize - 2); |
| ALOGD("DEBUG(%s): success making jpeg(%d) and exif(%d)", __FUNCTION__, jpegSize, exifSize); |
| |
| #ifdef SAVE_DUMP |
| #if 0 |
| save_dump_path((uint8_t*)mJpegHeap->data, |
| mPictureFrameSize, "/data/dump_full_img.jpg"); |
| #endif |
| #endif |
| } |
| |
| ret = NO_ERROR; |
| |
| destroyMem: |
| freeMemSinglePlane(&thumbnailJpeg, 0); |
| freeMemSinglePlane(&rawThumbnail, 0); |
| freeMemSinglePlane(&jpegOutBuf, 0); |
| freeMemSinglePlane(&exifOutBuf, 0); |
| |
| return ret; |
| } |
| |
| int SecCameraHardware::internalGetJpegForRawWithZoom(int *postviewOffset) |
| { |
| ExynosBuffer thumbnailJpeg; |
| ExynosBuffer rawThumbnail; |
| ExynosBuffer jpegOutBuf; |
| ExynosBuffer exifOutBuf; |
| ExynosBuffer nullBuf; |
| Exif exif(mCameraId); |
| int i; |
| |
| uint8_t *thumb; |
| bool thumbnail = false; |
| int err; |
| int ret = UNKNOWN_ERROR; |
| |
| int32_t jpegSize = -1; |
| int32_t jpegOffset; |
| int32_t thumbSize = 0; |
| int32_t thumbOffset; |
| |
| err = mFlite.gctrl(V4L2_CID_CAM_JPEG_MAIN_SIZE, &jpegSize); |
| CHECK_ERR(err, ("getJpeg: error %d, jpeg size", err)); |
| |
| ALOGD("internalgetJpeg: jpegSize = %d", jpegSize); |
| |
| err = mFlite.gctrl(V4L2_CID_CAM_JPEG_MAIN_OFFSET, &jpegOffset); |
| CHECK_ERR(err, ("getJpeg: error %d, jpeg offset", err)); |
| |
| |
| s5p_rect zoomRect; |
| ALOGV("DEBUG(%s)(%d): picture size(%d/%d)", __FUNCTION__, __LINE__, mPictureSize.width, mPictureSize.height); |
| |
| zoomRect.w = mPictureSize.width * 10 / mZoomValue; |
| zoomRect.h = mPictureSize.height * 10 / mZoomValue; |
| |
| if (zoomRect.w % 2) |
| zoomRect.w -= 1; |
| |
| if (zoomRect.h % 2) |
| zoomRect.h -= 1; |
| |
| zoomRect.x = (mPictureSize.width - zoomRect.w) / 2; |
| zoomRect.y = (mPictureSize.height - zoomRect.h) / 2; |
| |
| if (zoomRect.x % 2) |
| zoomRect.x -= 1; |
| |
| if (zoomRect.y % 2) |
| zoomRect.y -= 1; |
| |
| |
| if (mPictureBufDummy[0].size.extS[0] <= 0) |
| return UNKNOWN_ERROR; |
| |
| LOG_PERFORMANCE_START(3); |
| |
| #if 0 |
| ALOGD("mPostviewFrameSize = %d", mPostviewFrameSize); |
| save_dump_path((uint8_t*)mPostviewHeap->data, |
| mPostviewFrameSize, "/data/dump_postview_yuv.yuv"); |
| #endif |
| |
| thumbnail = false; |
| |
| LOG_PERFORMANCE_END(1, "encode thumbnail"); |
| #ifdef SAVE_DUMP |
| #if 0 |
| save_dump_path((uint8_t*)thumbnailJpeg.virt.extP[0], |
| thumbSize, "/data/dump_thumbnail_jpeg.jpg"); |
| #endif |
| #endif |
| |
| encodeJpeg: |
| /* Making EXIF header */ |
| |
| setExifChangedAttribute(); |
| |
| uint32_t exifSize; |
| uint8_t *jpeg; |
| |
| /* alloc exifOutBuf */ |
| exifOutBuf.size.extS[0] = EXIF_MAX_LEN; |
| if (allocMem(mIonCameraClient, &exifOutBuf, 1 << 1) == false) { |
| ALOGE("ERR(%s): exifTmpBuf allocMem() fail", __func__); |
| goto destroyMem; |
| } else { |
| ALOGV("DEBUG(%s): exifTmpBuf allocMem adr(%p), size(%d), ion(%d)", __FUNCTION__, |
| exifOutBuf.virt.extP[0], exifOutBuf.size.extS[0], mIonCameraClient); |
| memset(exifOutBuf.virt.extP[0], 0, exifOutBuf.size.extS[0]); |
| } |
| |
| if (!thumbnail) |
| exifSize = exif.make((void *)exifOutBuf.virt.extP[0], &mExifInfo); |
| else |
| exifSize = exif.make((void *)exifOutBuf.virt.extP[0], &mExifInfo, exifOutBuf.size.extS[0], thumb, thumbSize); |
| if (CC_UNLIKELY(!exifSize)) { |
| ALOGE("ERR(%s): getJpeg: error, fail to make EXIF", __FUNCTION__); |
| goto destroyMem; |
| } |
| |
| /* Finally, Creating Jpeg image file including EXIF */ |
| mPictureFrameSize = jpegSize + exifSize; |
| |
| { |
| ALOGD("jpegSize = %d, exifSize = %d", jpegSize, exifSize); |
| /*note that picture frame size is should be calculated before call allocateSnapshotHeap */ |
| if (!allocateSnapshotHeap()) { |
| ALOGE("getEncodedJpeg: error, allocateSnapshotHeap"); |
| goto destroyMem; |
| } |
| |
| // jpeg = (unsigned char *)jpegOutBuf.virt.extP[0]; |
| jpeg = (unsigned char *)mPictureBufDummy[0].virt.extP[0]; |
| memcpy((unsigned char *)mJpegHeap->data, jpeg, 2); |
| memcpy((unsigned char *)mJpegHeap->data + 2, exifOutBuf.virt.extP[0], exifSize); |
| memcpy((unsigned char *)mJpegHeap->data + 2 + exifSize, jpeg + 2, jpegSize - 2); |
| ALOGD("DEBUG(%s): success making jpeg(%d) and exif(%d)", __FUNCTION__, jpegSize, exifSize); |
| |
| #ifdef SAVE_DUMP |
| #if 0 |
| save_dump_path((uint8_t*)mJpegHeap->data, |
| mPictureFrameSize, "/data/dump_full_img.jpg"); |
| #endif |
| #endif |
| } |
| |
| ret = NO_ERROR; |
| |
| destroyMem: |
| freeMemSinglePlane(&jpegOutBuf, 0); |
| freeMemSinglePlane(&exifOutBuf, 0); |
| |
| return ret; |
| } |
| |
| |
| |
| int SecCameraHardware::internalGetJpegForSocYuv(int *postviewOffset) |
| { |
| ALOGD("internalGetJpegForSocYuv: E"); |
| sp<MemoryHeapBase> rawThumbnail; |
| sp<MemoryHeapBase> thumbnailJpeg; |
| uint8_t *thumb; |
| int32_t thumbSize = 0; |
| bool thumbnail = false; |
| int err; |
| |
| LOG_PERFORMANCE_START(1); |
| |
| /* Making thumbnail jpeg image */ |
| |
| if (mThumbnailSize.width == 0 || mThumbnailSize.height == 0) |
| goto encodeJpeg; |
| |
| rawThumbnail = new MemoryHeapBase(mThumbnailSize.width * mThumbnailSize.height * 2); |
| LOG_PERFORMANCE_START(3); |
| scaleDownYuv422((uint8_t *)mRawHeap->data, (int)mPictureSize.width, (int)mPictureSize.height, |
| (uint8_t *)rawThumbnail->base(), (int)mThumbnailSize.width, (int)mThumbnailSize.height); |
| LOG_PERFORMANCE_END(3, "scaleDownYuv422"); |
| |
| thumbnailJpeg = new MemoryHeapBase(mThumbnailSize.width * mThumbnailSize.height * 2); |
| |
| #ifdef CHG_ENCODE_JPEG |
| err = EncodeToJpeg((unsigned char*)rawThumbnail->base(), |
| mThumbnailSize.width, |
| mThumbnailSize.height, |
| CAM_PIXEL_FORMAT_YUV422I, |
| (unsigned char*)thumbnailJpeg->base(), |
| &thumbSize, |
| JPEG_THUMBNAIL_QUALITY); /* DSLIM fix lelvel*/ |
| if (CC_UNLIKELY(err)) { |
| ALOGE("getJpeg: error, EncodeToJpeg(thumbnail)"); |
| goto encodeJpeg; |
| } |
| #endif |
| |
| thumb = (uint8_t *)thumbnailJpeg->base(); |
| thumbnail = true; |
| |
| LOG_PERFORMANCE_END(1, "encode thumbnail"); |
| |
| encodeJpeg: |
| /* Making EXIF header */ |
| |
| setExifChangedAttribute(); |
| |
| Exif exif(mCameraId); |
| uint32_t exifSize; |
| int32_t jpegSize = 0; |
| uint8_t *jpeg; |
| |
| sp<MemoryHeapBase> jpegHeap = new MemoryHeapBase(mPictureSize.width * mPictureSize.height * 2); |
| sp<MemoryHeapBase> exifHeap = new MemoryHeapBase(EXIF_MAX_LEN); |
| if (!initialized(exifHeap) || !initialized(jpegHeap)) { |
| ALOGE("getJpeg: error, could not initialize jpeg, exif heap"); |
| return UNKNOWN_ERROR; |
| } |
| |
| if (!thumbnail) |
| exifSize = exif.make(exifHeap->base(), &mExifInfo); |
| else |
| exifSize = exif.make(exifHeap->base(), &mExifInfo, exifHeap->getSize(), thumb, thumbSize); |
| if (CC_UNLIKELY(!exifSize)) { |
| ALOGE("getJpeg: error, fail to make EXIF"); |
| return UNKNOWN_ERROR; |
| } |
| |
| /* Making main jpeg image */ |
| #ifdef CHG_ENCODE_JPEG |
| err = EncodeToJpeg((unsigned char *)mRawHeap->data, |
| mPictureSize.width, |
| mPictureSize.height, |
| CAM_PIXEL_FORMAT_YUV422I, |
| (unsigned char *)jpegHeap->base(), |
| &jpegSize, |
| mJpegQuality); |
| CHECK_ERR_N(err, ("getJpeg: error, EncodeToJpeg(Main)")); |
| #endif |
| /* Finally, Creating Jpeg image file including EXIF */ |
| mPictureFrameSize = jpegSize + exifSize; |
| |
| /* note that picture frame size is should be calculated before call allocateSnapshotHeap */ |
| if (!allocateSnapshotHeap()) { |
| ALOGE("getJpeg: error, allocateSnapshotHeap"); |
| return UNKNOWN_ERROR; |
| } |
| |
| jpeg = (uint8_t *)jpegHeap->base(); |
| memcpy(mJpegHeap->data, jpeg, 2); |
| memcpy((uint8_t *)mJpegHeap->data + 2, exifHeap->base(), exifSize); |
| memcpy((uint8_t *)mJpegHeap->data + 2 + exifSize, jpeg + 2, jpegSize - 2); |
| |
| ALOGD("internalGetJpegForSocYuv: X"); |
| return NO_ERROR; |
| } |
| |
| int SecCameraHardware::EncodeToJpeg(ExynosBuffer *yuvBuf, ExynosBuffer *jpegBuf, |
| int width, int height, cam_pixel_format srcformat, int* jpegSize, int quality) |
| { |
| ExynosJpegEncoder *jpegEnc = NULL; |
| int ret = UNKNOWN_ERROR; |
| |
| /* 1. ExynosJpegEncoder create */ |
| jpegEnc = new ExynosJpegEncoder(); |
| if (jpegEnc == NULL) { |
| ALOGE("ERR(%s) (%d): jpegEnc is null", __FUNCTION__, __LINE__); |
| return ret; |
| } |
| |
| ret = jpegEnc->create(); |
| if (ret < 0) { |
| ALOGE("ERR(%s):jpegEnc.create(%d) fail", __func__, ret); |
| goto jpeg_encode_done; |
| } |
| |
| /* 2. cache on */ |
| ret = jpegEnc->setCache(JPEG_CACHE_ON); |
| if (ret < 0) { |
| ALOGE("ERR(%s):jpegEnc.setCache(%d) fail", __func__, ret); |
| goto jpeg_encode_done; |
| } |
| |
| /* 3. set quality */ |
| ret = jpegEnc->setQuality(quality); |
| if (ret < 0) { |
| ALOGE("ERR(%s):jpegEnc.setQuality(%d) fail", __func__, ret); |
| goto jpeg_encode_done; |
| } |
| |
| ret = jpegEnc->setSize(width, height); |
| if (ret < 0) { |
| ALOGE("ERR(%s):jpegEnc.setSize() fail", __func__); |
| goto jpeg_encode_done; |
| } |
| |
| /* 4. set yuv format */ |
| ret = jpegEnc->setColorFormat(srcformat); |
| if (ret < 0) { |
| ALOGE("ERR(%s):jpegEnc.setColorFormat(%d) fail", __func__, ret); |
| goto jpeg_encode_done; |
| } |
| |
| /* 5. set jpeg format */ |
| ret = jpegEnc->setJpegFormat(V4L2_PIX_FMT_JPEG_422); |
| if (ret < 0) { |
| ALOGE("ERR(%s):jpegEnc.setJpegFormat(%d) fail", __func__, ret); |
| goto jpeg_encode_done; |
| } |
| |
| /* src and dst buffer alloc */ |
| /* 6. set yuv format(src) from FLITE */ |
| ret = jpegEnc->setInBuf(((char **)&(yuvBuf->virt.extP[0])), (int *)yuvBuf->size.extS); |
| if (ret < 0) { |
| ALOGE("ERR(%s):jpegEnc.setInBuf(%d) fail", __func__, ret); |
| goto jpeg_encode_done; |
| } |
| |
| /* 6. set jpeg format(dest) from FLITE */ |
| ret = jpegEnc->setOutBuf((char *)jpegBuf->virt.extP[0], jpegBuf->size.extS[0]); |
| if (ret < 0) { |
| ALOGE("ERR(%s):jpegEnc.setOutBuf(%d) fail", __func__, ret); |
| goto jpeg_encode_done; |
| } |
| |
| ret = jpegEnc->updateConfig(); |
| if (ret < 0) { |
| ALOGE("ERR(%s):jpegEnc.updateConfig(%d) fail", __func__, ret); |
| goto jpeg_encode_done; |
| } |
| |
| /* start encoding */ |
| ret = jpegEnc->encode(); |
| if (ret < 0) { |
| ALOGE("ERR(%s):jpegEnc.encode(%d) fail", __func__, ret); |
| goto jpeg_encode_done; |
| } |
| |
| /* start encoding */ |
| *jpegSize = jpegEnc->getJpegSize(); |
| if ((*jpegSize) <= 0) { |
| ALOGE("ERR(%s):jpegEnc.getJpegSize(%d) is too small", __func__, *jpegSize); |
| goto jpeg_encode_done; |
| } |
| |
| ALOGD("DEBUG(%s): jpegEnc success!! size(%d)", __func__, *jpegSize); |
| ret = NO_ERROR; |
| |
| jpeg_encode_done: |
| jpegEnc->destroy(); |
| delete jpegEnc; |
| |
| if (ret != NO_ERROR) { |
| ALOGE("ERR(%s): (%d) [yuvBuf->fd.extFd[0] %d][yuvSize[0] %d]", __FUNCTION__, __LINE__, |
| yuvBuf->fd.extFd[0], yuvBuf->size.extS[0]); |
| ALOGE("ERR(%s): (%d) [jpegBuf->fd.extFd %d][jpegBuf->size.extS %d]", __FUNCTION__, __LINE__, |
| jpegBuf->fd.extFd[0], jpegBuf->size.extS[0]); |
| ALOGE("ERR(%s): (%d) [w %d][h %d][colorFormat %d]", __FUNCTION__, __LINE__, |
| width, height, srcformat); |
| } |
| |
| return ret; |
| } |
| |
| #endif /* SAMSUNG_EXYNOS4210 */ |
| |
| #ifdef SAMSUNG_EXYNOS4210 |
| bool SecCameraHardware::internalEncodingJpeg(struct jpeg_encode_param *encodeParam) |
| { |
| struct jpeg_enc_param jpegParam; |
| jpeg_stream_format outputFormat = JPEG_422; |
| jpeg_frame_format inputFormat = YUV_422; |
| uint8_t *inBuf = NULL; |
| uint8_t *outBuf = NULL; |
| |
| if (!(encodeParam->srcWidth && encodeParam->srcHeight && encodeParam->srcBuf && encodeParam->srcBufSize)) { |
| ALOGE("encodingToJpeg: error, srcWidth=%d, srcHeight=%d, srcBuf=0x%X, srcBufSize=0x%X", |
| encodeParam->srcWidth, encodeParam->srcHeight, |
| (uint32_t)(encodeParam->srcBuf), encodeParam->srcBufSize); |
| return false; |
| } |
| |
| int jpegFd = api_jpeg_encode_init(); |
| CHECK_ERR(jpegFd, ("encodingToJpeg: error %d, api_jpeg_encode_init", jpegFd)); |
| |
| /* Fix below code */ |
| switch (encodeParam->srcFormat) { |
| case V4L2_PIX_FMT_NV12: |
| case V4L2_PIX_FMT_NV21: |
| case V4L2_PIX_FMT_NV12T: |
| case V4L2_PIX_FMT_YUV420: |
| outputFormat = JPEG_420; |
| ALOGW("encodingToJpeg, warning, srcFormat: %c%c%c%c", (uint8_t)(encodeParam->srcFormat), |
| (uint8_t)(encodeParam->srcFormat >> 8), (uint8_t)(encodeParam->srcFormat >> 16), |
| (uint8_t)(encodeParam->srcFormat >> 24)); |
| break; |
| case V4L2_PIX_FMT_YUYV: |
| case V4L2_PIX_FMT_UYVY: |
| case V4L2_PIX_FMT_YUV422P: |
| inputFormat = YUV_422; |
| outputFormat = JPEG_422; |
| break; |
| } |
| |
| /* set encode parameters */ |
| CLEAR(jpegParam); |
| jpegParam.width = encodeParam->srcWidth; |
| jpegParam.height = encodeParam->srcHeight; |
| jpegParam.in_fmt = inputFormat; /* YCBYCR Only */ |
| jpegParam.out_fmt = outputFormat; |
| jpegParam.quality = encodeParam->destJpegQuality; |
| api_jpeg_set_encode_param(&jpegParam); |
| |
| /* get Input buffer address */ |
| inBuf = (uint8_t *)api_jpeg_get_encode_in_buf(jpegFd, encodeParam->srcBufSize); |
| if (inBuf == NULL) { |
| ALOGE("encodingToJpeg: error, api_jpeg_get_encode_in_buf"); |
| goto out; |
| } |
| |
| ALOGV("Step 2: memcpy(inBuf(%p), srcBuf(%p), srcBufSize(%d)", |
| inBuf, encodeParam->srcBuf, encodeParam->srcBufSize); |
| memcpy(inBuf, encodeParam->srcBuf, encodeParam->srcBufSize); |
| |
| /* get output buffer address */ |
| ALOGV("Step 3: get outBuf (%p)\n", outBuf); |
| |
| outBuf = (uint8_t *)api_jpeg_get_encode_out_buf(jpegFd); |
| if (outBuf == NULL) { |
| ALOGE("encodingToJpeg: error, thumbnail api_jpeg_get_encode_out_buf"); |
| goto out; |
| } |
| |
| ALOGV("Step 4: excute jpeg encode\n"); |
| |
| if (api_jpeg_encode_exe(jpegFd, &jpegParam) != JPEG_ENCODE_OK) { |
| ALOGE("encodingToJpeg: error, thumbnail api_jpeg_get_encode_in_buf"); |
| goto out; |
| } |
| |
| ALOGV("Step 6: Done"); |
| |
| encodeParam->destJpegSize = jpegParam.size; |
| memcpy(encodeParam->destJpegBuf, outBuf, jpegParam.size); |
| |
| api_jpeg_encode_deinit(jpegFd); |
| return true; |
| |
| out: |
| api_jpeg_encode_deinit(jpegFd); |
| return false; |
| } |
| |
| inline bool SecCameraHardware::jpegOpenEncoding(struct jpeg_encode_param &encodeParam) |
| { |
| encodeParam.jpegFd = api_jpeg_encode_init(); |
| CHECK_ERR(encodeParam.jpegFd, ("jpegInitEncoding: error %d, api_jpeg_encode_init", encodeParam.jpegFd)); |
| |
| return true; |
| } |
| |
| bool SecCameraHardware::jpegExecuteEncoding(struct jpeg_encode_param &encodeParam) |
| { |
| int jpegFd = encodeParam.jpegFd; |
| uint8_t *inBuf = NULL; |
| uint8_t *outBuf = NULL; |
| jpeg_stream_format outputFormat = JPEG_422; |
| jpeg_frame_format inputFormat = YUV_422; |
| struct jpeg_enc_param jpegParam; |
| |
| if (!(encodeParam.srcWidth && encodeParam.srcHeight && encodeParam.srcBuf && encodeParam.srcBufSize)) { |
| ALOGE("jpegStartEncoding: error, srcWidth=%d, srcHeight=%d, srcBuf=0x%X, srcBufSize=0x%X", |
| encodeParam.srcWidth, encodeParam.srcHeight, |
| (uint32_t)(encodeParam.srcBuf), encodeParam.srcBufSize); |
| goto out; |
| } |
| |
| /* Fix below code */ |
| switch (encodeParam.srcFormat) { |
| case V4L2_PIX_FMT_NV12: |
| case V4L2_PIX_FMT_NV21: |
| case V4L2_PIX_FMT_NV12T: |
| case V4L2_PIX_FMT_YUV420: |
| outputFormat = JPEG_420; |
| ALOGW("jpegStartEncoding, warning, srcFormat: %c%c%c%c", (uint8_t)(encodeParam.srcFormat), |
| (uint8_t)(encodeParam.srcFormat >> 8), (uint8_t)(encodeParam.srcFormat >> 16), |
| (uint8_t)(encodeParam.srcFormat >> 24)); |
| break; |
| case V4L2_PIX_FMT_YUYV: |
| case V4L2_PIX_FMT_UYVY: |
| case V4L2_PIX_FMT_YUV422P: |
| inputFormat = YUV_422; |
| outputFormat = JPEG_422; |
| break; |
| } |
| |
| /* set encode parameters */ |
| CLEAR(jpegParam); |
| jpegParam.width = encodeParam.srcWidth; |
| jpegParam.height = encodeParam.srcHeight; |
| jpegParam.in_fmt = inputFormat; /* YCBYCR Only */ |
| jpegParam.out_fmt = outputFormat; |
| jpegParam.quality = encodeParam.destJpegQuality; |
| api_jpeg_set_encode_param(&jpegParam); |
| |
| /* get Input buffer address */ |
| inBuf = (uint8_t *)api_jpeg_get_encode_in_buf(jpegFd, encodeParam.srcBufSize); |
| if (inBuf == NULL) { |
| ALOGE("jpegStartEncoding: error, api_jpeg_get_encode_in_buf"); |
| goto out; |
| } |
| |
| ALOGV("Step 2: memcpy(inBuf(%p), srcBuf(%p), srcBufSize(%d)", |
| inBuf, encodeParam.srcBuf, encodeParam.srcBufSize); |
| memcpy(inBuf, encodeParam.srcBuf, encodeParam.srcBufSize); |
| |
| /* get output buffer address */ |
| outBuf = (uint8_t *)api_jpeg_get_encode_out_buf(jpegFd); |
| if (outBuf == NULL) { |
| ALOGE("jpegStartEncoding: error, thumbnail api_jpeg_get_encode_out_buf"); |
| goto out; |
| } |
| ALOGV("Step 3: get outBuf (%p)\n", outBuf); |
| |
| ALOGV("Step 4: excute jpeg encode\n"); |
| |
| if (api_jpeg_encode_exe(jpegFd, &jpegParam) != JPEG_ENCODE_OK) { |
| ALOGE("jpegStartEncoding: error, thumbnail api_jpeg_get_encode_in_buf"); |
| goto out; |
| } |
| |
| ALOGV("Step 6: Done"); |
| |
| encodeParam.destJpegSize = jpegParam.size; |
| encodeParam.destJpegBuf = outBuf; |
| |
| return true; |
| |
| out: |
| encodeParam.destJpegSize = 0; |
| encodeParam.destJpegBuf = NULL; |
| encodeParam.jpegFd = -1; |
| api_jpeg_encode_deinit(jpegFd); |
| return false; |
| } |
| |
| inline bool SecCameraHardware::jpegCloseEncoding(struct jpeg_encode_param &encodeParam) |
| { |
| if (encodeParam.jpegFd >= 0) { |
| api_jpeg_encode_deinit(encodeParam.jpegFd); |
| encodeParam.jpegFd = -1; |
| } |
| |
| return true; |
| } |
| #else /* !SAMSUNG_EXYNOS4210 */ |
| bool SecCameraHardware::internalEncodingJpeg(struct jpeg_encode_param *encodeParam) |
| { |
| return true; |
| } |
| |
| inline bool SecCameraHardware::jpegOpenEncoding(struct jpeg_encode_param &encodeParam) |
| { |
| return true; |
| } |
| |
| bool SecCameraHardware::jpegExecuteEncoding(struct jpeg_encode_param &encodeParam) |
| { |
| return true; |
| } |
| |
| inline bool SecCameraHardware::jpegCloseEncoding(struct jpeg_encode_param &encodeParam) |
| { |
| return true; |
| } |
| #endif /* SAMSUNG_EXYNOS4210 */ |
| |
| #if !defined(REAR_USE_YUV_CAPTURE) |
| /* |
| * rawThumbOffset - not used. |
| */ |
| /* #define J_DEBUG */ |
| bool SecCameraHardware::extractJpegAndRawThumb(uint32_t jpegOffset, uint32_t *rawThumbSize, |
| uint32_t rawThumbOffset, void *srcInterleavedDataBuf, |
| uint32_t *jpegSize, void *dstJpegBuf, void *dstRawThumbBuf) |
| { |
| const uint8_t *src = (const uint8_t *)srcInterleavedDataBuf; |
| uint8_t *dstJpeg = (uint8_t *)dstJpegBuf; |
| uint8_t *dstRawThumb = (uint8_t *)dstRawThumbBuf; |
| uint32_t dstJpegSize = 0; |
| uint32_t dstRawThumbSize = 0; |
| uint32_t dstThumbHeight = 0; |
| const uint32_t srcBufSize = *jpegSize; |
| uint8_t * const endOfSrcBuf = (uint8_t *)srcInterleavedDataBuf + srcBufSize; |
| uint8_t * const endOfDstThumbBuf = (uint8_t *)dstRawThumbBuf + *rawThumbSize; |
| jpegHeader_t *jpegHeader = (jpegHeader_t *)srcInterleavedDataBuf; |
| const uint32_t jpegHeaderSize = sizeof(jpegHeader_t); |
| uint32_t yuvDataLength = __swap16gen(jpegHeader->resInfo.thumbWidth) * 2; |
| |
| const uint16_t JPEG_SOI = 0xD8FF; /* FF D8 */ |
| const uint16_t JPEG_EOI = 0xD9FF; /* FF D9 */ |
| const uint16_t YUV_SOI = 0xBEFF; /* FF BE */ |
| const uint16_t YUV_EOI = 0xBFFF; /* FF BF */ |
| const uint8_t a_JPEG_SOI[] = {0xFF, 0xD8}; |
| const uint8_t a_JPEG_EOI[] = {0xFF, 0xD9}; |
| const uint8_t a_YUV_SOI[] = {0xFF, 0xBE}; |
| const uint8_t a_YUV_EOI[] = {0xFF, 0xBF}; |
| bool isJpegEoi = false; |
| bool isYuvEoi = false; |
| #ifdef J_DEBUG |
| bool isFristJpegData = true; |
| bool isFoundJpegEOI = false; |
| uint8_t *src2 = endOfSrcBuf - sizeof(a_JPEG_EOI); |
| jpegInfo_t *jpegInform = NULL; |
| #endif |
| /* |
| ALOGV("%s: SrcBuf addr=0x%X, size=0x%X, DstJpegBuf addr=0x%X, size=0x%X, DstThumbBuf addr=0x%X, size=0x%X", |
| __FUNCTION__, srcInterleavedDataBuf, mRawHeap->getSize(), dstJpegBuf, *jpegSize, |
| dstRawThumbBuf, *rawThumbSize); |
| */ |
| |
| if (jpegHeader->soi != JPEG_SOI) { |
| ALOGE("ERROR(%s): Not Jpeg file", __FUNCTION__); |
| goto out; |
| } |
| |
| if ( (mPictureSize.width != __swap16gen(jpegHeader->resInfo.jpegWidth)) || |
| (mPictureSize.height != __swap16gen(jpegHeader->resInfo.jpegHeight)) || |
| (mThumbnailSize.width != __swap16gen(jpegHeader->resInfo.thumbWidth)) || |
| (mThumbnailSize.height != __swap16gen(jpegHeader->resInfo.thumbHeight)) ) { |
| ALOGE("extractJpegAndRawThumb: error, Invalid Jpeg width=0x%04X height=0x%04X, Thumnail width=0x%04X, height=0x%04X", |
| __swap16gen(jpegHeader->resInfo.jpegWidth), __swap16gen(jpegHeader->resInfo.jpegHeight), |
| __swap16gen(jpegHeader->resInfo.thumbWidth), __swap16gen(jpegHeader->resInfo.thumbHeight)); |
| goto out; |
| } |
| |
| #ifdef J_DEBUG |
| while (src2 >= srcInterleavedDataBuf) { |
| if ((*src2 == 0xFF) && (*(src2+1) == a_JPEG_EOI[1])) { |
| /* ALOGV("%s: found Jpeg EOI(0x%X), addr=0x%X, ", __FUNCTION__, *(uint16_t *)src2, src2); */ |
| isFoundJpegEOI = true; |
| break; |
| } else if ((*src2 == a_JPEG_EOI[1]) && (*(src2-1) == 0xFF) ) { |
| isFoundJpegEOI = true; |
| src2 -= 1; |
| break; |
| } |
| |
| src2 -= sizeof(a_JPEG_EOI); |
| } |
| #endif |
| |
| #ifdef J_DEBUG |
| if (jpegHeaderSize != 0x27C) { |
| ALOGE("ERROR(%s): Jpeg Header size = 0x%x", __FUNCTION__, jpegHeaderSize ); |
| return false; |
| } |
| #endif |
| |
| /* Copy Jpeg Header */ |
| memcpy(dstJpeg, src, jpegHeaderSize); |
| dstJpeg += jpegHeaderSize; |
| dstJpegSize += jpegHeaderSize; |
| src += jpegHeaderSize; |
| |
| /* Check First YUV SOI */ |
| if (CC_UNLIKELY(*(uint16_t *)src != YUV_SOI)) { |
| ALOGE("ERROR(%s, %d): Jpeg file is corrupted", __FUNCTION__, __LINE__); |
| goto out; |
| } else { |
| src += sizeof(YUV_SOI); |
| } |
| |
| while (src < endOfSrcBuf - 1) { |
| /* Copy YUV Data */ |
| if (CC_UNLIKELY(src + yuvDataLength + sizeof(YUV_EOI) >= endOfSrcBuf)) { |
| ALOGE("ERROR(%s, %d): Jpeg file is corrupted(0x0A)", __FUNCTION__, __LINE__); |
| goto out; |
| } |
| #ifdef J_DEBUG |
| /* ALOGV("2. Copy YUV Segment"); */ |
| if (CC_UNLIKELY(dstRawThumb+yuvDataLength > endOfDstThumbBuf)) { |
| ALOGE("ERROR: dstRawThumb+yuvDataLength = 0x%X, endOfDstThumbBuf=0x%X", |
| (uint32_t)(dstRawThumb+yuvDataLength), (uint32_t)endOfDstThumbBuf); |
| ALOGE("yuvDataLength=0x%X, dstRawThumbSize=0x%X, dstThumbHeight=0x%X", |
| yuvDataLength, dstRawThumbSize, dstThumbHeight); |
| goto out; |
| } |
| #endif |
| memcpy(dstRawThumb, src, yuvDataLength); |
| dstRawThumb += yuvDataLength; |
| dstRawThumbSize += yuvDataLength; |
| src += yuvDataLength; |
| dstThumbHeight++; |
| |
| /* Check YUV EOI */ |
| if (CC_UNLIKELY(*(uint16_t *)src != YUV_EOI)) { |
| ALOGE("ERROR(%s, %d): Jpeg file is corrupted(0x0B)", __FUNCTION__, __LINE__); |
| ALOGE("YUV_EOI = 0x%02X %02X, yuvDataLength=0x%X", *src, *(src+1), yuvDataLength); |
| goto out; |
| } |
| src += sizeof(YUV_EOI); |
| |
| #ifdef J_DEBUG |
| /* ALOGV("3. Succes to check YUV EOI"); */ |
| if (isFristJpegData) { |
| if ((src - (uint8_t *)srcInterleavedDataBuf) != jpegOffset) |
| ALOGE("ERROR(%s)First Jpeg offset(0x%X) is innormal(0x%X)", __FUNCTION__, jpegOffset, src - (uint8_t *)srcInterleavedDataBuf); |
| isFristJpegData = false; |
| } |
| /* ALOGV("4. Copy JPEG Segment"); */ |
| #endif |
| |
| #ifdef NOTDEFINED |
| /* |
| * Copy Jpeg Data. |
| * We need to improve data copy speed(from 1byte to 4byte) */ |
| while((*(uint16_t *)src != YUV_SOI) && (*(uint16_t *)src != JPEG_EOI)) { |
| if (CC_LIKELY(src < endOfSrcBuf)) { |
| *dstJpeg++ = *src++; |
| dstJpegSize++; |
| } else { |
| ALOGE("ERROR(%s, %d): Jpeg file is corrupted(0x0C)", __FUNCTION__, __LINE__); |
| return false; |
| } |
| } |
| |
| /* Check whether YUV Start or Jpeg end */ |
| if (*(uint16_t *)src == JPEG_EOI) { |
| *(uint16_t *)dstJpeg = *(uint16_t *)src; |
| ALOGV("Coping Jpeg data is completed!(EOI=0x%X)", *(uint16_t *)dstJpeg); |
| dstJpegSize += sizeof(JPEG_EOI); |
| break; |
| } else |
| src += sizeof(YUV_SOI); |
| #else |
| /* |
| * Copy Jpeg Data. |
| * We need to improve data copy speed(from 1byte to 4byte) */ |
| while(src < endOfSrcBuf - 1) { |
| if ((*src == 0xFF) && (*(src+1) == a_YUV_SOI[1])) { |
| src += sizeof(a_YUV_SOI); |
| isYuvEoi = true; |
| break; |
| } else if ((*src == 0xFF) && (*(src+1) == a_JPEG_EOI[1])) { |
| /* *(uint16_t *)dstJpeg = *(uint16_t *)src; */ |
| *dstJpeg++ = *src++; |
| *dstJpeg++ = *src++; |
| dstJpegSize += sizeof(a_JPEG_EOI); |
| isJpegEoi = true; |
| break; |
| } else if (*(src+1) == 0xFF) { |
| *dstJpeg++ = *src++; |
| dstJpegSize++; |
| continue; |
| } |
| |
| *dstJpeg++ = *src++; |
| *dstJpeg++ = *src++; |
| dstJpegSize += 2; |
| } |
| |
| /* Check whether YUV Start or Jpeg end */ |
| if (isJpegEoi) { |
| ALOGV("Coping Jpeg data is completed!!!"); |
| break; |
| } else if (!isYuvEoi) { |
| #ifdef J_DEBUG |
| ALOGE("ERROR(%s, %d): Jpeg file is corrupted(0x0C), isFoundJpegEOI=%d", |
| __FUNCTION__, __LINE__, isFoundJpegEOI); |
| #endif |
| goto out; |
| } |
| |
| isYuvEoi = false; |
| #endif |
| } /* while (src < endOfSrcBuf) */ |
| |
| #ifdef J_DEBUG |
| if (!(isFoundJpegEOI && isJpegEoi)) { |
| /* You should not be here */ |
| ALOGE("ERROR(%s): isFoundJpegEOI=%d, isJpegEoi=%d", __FUNCTION__, isFoundJpegEOI, isJpegEoi); |
| goto out; |
| } |
| #endif |
| |
| ALOGV("JpegSize=%d, rawThumbSize=%d", *jpegSize, *rawThumbSize); |
| ALOGV("dstJpegSize=%d, dstRawThumbSize=%d, dstThumbHeight = %d", dstJpegSize, dstRawThumbSize, dstThumbHeight); |
| |
| if (CC_UNLIKELY(*rawThumbSize != dstRawThumbSize)) { |
| ALOGE("ERROR(%s): Raw thumb size= %d", __FUNCTION__, *rawThumbSize); |
| goto out; |
| } |
| |
| *jpegSize = dstJpegSize; |
| *rawThumbSize = dstRawThumbSize; |
| |
| ALOGI("Extracting Jpeg,YUV data is completed!"); |
| |
| return true; |
| |
| out: |
| ALOGE("extractJpegAndRawThumb: error, dstJpegSize=%d, dstRawThumbSize=%d, dstThumbHeight = %d", |
| dstJpegSize, dstRawThumbSize, dstThumbHeight); |
| if (dstJpegSize > jpegHeaderSize) { |
| *dstJpeg++ = a_JPEG_EOI[0]; |
| *dstJpeg = a_JPEG_EOI[1]; |
| dstJpegSize += sizeof(a_JPEG_EOI); |
| } |
| |
| return false; |
| } |
| #endif |
| |
| bool SecCameraHardware::scaleDownYuv422(uint8_t *srcBuf, int srcW, int srcH, |
| uint8_t *dstBuf, int dstW, int dstH) |
| |
| { |
| int step_x, step_y; |
| int dst_pos; |
| char *src_buf = (char *)srcBuf; |
| char *dst_buf = (char *)dstBuf; |
| |
| if (dstW & 0x01 || dstH & 0x01) { |
| ALOGE("ERROR(%s): (%d) width or height invalid(%d/%d)", __FUNCTION__, __LINE__, |
| dstW & 0x01, dstH & 0x01); |
| return false; |
| } |
| |
| step_x = srcW / dstW; |
| step_y = srcH / dstH; |
| |
| unsigned int srcWStride = srcW * 2; |
| unsigned int stepXStride = step_x * 2; |
| |
| dst_pos = 0; |
| for (int y = 0; y < dstH; y++) { |
| int src_y_start_pos; |
| src_y_start_pos = srcWStride * step_y * y; |
| for (int x = 0; x < dstW; x += 2) { |
| int src_pos; |
| src_pos = src_y_start_pos + (stepXStride * x); |
| dst_buf[dst_pos++] = src_buf[src_pos]; |
| dst_buf[dst_pos++] = src_buf[src_pos + 1]; |
| dst_buf[dst_pos++] = src_buf[src_pos + 2]; |
| dst_buf[dst_pos++] = src_buf[src_pos + 3]; |
| } |
| } |
| |
| return true; |
| } |
| |
| bool SecCameraHardware::conversion420to422(uint8_t *srcBuf, uint8_t *dstBuf, int width, int height) |
| { |
| int i, j, k; |
| int vPos1, vPos2, uPos1, uPos2; |
| |
| /* copy y table */ |
| for (i = 0; i < width * height; i++) { |
| j = i * 2; |
| dstBuf[j] = srcBuf[i]; |
| } |
| |
| for (i = 0; i < width * height / 2; i += 2) { |
| j = width * height; |
| k = width * 2; |
| uPos1 = (i / width) * k * 2 + (i % width) * 2 + 1; |
| uPos2 = uPos1 + k; |
| vPos1 = uPos1 + 2; |
| vPos2 = uPos2 + 2; |
| |
| if (uPos1 >= 0) { |
| dstBuf[vPos1] = srcBuf[j + i]; /* V table */ |
| dstBuf[vPos2] = srcBuf[j + i]; /* V table */ |
| dstBuf[uPos1] = srcBuf[j + i + 1]; /* U table */ |
| dstBuf[uPos2] = srcBuf[j + i + 1]; /* U table */ |
| } |
| } |
| |
| return true; |
| } |
| |
| bool SecCameraHardware::conversion420Tto422(uint8_t *srcBuf, uint8_t *dstBuf, int width, int height) |
| { |
| int i, j, k; |
| int vPos1, vPos2, uPos1, uPos2; |
| |
| /* copy y table */ |
| for (i = 0; i < width * height; i++) { |
| j = i * 2; |
| dstBuf[j] = srcBuf[i]; |
| } |
| for (i = 0; i < width * height / 2; i+=2) { |
| j = width * height; |
| k = width * 2; |
| uPos1 = (i / width) * k * 2 + (i % width) * 2 + 1; |
| uPos2 = uPos1 + k; |
| vPos1 = uPos1 + 2; |
| vPos2 = uPos2 + 2; |
| |
| if (uPos1 >= 0) { |
| dstBuf[uPos1] = srcBuf[j + i]; /* V table */ |
| dstBuf[uPos2] = srcBuf[j + i]; /* V table */ |
| dstBuf[vPos1] = srcBuf[j + i + 1]; /* U table */ |
| dstBuf[vPos2] = srcBuf[j + i + 1]; /* U table */ |
| } |
| } |
| |
| return true; |
| } |
| |
| #if IS_FW_DEBUG |
| void SecCameraHardware::dump_is_fw_log(const char *fname, int8_t *buf, uint32_t size) |
| { |
| int nw, cnt = 0; |
| uint32_t written = 0; |
| char fileName[50]; |
| |
| sprintf(fileName, "/sdcard/log/IS%s.log", fname); |
| /* ALOGD("opening file [%s]\n", fileName); */ |
| int fd = open(fileName, O_RDWR | O_CREAT, 0664); |
| if (fd < 0) { |
| system("mkdir sdcard/log"); |
| |
| fd = open(fileName, O_RDWR | O_CREAT, 0664); |
| if (fd < 0) { |
| ALOGE("failed to create file [%s]: %s", fileName, strerror(errno)); |
| return; |
| } |
| } |
| |
| /* ALOGD("writing %d bytes to file [%s]\n", size, fileName); */ |
| while (written < size) { |
| nw = ::write(fd, |
| buf + written, |
| size - written); |
| if (nw < 0) { |
| ALOGE("failed to write to file [%s]: %s", |
| fname, strerror(errno)); |
| break; |
| } |
| written += nw; |
| cnt++; |
| } |
| /* ALOGD("done writing %d bytes to file [%s] in %d passes\n", size, fileName, cnt); */ |
| ::close(fd); |
| } |
| #endif |
| |
| int SecCameraHardware::mSaveDump(const char *filepath, ExynosBuffer *dstBuf, int index) |
| { |
| FILE *yuv_fp = NULL; |
| char filename[100]; |
| char *buffer = NULL; |
| CLEAR(filename); |
| |
| /* file create/open, note to "wb" */ |
| snprintf(filename, 100, filepath, index); |
| yuv_fp = fopen(filename, "wb"); |
| if (yuv_fp == NULL) { |
| ALOGE("Save jpeg file open error[%s]", filename); |
| return -1; |
| } |
| |
| int yuv_size = dstBuf->size.extS[0] + dstBuf->size.extS[1] + dstBuf->size.extS[2]; |
| |
| buffer = (char *) malloc(yuv_size); |
| if (buffer == NULL) { |
| ALOGE("Save YUV] buffer alloc failed"); |
| if (yuv_fp) |
| fclose(yuv_fp); |
| |
| return -1; |
| } |
| |
| memcpy(buffer, dstBuf->virt.extP[0], dstBuf->size.extS[0]); |
| if (dstBuf->size.extS[1] > 0) { |
| memcpy(buffer + dstBuf->size.extS[0], |
| dstBuf->virt.extP[1], dstBuf->size.extS[1]); |
| if (dstBuf->size.extS[2] > 0) { |
| memcpy(buffer + dstBuf->size.extS[0] + dstBuf->size.extS[1], |
| dstBuf->virt.extP[2], dstBuf->size.extS[2]); |
| } |
| } |
| |
| fflush(stdout); |
| |
| fwrite(buffer, 1, yuv_size, yuv_fp); |
| |
| fflush(yuv_fp); |
| |
| if (yuv_fp) |
| fclose(yuv_fp); |
| if (buffer) |
| free(buffer); |
| |
| return 0; |
| } |
| |
| |
| int SecCameraHardware::createInstance(int cameraId) |
| { |
| if (!init()) { |
| ALOGE("createInstance: error, camera cannot be initialiezed"); |
| mInitialized = false; |
| return NO_INIT; |
| } |
| |
| initDefaultParameters(); |
| ALOGD("createInstance: %s camera, created ", |
| cameraId == CAMERA_FACING_BACK ? "Back" : "Front"); |
| |
| mInitialized = true; |
| return NO_ERROR; |
| } |
| |
| }; /* namespace android */ |
| |
| #endif /* ANDROID_HARDWARE_SECCAMERAHARDWARE_CPP */ |