status_t ExynosCameraPipeSCP::m_getBuffer(void) { ExynosCameraFrame *curFrame = NULL; ExynosCameraBuffer curBuffer; int index = -1; int ret = 0; if (m_numOfRunningFrame <= 0 || m_flagStartPipe == false) { ALOGD("DEBUG(%s[%d]): skip getBuffer, flagStartPipe(%d), numOfRunningFrame = %d", __FUNCTION__, __LINE__, m_flagStartPipe, m_numOfRunningFrame); return NO_ERROR; } ret = m_mainNode->getBuffer(&curBuffer, &index); if (ret < 0) { CLOGE("ERR(%s[%d]):getBuffer fail", __FUNCTION__, __LINE__); /* TODO: doing exception handling */ return ret; } if (index < 0) { CLOGE("ERR(%s[%d]):Invalid index(%d) fail", __FUNCTION__, __LINE__, index); return INVALID_OPERATION; } m_activityControl->activityAfterExecFunc(getPipeId(), (void *)&curBuffer); /* complete frame */ ret = m_completeFrame(&curFrame, curBuffer); if (ret < 0) { CLOGE("ERR(%s):m_comleteFrame fail", __FUNCTION__); /* TODO: doing exception handling */ } if (curFrame == NULL) { CLOGE("ERR(%s):curFrame is fail", __FUNCTION__); } ret = curFrame->setDstBufferState(getPipeId(), ENTITY_BUFFER_STATE_COMPLETE); if (ret < 0) { CLOGE("ERR(%s): setDstBuffer state fail", __FUNCTION__); return ret; } m_outputFrameQ->pushProcessQ(&curFrame); return NO_ERROR; }
status_t ExynosCameraPipeJpeg::create(int32_t *sensorIds) { m_mainThread = ExynosCameraThreadFactory::createThread(this, &ExynosCameraPipeJpeg::m_mainThreadFunc, "JpegThread"); m_mainNode = NULL; m_inputFrameQ = new frame_queue_t(m_mainThread); ALOGI("INFO(%s[%d]):create() is succeed (%d)", __FUNCTION__, __LINE__, getPipeId()); return NO_ERROR; }
status_t ExynosCameraPipeJpeg::destroy(void) { if (m_inputFrameQ != NULL) { m_inputFrameQ->release(); delete m_inputFrameQ; m_inputFrameQ = NULL; } ALOGI("INFO(%s[%d]):destroy() is succeed (%d)", __FUNCTION__, __LINE__, getPipeId()); return NO_ERROR; }
status_t ExynosCameraPipeSCP::setupPipe(camera_pipe_info_t *pipeInfos) { CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); status_t ret = NO_ERROR; /* TODO: check node state stream on? */ /* initialize node */ int maxW = pipeInfos[0].rectInfo.fullW; int maxH = pipeInfos[0].rectInfo.fullH; int colorFormat = pipeInfos[0].rectInfo.colorFormat; enum v4l2_buf_type bufType = (enum v4l2_buf_type)pipeInfos[0].bufInfo.type; enum v4l2_memory memType = (enum v4l2_memory)pipeInfos[0].bufInfo.memory; m_numBuffers = pipeInfos[0].bufInfo.count; m_mainNode->setSize(maxW, maxH); m_mainNode->setColorFormat(colorFormat, 4); m_mainNode->setBufferType(m_numBuffers, bufType, memType); m_mainNode->setFormat(); m_mainNode->reqBuffers(); /* setfile setting */ #ifdef SET_SETFILE_BY_SHOT /* nop */ #else #if SET_SETFILE_BY_SET_CTRL_SCP int setfile = 0; int yuvRange = 0; m_parameters->getSetfileYuvRange(m_reprocessing, &setfile, &yuvRange); ret = m_mainNode->setControl(V4L2_CID_IS_COLOR_RANGE, yuvRange); if (ret != NO_ERROR) { CLOGE("ERR(%s[%d]):setControl(%d) fail(ret = %d)", __FUNCTION__, __LINE__, setfile, ret); return ret; } #endif #endif for (uint32_t i = 0; i < m_numBuffers; i++) { m_runningFrameList[i] = NULL; } m_numOfRunningFrame = 0; m_prepareBufferCount = m_exynosconfig->current->pipeInfo.prepare[getPipeId()]; ALOGI("INFO(%s[%d]):setupPipe() is succeed (%d) setupPipe (%d)", __FUNCTION__, __LINE__, getPipeId(), m_prepareBufferCount); return NO_ERROR; }
status_t ExynosCameraPipeJpeg::startThread(void) { ALOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); start(); if (m_outputFrameQ == NULL) { ALOGE("ERR(%s):outputFrameQ is NULL, cannot start", __FUNCTION__); return INVALID_OPERATION; } m_mainThread->run(); ALOGI("INFO(%s[%d]):startThread is succeed (%d)", __FUNCTION__, __LINE__, getPipeId()); return NO_ERROR; }
status_t ExynosCameraPipeSCP::create(int32_t *sensorIds) { CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); int ret = 0; if (sensorIds == NULL) { ALOGE("ERR(%s[%d]): Pipe need sensorId", __FUNCTION__, __LINE__); return BAD_VALUE; } m_mainNode = new ExynosCameraNode(); ret = m_mainNode->create("SCP"); if (ret < 0) { ALOGE("ERR(%s[%d]): mainNode create fail, ret(%d)", __FUNCTION__, __LINE__, ret); return ret; } ret = m_mainNode->open(m_mainNodeNum); if (ret < 0) { ALOGE("ERR(%s[%d]): mainNode open fail, ret(%d)", __FUNCTION__, __LINE__, ret); return ret; } ALOGD("DEBUG(%s):Node(%d) opened", __FUNCTION__, m_mainNodeNum); ret = m_mainNode->setInput(sensorIds[CAPTURE_NODE]); if (ret < 0) { ALOGE("ERR(%s[%d]): mainNode setInput fail, sensorId(%d), ret(%d)", __FUNCTION__, __LINE__, sensorIds[CAPTURE_NODE], ret); return ret; } m_mainThread = ExynosCameraThreadFactory::createThread(this, &ExynosCameraPipeSCP::m_mainThreadFunc, "SCPThread", PRIORITY_URGENT_DISPLAY); m_inputFrameQ = new frame_queue_t; m_prepareBufferCount = m_exynosconfig->current->pipeInfo.prepare[getPipeId()]; ALOGI("INFO(%s[%d]):create() is succeed (%d) setupPipe (%d)", __FUNCTION__, __LINE__, getPipeId(), m_prepareBufferCount); return NO_ERROR; }
status_t ExynosCameraPipeSCP::destroy(void) { CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__); if (m_mainNode != NULL) { if (m_mainNode->close() != NO_ERROR) { CLOGE("ERR(%s):close fail", __FUNCTION__); return INVALID_OPERATION; } delete m_mainNode; m_mainNode = NULL; ALOGD("DEBUG(%s):Node(%d) closed", __FUNCTION__, FIMC_IS_VIDEO_SCP_NUM); } if (m_inputFrameQ != NULL) { m_inputFrameQ->release(); delete m_inputFrameQ; m_inputFrameQ = NULL; } ALOGI("INFO(%s[%d]):destroy() is succeed (%d)", __FUNCTION__, __LINE__, getPipeId()); return NO_ERROR; }
MBOOL PipeImp:: configMdpOutPort(PortInfo const* oImgInfo, MdpRotDMACfg &a_rotDma) { MUINT32 plane_num = 1; MUINT32 uv_resample = 1; MUINT32 uv_h_ratio = 1; MUINT32 uv_v_ratio = 1; MUINT32 y_plane_size = 0; MUINT32 u_plane_size = 0; // PIPE_DBG("[oImgInfo]w(%d),h(%d),stride(%d/%d/%d),crop(%d,%d,%d,%d)_f(0x%x, 0x%x),rot(%d) eImgFmt(%d)", oImgInfo->u4ImgWidth,oImgInfo->u4ImgHeight,oImgInfo->u4Stride[ESTRIDE_1ST_PLANE],oImgInfo->u4Stride[ESTRIDE_2ND_PLANE],oImgInfo->u4Stride[ESTRIDE_3RD_PLANE], \ oImgInfo->crop1.x,oImgInfo->crop1.y,oImgInfo->crop1.w,oImgInfo->crop1.h,oImgInfo->crop1.floatX,oImgInfo->crop1.floatY, \ oImgInfo->eImgRot,oImgInfo->eImgFmt ); // if ( ePipeID_1x1_Sensor_Tg_Mem == getPipeId() ) { PIPE_ERR("Pipe Not Support"); return MFALSE; } // a_rotDma.uv_plane_swap = 0; // switch( oImgInfo->eImgFmt ) { case eImgFmt_YV12: //= 0x00008, //420 format, 3 plane(YVU) case eImgFmt_I420: //= 0x20000, //420 format, 3 plane(YUV) a_rotDma.Format = CRZ_DRV_FORMAT_YUV420; a_rotDma.Plane = CRZ_DRV_PLANE_3; a_rotDma.Sequence = CRZ_DRV_SEQUENCE_UVUV; //don't care, but cdp_drv need to set this value , why? plane_num = 3; uv_h_ratio = 2; uv_v_ratio = 2; a_rotDma.uv_plane_swap = (eImgFmt_YV12==oImgInfo->eImgFmt)?1:0; break; case eImgFmt_I422: //422 format, 3 plane(YUV) a_rotDma.Format = CRZ_DRV_FORMAT_YUV422; a_rotDma.Plane = CRZ_DRV_PLANE_3; a_rotDma.Sequence = CRZ_DRV_SEQUENCE_UVUV; //don't care, but cdp_drv need to set this value , why? plane_num = 3; uv_h_ratio = 2; uv_v_ratio = 1; break; case eImgFmt_NV21: //= 0x0010, //420 format, 2 plane (VU) a_rotDma.Format = CRZ_DRV_FORMAT_YUV420; a_rotDma.Plane = CRZ_DRV_PLANE_2; a_rotDma.Sequence = CRZ_DRV_SEQUENCE_UVUV; //MSN->LSB plane_num = 2; uv_h_ratio = 2; uv_v_ratio = 2; break; case eImgFmt_NV12: //= 0x0040, //420 format, 2 plane (UV) a_rotDma.Format = CRZ_DRV_FORMAT_YUV420; a_rotDma.Plane = CRZ_DRV_PLANE_2; a_rotDma.Sequence = CRZ_DRV_SEQUENCE_VUVU; //MSN->LSB plane_num = 2; uv_h_ratio = 2; uv_v_ratio = 2; break; case eImgFmt_YUY2: //= 0x0100, //422 format, 1 plane (YUYV) a_rotDma.Format = CRZ_DRV_FORMAT_YUV422; a_rotDma.Plane = CRZ_DRV_PLANE_1; a_rotDma.Sequence = CRZ_DRV_SEQUENCE_VYUY; //MSN->LSB break; case eImgFmt_UYVY: //= 0x0200, //422 format, 1 plane (UYVY) a_rotDma.Format = CRZ_DRV_FORMAT_YUV422; a_rotDma.Plane = CRZ_DRV_PLANE_1; a_rotDma.Sequence = CRZ_DRV_SEQUENCE_YVYU; //MSN->LSB break; case eImgFmt_YV16: //422 format, 3 plane a_rotDma.Format = CRZ_DRV_FORMAT_YUV422; a_rotDma.Plane = CRZ_DRV_PLANE_3; a_rotDma.Sequence = (CRZ_DRV_SEQUENCE_ENUM)0; //MSN->LSB plane_num = 3; uv_h_ratio = 2; uv_v_ratio = 1; break; case eImgFmt_NV16: //422 format, 2 plane a_rotDma.Format = CRZ_DRV_FORMAT_YUV422; a_rotDma.Plane = CRZ_DRV_PLANE_2; a_rotDma.Sequence = CRZ_DRV_SEQUENCE_VUVU; //MSN->LSB plane_num = 2; uv_h_ratio = 2; uv_v_ratio = 1; break; case eImgFmt_RGB565: //= 0x0400, //RGB 565 (16-bit), 1 plane a_rotDma.Format = CRZ_DRV_FORMAT_RGB565; a_rotDma.Plane = CRZ_DRV_PLANE_1; a_rotDma.Sequence = CRZ_DRV_SEQUENCE_RGB; //MSN->LSB break; case eImgFmt_RGB888: //= 0x0800, //RGB 888 (24-bit), 1 plane a_rotDma.Format = CRZ_DRV_FORMAT_RGB888; a_rotDma.Plane = CRZ_DRV_PLANE_1; a_rotDma.Sequence = CRZ_DRV_SEQUENCE_BGR; //MSN->LSB break; case eImgFmt_ARGB8888: //= 0x1000, //ARGB (32-bit), 1 plane a_rotDma.Format = CRZ_DRV_FORMAT_XRGB8888; a_rotDma.Plane = CRZ_DRV_PLANE_1; a_rotDma.Sequence = CRZ_DRV_SEQUENCE_XBGR; //MSN->LSB break; case eImgFmt_Y800: //= 0x040000, //Y plane only a_rotDma.Format = CRZ_DRV_FORMAT_Y; a_rotDma.Plane = CRZ_DRV_PLANE_1; a_rotDma.Sequence = CRZ_DRV_SEQUENCE_Y; //MSN->LSB break; case eImgFmt_JPG_I420: a_rotDma.Format = CRZ_DRV_FORMAT_JPEG_YUV420; a_rotDma.Plane = CRZ_DRV_PLANE_3; a_rotDma.Sequence = CRZ_DRV_SEQUENCE_UVUV; //don't care, plane_num = 3; uv_h_ratio = 2; uv_v_ratio = 2; break; case eImgFmt_JPG_I422: a_rotDma.Format = CRZ_DRV_FORMAT_JPEG_YUV422; a_rotDma.Plane = CRZ_DRV_PLANE_3; a_rotDma.Sequence = CRZ_DRV_SEQUENCE_UVUV; //don't care, plane_num = 3; uv_h_ratio = 2; uv_v_ratio = 1; break; case eImgFmt_BAYER8: //= 0x0001, //Bayer format, 8-bit // for imgo a_rotDma.Format = CRZ_DRV_FORMAT_RAW8; a_rotDma.Plane = CRZ_DRV_PLANE_1; break; case eImgFmt_BAYER10: //= 0x0002, //Bayer format, 10-bit // for imgo a_rotDma.Format = CRZ_DRV_FORMAT_RAW10; a_rotDma.Plane = CRZ_DRV_PLANE_1; break; case eImgFmt_BAYER12: //= 0x0004, //Bayer format, 12-bit // for imgo a_rotDma.Format = CRZ_DRV_FORMAT_RAW12; a_rotDma.Plane = CRZ_DRV_PLANE_1; break; case eImgFmt_NV21_BLK: //= 0x0020, //420 format block mode, 2 plane (UV) case eImgFmt_NV12_BLK: //= 0x0080, //420 format block mode, 2 plane (VU) case eImgFmt_JPEG: //= 0x2000, //JPEG format default: PIPE_ERR("vOutPorts[]->eImgFmt:Format(%d) NOT Support",oImgInfo->eImgFmt); break; } // //ROTATION, stride is after, others are before a_rotDma.Rotation = (CRZ_DRV_ROTATION_ENUM)oImgInfo->eImgRot; a_rotDma.Flip = (eImgFlip_ON == oImgInfo->eImgFlip)?MTRUE:MFALSE; //dma port capbility a_rotDma.capbility=oImgInfo->capbility; //Y a_rotDma.memBuf.base_pAddr = oImgInfo->u4BufPA[0]; a_rotDma.memBuf.base_vAddr = oImgInfo->u4BufVA[0]; a_rotDma.memBuf.size = oImgInfo->u4BufSize[0]; a_rotDma.memBuf.ofst_addr = 0; a_rotDma.memBuf.alignment = 0; //after ROT a_rotDma.size.w = oImgInfo->u4ImgWidth; a_rotDma.size.h = oImgInfo->u4ImgHeight; //stride info after ROT a_rotDma.size.stride = oImgInfo->u4Stride[ESTRIDE_1ST_PLANE]; // y_plane_size = oImgInfo->u4BufSize[ESTRIDE_1ST_PLANE]; //tpipemain lib need image info before ROT. stride info after ROT //if ( CRZ_DRV_ROTATION_90 == a_rotDma.Rotation || CRZ_DRV_ROTATION_270 == a_rotDma.Rotation ) { // // a_rotDma.size.w = oImgInfo->u4ImgHeight; // a_rotDma.size.h = oImgInfo->u4ImgWidth; //} // if ( 2<=plane_num) { //U a_rotDma.memBuf_c.base_pAddr = oImgInfo->u4BufPA[ESTRIDE_2ND_PLANE]; a_rotDma.memBuf_c.base_vAddr = oImgInfo->u4BufVA[ESTRIDE_2ND_PLANE]; a_rotDma.memBuf_c.ofst_addr = 0; a_rotDma.memBuf_c.alignment = 0; //after ROT a_rotDma.size_c.w = a_rotDma.size.w/uv_h_ratio; a_rotDma.size_c.h = a_rotDma.size.h/uv_v_ratio; //stride info after ROT a_rotDma.size_c.stride = oImgInfo->u4Stride[ESTRIDE_2ND_PLANE]; // u_plane_size = oImgInfo->u4BufSize[ESTRIDE_2ND_PLANE]; //tpipemain lib need image info before ROT. stride info after ROT //if ( CRZ_DRV_ROTATION_90 == a_rotDma.Rotation || CRZ_DRV_ROTATION_270 == a_rotDma.Rotation ) { // a_rotDma.size_c.w = a_rotDma.size.h/uv_v_ratio; // a_rotDma.size_c.h = a_rotDma.size.w/uv_h_ratio; //} // if ( 3 == plane_num ) { //V a_rotDma.memBuf_v.base_pAddr = oImgInfo->u4BufPA[ESTRIDE_3RD_PLANE]; a_rotDma.memBuf_v.base_vAddr = oImgInfo->u4BufVA[ESTRIDE_3RD_PLANE]; a_rotDma.memBuf_v.ofst_addr = 0; a_rotDma.memBuf_v.alignment = 0; //after ROT a_rotDma.size_v.w = a_rotDma.size_c.w; a_rotDma.size_v.h = a_rotDma.size_c.h; //stride info after ROT a_rotDma.size_v.stride = oImgInfo->u4Stride[ESTRIDE_3RD_PLANE]; //tpipemain lib need image info BEFORE ROT. stride info AFTER ROT //if ( CRZ_DRV_ROTATION_90 == a_rotDma.Rotation || CRZ_DRV_ROTATION_270 == a_rotDma.Rotation ) { // a_rotDma.size_v.w = a_rotDma.size_c.h; // a_rotDma.size_v.h = a_rotDma.size_c.w; //} } // /* if ( a_rotDma.uv_plane_swap ) { a_rotDma.memBuf_c.base_pAddr = oImgInfo->u4BufPA[ESTRIDE_3RD_PLANE]; a_rotDma.memBuf_c.base_vAddr = oImgInfo->u4BufVA[ESTRIDE_3RD_PLANE]; a_rotDma.memBuf_v.base_pAddr = oImgInfo->u4BufPA[ESTRIDE_2ND_PLANE]; a_rotDma.memBuf_v.base_vAddr = oImgInfo->u4BufVA[ESTRIDE_2ND_PLANE]; } */ } //tpipemain lib need image info before ROT. stride info after ROT //if ( CRZ_DRV_ROTATION_90 == a_rotDma.Rotation || CRZ_DRV_ROTATION_270 == a_rotDma.Rotation ) { // // // a_rotDma.size.w = oImgInfo->u4ImgHeight; // a_rotDma.size.h = oImgInfo->u4ImgWidth; //} /* * DONOT USE CRZ CROP due to throughtput issue */ //default set ENABLE, if need to be programmable, check cdp driver as well. a_rotDma.crop_en = 1; //always enable crop for rotation issue. // a_rotDma.crop.x = 0; a_rotDma.crop.floatX = 0; a_rotDma.crop.y = 0; a_rotDma.crop.floatY = 0; a_rotDma.crop.w = 0; a_rotDma.crop.h = 0; // PIPE_DBG("[a_rotDma]w(%d),h(%d),stride(pxl)(%d),pa(0x%x),va(0x%x),size(%d)",a_rotDma.size.w,a_rotDma.size.h,a_rotDma.size.stride,a_rotDma.memBuf.base_pAddr,a_rotDma.memBuf.base_vAddr,a_rotDma.memBuf.size); PIPE_DBG("[a_rotDma]crop(%d,%d,%d,%d)_f(0x%x,0x%x)",a_rotDma.crop.x,a_rotDma.crop.y,a_rotDma.crop.w,a_rotDma.crop.h,a_rotDma.crop.floatX,a_rotDma.crop.floatY); PIPE_DBG("[a_rotDma]rot(%d),fmt(%d),plane(%d),seq(%d),pxlByte((0x%x))",a_rotDma.Rotation,a_rotDma.Format,a_rotDma.Plane,a_rotDma.Sequence,a_rotDma.pixel_byte); PIPE_DBG("[a_rotDma]c_ofst_addr(0x%x),v_ofst_addr(0x%x),uv_plane_swap(%d)",a_rotDma.memBuf_c.ofst_addr,a_rotDma.memBuf_v.ofst_addr,a_rotDma.uv_plane_swap); PIPE_DBG("[a_rotDma]va[0x%x,0x%x,0x%x]--pa[0x%x,0x%x,0x%x]", a_rotDma.memBuf.base_vAddr,a_rotDma.memBuf_c.base_vAddr,a_rotDma.memBuf_v.base_vAddr,a_rotDma.memBuf.base_pAddr,a_rotDma.memBuf_c.base_pAddr,a_rotDma.memBuf_v.base_pAddr); return MTRUE; }
status_t ExynosCameraPipeSCP::m_putBuffer(void) { ExynosCameraFrame *newFrame = NULL; ExynosCameraBuffer newBuffer; int ret = 0; retry: ret = m_inputFrameQ->waitAndPopProcessQ(&newFrame); if (ret < 0) { /* TODO: We need to make timeout duration depends on FPS */ if (ret == TIMED_OUT) { CLOGW("WARN(%s):wait timeout", __FUNCTION__); m_mainNode->dumpState(); } else { CLOGE("ERR(%s):wait and pop fail, ret(%d)", __FUNCTION__, ret); /* TODO: doing exception handling */ } return ret; } if (newFrame == NULL) { CLOGE("ERR(%s):newFrame is NULL", __FUNCTION__); return INVALID_OPERATION; } ret = newFrame->getDstBuffer(getPipeId(), &newBuffer); if (ret < 0) { CLOGE("ERR(%s[%d]):frame get buffer fail, ret(%d)", __FUNCTION__, __LINE__, ret); /* TODO: doing exception handling */ return OK; } /* check buffer index */ if (newBuffer.index < 0) { CLOGD("DEBUG(%s[%d]): no buffer to QBUF (%d)", __FUNCTION__, __LINE__, newFrame->getFrameCount()); ret = newFrame->setDstBufferState(getPipeId(), ENTITY_BUFFER_STATE_REQUESTED); if (ret < 0) { CLOGE("ERR(%s): setDstBuffer state fail", __FUNCTION__); return ret; } ret = newFrame->setEntityState(getPipeId(), ENTITY_STATE_FRAME_DONE); if (ret < 0) { CLOGE("ERR(%s[%d]):set entity state fail, ret(%d)", __FUNCTION__, __LINE__, ret); /* TODO: doing exception handling */ return OK; } CLOGV("DEBUG(%s):entity pipeId(%d), frameCount(%d), numOfRunningFrame(%d), requestCount(%d)", __FUNCTION__, getPipeId(), newFrame->getFrameCount(), m_numOfRunningFrame, m_requestCount); usleep(33000); m_outputFrameQ->pushProcessQ(&newFrame); goto retry; } else { if (m_runningFrameList[newBuffer.index] != NULL) { CLOGE("ERR(%s):new buffer is invalid, we already get buffer index(%d), newFrame->frameCount(%d)", __FUNCTION__, newBuffer.index, newFrame->getFrameCount()); m_dumpRunningFrameList(); return BAD_VALUE; } camera2_shot_ext *shot_ext = (struct camera2_shot_ext *)(newBuffer.addr[1]); if (shot_ext != NULL) { newFrame->getMetaData(shot_ext); m_parameters->duplicateCtrlMetadata((void *)shot_ext); m_activityControl->activityBeforeExecFunc(getPipeId(), (void *)&newBuffer); if (m_perframeMainNodeGroupInfo.perFrameLeaderInfo.perFrameNodeType == PERFRAME_NODE_TYPE_LEADER) { camera2_node_group node_group_info; memset(&shot_ext->node_group, 0x0, sizeof(camera2_node_group)); newFrame->getNodeGroupInfo(&node_group_info, m_perframeMainNodeGroupInfo.perFrameLeaderInfo.perframeInfoIndex); /* Per - Leader */ if (node_group_info.leader.request == 1) { setMetaNodeLeaderInputSize(shot_ext, node_group_info.leader.input.cropRegion[0], node_group_info.leader.input.cropRegion[1], node_group_info.leader.input.cropRegion[2], node_group_info.leader.input.cropRegion[3]); setMetaNodeLeaderOutputSize(shot_ext, node_group_info.leader.output.cropRegion[0], node_group_info.leader.output.cropRegion[1], node_group_info.leader.output.cropRegion[2], node_group_info.leader.output.cropRegion[3]); setMetaNodeLeaderRequest(shot_ext, node_group_info.leader.request); setMetaNodeLeaderVideoID(shot_ext, m_perframeMainNodeGroupInfo.perFrameLeaderInfo.perFrameVideoID); } /* Per - Captures */ for (int i = 0; i < m_perframeMainNodeGroupInfo.perframeSupportNodeNum - 1; i ++) { if (node_group_info.capture[i].request == 1) { setMetaNodeCaptureInputSize(shot_ext, i, node_group_info.capture[i].input.cropRegion[0], node_group_info.capture[i].input.cropRegion[1], node_group_info.capture[i].input.cropRegion[2], node_group_info.capture[i].input.cropRegion[3]); setMetaNodeCaptureOutputSize(shot_ext, i, node_group_info.capture[i].output.cropRegion[0], node_group_info.capture[i].output.cropRegion[1], node_group_info.capture[i].output.cropRegion[2], node_group_info.capture[i].output.cropRegion[3]); setMetaNodeCaptureRequest(shot_ext, i, node_group_info.capture[i].request); setMetaNodeCaptureVideoID(shot_ext, i, m_perframeMainNodeGroupInfo.perFrameCaptureInfo[i].perFrameVideoID); } } } } ret = m_mainNode->putBuffer(&newBuffer); if (ret < 0) { CLOGE("ERR(%s):putBuffer fail", __FUNCTION__); return ret; /* TODO: doing exception handling */ } ret = newFrame->setDstBufferState(getPipeId(), ENTITY_BUFFER_STATE_PROCESSING); if (ret < 0) { CLOGE("ERR(%s): setDstBuffer state fail", __FUNCTION__); return ret; } m_runningFrameList[newBuffer.index] = newFrame; m_numOfRunningFrame++; } return NO_ERROR; }
status_t ExynosCameraPipeJpeg::m_run(void) { ExynosCameraAutoTimer autoTimer(__FUNCTION__); status_t ret = 0; ExynosCameraFrame *newFrame = NULL; ExynosCameraBuffer yuvBuf; ExynosCameraBuffer jpegBuf; ExynosRect pictureRect; int jpegQuality = m_parameters->getJpegQuality(); ExynosRect thumbnailRect; int thumbnailQuality = m_parameters->getThumbnailQuality(); exif_attribute_t exifInfo; m_parameters->getFixedExifInfo(&exifInfo); struct camera2_shot_ext shot_ext; memset(&shot_ext, 0x00, sizeof(struct camera2_shot_ext)); pictureRect.colorFormat = m_parameters->getPictureFormat(); m_parameters->getPictureSize(&pictureRect.w, &pictureRect.h); m_parameters->getThumbnailSize(&thumbnailRect.w, &thumbnailRect.h); ALOGI("DEBUG(%s[%d]): -IN-", __FUNCTION__, __LINE__); ALOGD("DEBUG(%s[%d]):picture size(%dx%d), thumbnail size(%dx%d)", __FUNCTION__, __LINE__, pictureRect.w, pictureRect.h, thumbnailRect.w, thumbnailRect.h); ret = m_inputFrameQ->waitAndPopProcessQ(&newFrame); if (ret < 0) { /* TODO: We need to make timeout duration depends on FPS */ if (ret == TIMED_OUT) { ALOGW("WARN(%s):wait timeout", __FUNCTION__); } else { ALOGE("ERR(%s):wait and pop fail, ret(%d)", __FUNCTION__, ret); /* TODO: doing exception handling */ } return ret; } if (newFrame == NULL) { ALOGE("ERR(%s):new frame is NULL", __FUNCTION__); return NO_ERROR; } ret = newFrame->getSrcBuffer(getPipeId(), &yuvBuf); if (ret < 0) { CLOGE("ERR(%s[%d]):frame get src buffer fail, ret(%d)", __FUNCTION__, __LINE__, ret); /* TODO: doing exception handling */ return OK; } ret = newFrame->getDstBuffer(getPipeId(), &jpegBuf); if (ret < 0) { CLOGE("ERR(%s[%d]):frame get dst buffer fail, ret(%d)", __FUNCTION__, __LINE__, ret); /* TODO: doing exception handling */ return OK; } if (m_jpegEnc.create()) { ALOGE("ERR(%s):m_jpegEnc.create() fail", __FUNCTION__); ret = INVALID_OPERATION; goto jpeg_encode_done; } if (m_jpegEnc.setQuality(jpegQuality)) { ALOGE("ERR(%s):m_jpegEnc.setQuality() fail", __FUNCTION__); ret = INVALID_OPERATION; goto jpeg_encode_done; } if (m_jpegEnc.setSize(pictureRect.w, pictureRect.h)) { ALOGE("ERR(%s):m_jpegEnc.setSize() fail", __FUNCTION__); ret = INVALID_OPERATION; goto jpeg_encode_done; } if (m_jpegEnc.setColorFormat(pictureRect.colorFormat)) { ALOGE("ERR(%s):m_jpegEnc.setColorFormat() fail", __FUNCTION__); ret = INVALID_OPERATION; goto jpeg_encode_done; } if (m_jpegEnc.setJpegFormat(V4L2_PIX_FMT_JPEG_422)) { ALOGE("ERR(%s):m_jpegEnc.setJpegFormat() fail", __FUNCTION__); ret = INVALID_OPERATION; goto jpeg_encode_done; } if (thumbnailRect.w != 0 && thumbnailRect.h != 0) { exifInfo.enableThumb = true; if (pictureRect.w < 320 || pictureRect.h < 240) { thumbnailRect.w = 160; thumbnailRect.h = 120; } if (m_jpegEnc.setThumbnailSize(thumbnailRect.w, thumbnailRect.h)) { ALOGE("ERR(%s):m_jpegEnc.setThumbnailSize(%d, %d) fail", __FUNCTION__, thumbnailRect.w, thumbnailRect.h); ret = INVALID_OPERATION; goto jpeg_encode_done; } if (0 < thumbnailQuality && thumbnailQuality <= 100) { if (m_jpegEnc.setThumbnailQuality(thumbnailQuality)) { ret = INVALID_OPERATION; ALOGE("ERR(%s):m_jpegEnc.setThumbnailQuality(%d) fail", __FUNCTION__, thumbnailQuality); } } } else { exifInfo.enableThumb = false; } /* wait for medata update */ if(newFrame->getMetaDataEnable() == false) { CLOGD("DEBUG(%s[%d]): Waiting for update jpeg metadata failed (%d) ", __FUNCTION__, __LINE__, ret); } /* get dynamic meters for make exif info */ newFrame->getDynamicMeta(&shot_ext); newFrame->getUserDynamicMeta(&shot_ext); m_parameters->setExifChangedAttribute(&exifInfo, &pictureRect, &thumbnailRect,&shot_ext.shot.dm, &shot_ext.shot.udm); if (m_jpegEnc.setInBuf((int *)&(yuvBuf.fd), (int *)yuvBuf.size)) { ALOGE("ERR(%s):m_jpegEnc.setInBuf() fail", __FUNCTION__); ret = INVALID_OPERATION; goto jpeg_encode_done; } if (m_jpegEnc.setOutBuf(jpegBuf.fd[0], jpegBuf.size[0] + jpegBuf.size[1] + jpegBuf.size[2])) { ALOGE("ERR(%s):m_jpegEnc.setOutBuf() fail", __FUNCTION__); ret = INVALID_OPERATION; goto jpeg_encode_done; } if (m_jpegEnc.updateConfig()) { ALOGE("ERR(%s):m_jpegEnc.updateConfig() fail", __FUNCTION__); ret = INVALID_OPERATION; goto jpeg_encode_done; } if (m_jpegEnc.encode((int *)&jpegBuf.size, &exifInfo, m_parameters->getDebugAttribute())) { ALOGE("ERR(%s):m_jpegEnc.encode() fail", __FUNCTION__); ret = INVALID_OPERATION; goto jpeg_encode_done; } newFrame->setJpegSize(jpegBuf.size[0]); ret = newFrame->setEntityState(getPipeId(), ENTITY_STATE_FRAME_DONE); if (ret < 0) { CLOGE("ERR(%s[%d]):set entity state fail, ret(%d)", __FUNCTION__, __LINE__, ret); /* TODO: doing exception handling */ return OK; } m_outputFrameQ->pushProcessQ(&newFrame); jpeg_encode_done: if (ret != NO_ERROR) { ALOGD("[jpegBuf.fd[0] %d][jpegBuf.size[0] + jpegBuf.size[1] + jpegBuf.size[2] %d]", jpegBuf.fd[0], jpegBuf.size[0] + jpegBuf.size[1] + jpegBuf.size[2]); ALOGD("[pictureW %d][pictureH %d][pictureFormat %d]", pictureRect.w, pictureRect.h, pictureRect.colorFormat); } if (m_jpegEnc.flagCreate() == true) m_jpegEnc.destroy(); ALOGI("DEBUG(%s[%d]): -OUT-", __FUNCTION__, __LINE__); return ret; }