Jiyoung Shin | afd46e5 | 2012-04-17 18:01:11 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright Samsung Electronics Co.,LTD. |
| 3 | * Copyright (C) 2011 The Android Open Source Project |
| 4 | * |
| 5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | * you may not use this file except in compliance with the License. |
| 7 | * You may obtain a copy of the License at |
| 8 | * |
| 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | * |
| 11 | * Unless required by applicable law or agreed to in writing, software |
| 12 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | * See the License for the specific language governing permissions and |
| 15 | * limitations under the License. |
| 16 | */ |
| 17 | |
| 18 | #include <stdio.h> |
| 19 | #include <stdlib.h> |
| 20 | #include <sys/types.h> |
| 21 | #include <sys/stat.h> |
| 22 | #include <sys/ioctl.h> |
| 23 | #include <fcntl.h> |
| 24 | #include <ctype.h> |
| 25 | #include <unistd.h> |
| 26 | #include <sys/mman.h> |
| 27 | #include <string.h> |
| 28 | #include <errno.h> |
| 29 | #include <signal.h> |
| 30 | #include <math.h> |
| 31 | #include <sys/poll.h> |
| 32 | |
| 33 | #include <cutils/log.h> |
| 34 | |
| 35 | #include <utils/Log.h> |
| 36 | |
| 37 | #include "ExynosJpegApi.h" |
| 38 | |
| 39 | #define JPEG_DEC_NODE "/dev/video11" |
| 40 | #define JPEG_ENC_NODE "/dev/video12" |
| 41 | |
| 42 | #define MAX_JPG_WIDTH (8192) |
| 43 | #define MAX_JPG_HEIGHT (8192) |
| 44 | |
| 45 | #define JPEG_ERROR_LOG(fmt,...) |
| 46 | |
| 47 | ExynosJpegBase::ExynosJpegBase() |
| 48 | { |
| 49 | } |
| 50 | |
| 51 | ExynosJpegBase::~ExynosJpegBase() |
| 52 | { |
| 53 | } |
| 54 | |
| 55 | int ExynosJpegBase::t_v4l2Querycap(int iFd) |
| 56 | { |
| 57 | struct v4l2_capability cap; |
| 58 | int iRet = ERROR_NONE; |
| 59 | |
| 60 | iRet = ioctl(iFd, VIDIOC_QUERYCAP, &cap); |
| 61 | if (iRet < 0) { |
| 62 | JPEG_ERROR_LOG("[%s:%d]: VIDIOC_QUERYCAP failed\n", __func__, iRet); |
| 63 | return iRet; |
| 64 | } |
| 65 | |
| 66 | return iRet; |
| 67 | } |
| 68 | |
| 69 | int ExynosJpegBase::t_v4l2SetJpegcomp(int iFd, int iQuality) |
| 70 | { |
| 71 | struct v4l2_jpegcompression arg; |
| 72 | int iRet = ERROR_NONE; |
| 73 | |
| 74 | arg.quality = iQuality; |
| 75 | |
| 76 | iRet = ioctl(iFd, VIDIOC_S_JPEGCOMP, &arg); |
| 77 | if (iRet < 0) { |
| 78 | JPEG_ERROR_LOG("[%s:%d]: VIDIOC_S_JPEGCOMP failed\n", __func__, iRet); |
| 79 | return iRet; |
| 80 | } |
| 81 | |
| 82 | return iRet; |
| 83 | } |
| 84 | |
| 85 | int ExynosJpegBase::t_v4l2SetFmt(int iFd, enum v4l2_buf_type eType, struct CONFIG *pstConfig) |
| 86 | { |
| 87 | struct v4l2_format fmt; |
| 88 | int iRet = ERROR_NONE; |
| 89 | |
| 90 | fmt.type = eType; |
| 91 | fmt.fmt.pix_mp.width = pstConfig->width; |
| 92 | fmt.fmt.pix_mp.height = pstConfig->height; |
| 93 | fmt.fmt.pix_mp.field = V4L2_FIELD_ANY; |
| 94 | fmt.fmt.pix_mp.num_planes = pstConfig->numOfPlanes; |
| 95 | |
| 96 | if (pstConfig->mode == MODE_ENCODE) |
| 97 | fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_JPEG; |
| 98 | |
| 99 | switch (fmt.type) { |
| 100 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: // fall through |
| 101 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
| 102 | break; |
| 103 | case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: |
| 104 | if (pstConfig->mode == MODE_ENCODE) { |
| 105 | fmt.fmt.pix_mp.pixelformat = pstConfig->pix.enc_fmt.in_fmt; |
| 106 | } else { |
| 107 | fmt.fmt.pix_mp.pixelformat = pstConfig->pix.dec_fmt.in_fmt; |
| 108 | fmt.fmt.pix_mp.plane_fmt[0].sizeimage = pstConfig->sizeJpeg; |
| 109 | } |
| 110 | break; |
| 111 | case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: |
| 112 | if (pstConfig->mode == MODE_ENCODE) { |
| 113 | fmt.fmt.pix_mp.pixelformat = pstConfig->pix.enc_fmt.out_fmt; |
| 114 | } else { |
| 115 | fmt.fmt.pix_mp.pixelformat = pstConfig->pix.dec_fmt.out_fmt; |
| 116 | fmt.fmt.pix_mp.width = pstConfig->scaled_width; |
| 117 | fmt.fmt.pix_mp.height = pstConfig->scaled_height; |
| 118 | } |
| 119 | break; |
| 120 | default: |
| 121 | return ERROR_INVALID_V4l2_BUF_TYPE; |
| 122 | break; |
| 123 | } |
| 124 | |
| 125 | iRet = ioctl(iFd, VIDIOC_S_FMT, &fmt); |
| 126 | if (iRet < 0) { |
| 127 | JPEG_ERROR_LOG("[%s:%d]: VIDIOC_S_FMT failed\n", __func__, iRet); |
| 128 | return iRet; |
| 129 | } |
| 130 | |
| 131 | return iRet; |
| 132 | } |
| 133 | |
| 134 | int ExynosJpegBase::t_v4l2GetFmt(int iFd, enum v4l2_buf_type eType, struct CONFIG *pstConfig) |
| 135 | { |
| 136 | struct v4l2_format fmt; |
| 137 | int iRet = ERROR_NONE; |
| 138 | |
| 139 | fmt.type = eType; |
| 140 | iRet = ioctl(iFd, VIDIOC_G_FMT, &fmt); |
| 141 | if (iRet < 0) { |
| 142 | JPEG_ERROR_LOG("[%s:%d]: VIDIOC_G_FMT failed\n", __func__, iRet); |
| 143 | return iRet; |
| 144 | } |
| 145 | |
| 146 | switch (fmt.type) { |
| 147 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: // fall through |
| 148 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
| 149 | pstConfig->width = fmt.fmt.pix.width; |
| 150 | pstConfig->height = fmt.fmt.pix.height; |
| 151 | break; |
| 152 | case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: |
| 153 | pstConfig->width = fmt.fmt.pix_mp.width; |
| 154 | pstConfig->height = fmt.fmt.pix_mp.height; |
| 155 | if (pstConfig->mode == MODE_ENCODE) |
| 156 | pstConfig->pix.enc_fmt.in_fmt = fmt.fmt.pix_mp.pixelformat; |
| 157 | else |
| 158 | pstConfig->pix.dec_fmt.in_fmt = fmt.fmt.pix_mp.pixelformat; |
| 159 | break; |
| 160 | case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: |
| 161 | pstConfig->width = fmt.fmt.pix_mp.width; |
| 162 | pstConfig->height = fmt.fmt.pix_mp.height; |
| 163 | if (pstConfig->mode == MODE_ENCODE) |
| 164 | pstConfig->pix.enc_fmt.out_fmt = fmt.fmt.pix_mp.pixelformat; |
| 165 | else |
| 166 | pstConfig->pix.dec_fmt.out_fmt = fmt.fmt.pix_mp.pixelformat; |
| 167 | break; |
| 168 | default: |
| 169 | return ERROR_INVALID_V4l2_BUF_TYPE; |
| 170 | } |
| 171 | |
| 172 | return iRet; |
| 173 | } |
| 174 | |
| 175 | int ExynosJpegBase::t_v4l2Reqbufs(int iFd, int iBufCount, struct BUF_INFO *pstBufInfo) |
| 176 | { |
| 177 | struct v4l2_requestbuffers req; |
| 178 | int iRet = ERROR_NONE; |
| 179 | |
Jiyoung Shin | 1ae2a55 | 2012-06-01 16:11:04 -0700 | [diff] [blame] | 180 | memset(&req, 0, sizeof(v4l2_requestbuffers)); |
Jiyoung Shin | afd46e5 | 2012-04-17 18:01:11 -0700 | [diff] [blame] | 181 | |
| 182 | req.type = pstBufInfo->buf_type; |
| 183 | req.memory = pstBufInfo->memory; |
| 184 | |
| 185 | //if (pstBufInfo->memory == V4L2_MEMORY_MMAP) |
| 186 | req.count = iBufCount; |
| 187 | |
| 188 | iRet = ioctl(iFd, VIDIOC_REQBUFS, &req); |
| 189 | if (iRet < 0) { |
| 190 | JPEG_ERROR_LOG("[%s:%d]: VIDIOC_REQBUFS failed\n", __func__, iRet); |
| 191 | return iRet; |
| 192 | } |
| 193 | |
| 194 | return iRet; |
| 195 | } |
| 196 | |
Jiyoung Shin | afd46e5 | 2012-04-17 18:01:11 -0700 | [diff] [blame] | 197 | int ExynosJpegBase::t_v4l2Qbuf(int iFd, struct BUF_INFO *pstBufInfo, struct BUFFER *pstBuf) |
| 198 | { |
| 199 | struct v4l2_buffer v4l2_buf; |
| 200 | struct v4l2_plane plane[JPEG_MAX_PLANE_CNT]; |
| 201 | int i; |
| 202 | int iRet = ERROR_NONE; |
| 203 | |
| 204 | memset(&v4l2_buf, 0, sizeof(struct v4l2_buffer)); |
| 205 | memset(plane, 0, (int)JPEG_MAX_PLANE_CNT * sizeof(struct v4l2_plane)); |
| 206 | |
| 207 | v4l2_buf.index = 0; |
| 208 | v4l2_buf.type = pstBufInfo->buf_type; |
| 209 | v4l2_buf.memory = pstBufInfo->memory; |
| 210 | v4l2_buf.field = V4L2_FIELD_ANY; |
| 211 | v4l2_buf.length = pstBufInfo->numOfPlanes; |
| 212 | v4l2_buf.m.planes = plane; |
| 213 | |
Sungjoong Kang | ed904e2 | 2012-07-20 22:31:51 +0900 | [diff] [blame] | 214 | if (pstBufInfo->memory == V4L2_MEMORY_DMABUF) { |
Jiyoung Shin | afd46e5 | 2012-04-17 18:01:11 -0700 | [diff] [blame] | 215 | for (i = 0; i < pstBufInfo->numOfPlanes; i++) { |
Sungjoong Kang | ed904e2 | 2012-07-20 22:31:51 +0900 | [diff] [blame] | 216 | v4l2_buf.m.planes[i].m.fd = (unsigned long)pstBuf->addr[i]; |
Jiyoung Shin | afd46e5 | 2012-04-17 18:01:11 -0700 | [diff] [blame] | 217 | v4l2_buf.m.planes[i].length = pstBuf->size[i]; |
| 218 | } |
| 219 | } |
| 220 | |
| 221 | iRet = ioctl(iFd, VIDIOC_QBUF, &v4l2_buf); |
| 222 | if (iRet < 0) { |
| 223 | JPEG_ERROR_LOG("[%s:%d] VIDIOC_QBUF failed\n", __func__, iRet); |
| 224 | pstBuf->numOfPlanes = 0; |
| 225 | return iRet; |
| 226 | } |
| 227 | |
| 228 | return iRet; |
| 229 | } |
| 230 | |
| 231 | int ExynosJpegBase::t_v4l2Dqbuf(int iFd, enum v4l2_buf_type eType, enum v4l2_memory eMemory, int iNumPlanes) |
| 232 | { |
| 233 | struct v4l2_buffer buf; |
| 234 | struct v4l2_plane planes[3]; |
| 235 | int iRet = ERROR_NONE; |
| 236 | |
| 237 | memset(&buf, 0, sizeof(struct v4l2_buffer)); |
| 238 | memset(planes, 0, sizeof(struct v4l2_plane)*3); |
| 239 | |
| 240 | buf.type = eType; |
| 241 | buf.memory = eMemory; |
| 242 | buf.length = iNumPlanes; |
| 243 | buf.m.planes = planes; |
| 244 | |
| 245 | iRet = ioctl(iFd, VIDIOC_DQBUF, &buf); |
| 246 | if (iRet < 0) { |
| 247 | JPEG_ERROR_LOG("[%s:%d] VIDIOC_DQBUF failed\n", __func__, iRet); |
| 248 | return iRet; |
| 249 | } |
| 250 | |
| 251 | #ifdef KERNEL_33_JPEG_API |
| 252 | if ((eType == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) && \ |
| 253 | (t_stJpegConfig.mode == MODE_ENCODE)) { |
| 254 | t_stJpegConfig.sizeJpeg = buf.m.planes[0].bytesused; |
| 255 | } |
| 256 | #endif |
| 257 | |
| 258 | return iRet; |
| 259 | } |
| 260 | |
| 261 | int ExynosJpegBase::t_v4l2StreamOn(int iFd, enum v4l2_buf_type eType) |
| 262 | { |
| 263 | int iRet = ERROR_NONE; |
| 264 | |
| 265 | iRet = ioctl(iFd, VIDIOC_STREAMON, &eType); |
| 266 | if (iRet < 0) { |
| 267 | JPEG_ERROR_LOG("[%s:%d] VIDIOC_STREAMON failed\n", __func__, iRet); |
| 268 | return iRet; |
| 269 | } |
| 270 | |
| 271 | return iRet; |
| 272 | } |
| 273 | |
| 274 | int ExynosJpegBase::t_v4l2StreamOff(int iFd, enum v4l2_buf_type eType) |
| 275 | { |
| 276 | int iRet = ERROR_NONE; |
| 277 | |
| 278 | iRet = ioctl(iFd, VIDIOC_STREAMOFF, &eType); |
| 279 | if (iRet < 0) { |
| 280 | JPEG_ERROR_LOG("[%s:%d] VIDIOC_STREAMOFF failed\n", __func__, iRet); |
| 281 | return iRet; |
| 282 | } |
| 283 | |
| 284 | return iRet; |
| 285 | } |
| 286 | |
| 287 | int ExynosJpegBase::t_v4l2SetCtrl(int iFd, int iCid, int iValue) |
| 288 | { |
| 289 | struct v4l2_control vc; |
| 290 | int iRet = ERROR_NONE; |
| 291 | |
| 292 | vc.id = iCid; |
| 293 | vc.value = iValue; |
| 294 | |
| 295 | iRet = ioctl(iFd, VIDIOC_S_CTRL, &vc); |
| 296 | if (iRet < 0) { |
| 297 | JPEG_ERROR_LOG("[%s] VIDIOC_S_CTRL failed : cid(%d), value(%d)\n", __func__, iCid, iValue); |
| 298 | return iRet; |
| 299 | } |
| 300 | |
| 301 | return iRet; |
| 302 | } |
| 303 | |
| 304 | int ExynosJpegBase::t_v4l2GetCtrl(int iFd, int iCid) |
| 305 | { |
| 306 | struct v4l2_control ctrl; |
| 307 | int iRet = ERROR_NONE; |
| 308 | |
| 309 | ctrl.id = iCid; |
| 310 | |
| 311 | iRet = ioctl(iFd, VIDIOC_G_CTRL, &ctrl); |
| 312 | if (iRet < 0) { |
| 313 | JPEG_ERROR_LOG("[%s] VIDIOC_G_CTRL failed : cid(%d)\n", __func__, ctrl.id); |
| 314 | return iRet; |
| 315 | } |
| 316 | |
| 317 | return ctrl.value; |
| 318 | } |
| 319 | |
| 320 | int ExynosJpegBase::create(enum MODE eMode) |
| 321 | { |
| 322 | if (t_bFlagCreate == true) { |
| 323 | return ERROR_JPEG_DEVICE_ALREADY_CREATE; |
| 324 | } |
| 325 | |
| 326 | int iRet = ERROR_NONE; |
| 327 | |
| 328 | switch (eMode) { |
| 329 | case MODE_ENCODE: |
| 330 | t_iJpegFd = open(JPEG_ENC_NODE, O_RDWR, 0); |
| 331 | break; |
| 332 | case MODE_DECODE: |
| 333 | t_iJpegFd = open(JPEG_DEC_NODE, O_RDWR, 0); |
| 334 | break; |
| 335 | default: |
| 336 | t_iJpegFd = -1; |
| 337 | return ERROR_INVALID_JPEG_MODE; |
| 338 | break; |
| 339 | } |
| 340 | |
| 341 | if (t_iJpegFd < 0) { |
| 342 | t_iJpegFd = -1; |
| 343 | JPEG_ERROR_LOG("[%s]: JPEG_NODE open failed\n", __func__); |
| 344 | return ERROR_CANNOT_OPEN_JPEG_DEVICE; |
| 345 | } |
| 346 | |
| 347 | if (t_iJpegFd <= 0) { |
| 348 | t_iJpegFd = -1; |
| 349 | JPEG_ERROR_LOG("ERR(%s):JPEG device was closed\n", __func__); |
| 350 | return ERROR_JPEG_DEVICE_ALREADY_CLOSED; |
| 351 | } |
| 352 | |
| 353 | iRet = t_v4l2Querycap(t_iJpegFd); |
| 354 | if (iRet < 0) { |
| 355 | JPEG_ERROR_LOG("[%s]: QUERYCAP failed\n", __func__); |
| 356 | close(t_iJpegFd); |
| 357 | return ERROR_CANNOT_OPEN_JPEG_DEVICE; |
| 358 | } |
| 359 | |
| 360 | memset(&t_stJpegConfig, 0, sizeof(struct CONFIG)); |
| 361 | memset(&t_stJpegInbuf, 0, sizeof(struct BUFFER)); |
| 362 | memset(&t_stJpegOutbuf, 0, sizeof(struct BUFFER)); |
| 363 | |
| 364 | t_stJpegConfig.mode = eMode; |
| 365 | |
| 366 | t_bFlagCreate = true; |
| 367 | t_bFlagCreateInBuf = false; |
| 368 | t_bFlagCreateOutBuf = false; |
| 369 | t_bFlagExcute = false; |
| 370 | |
| 371 | t_iPlaneNum = 0; |
| 372 | |
| 373 | return ERROR_NONE; |
| 374 | } |
| 375 | |
| 376 | int ExynosJpegBase::destroy(int iInBufs, int iOutBufs) |
| 377 | { |
| 378 | if (t_bFlagCreate == false) { |
| 379 | return ERROR_JPEG_DEVICE_ALREADY_DESTROY; |
| 380 | } |
| 381 | |
| 382 | if (t_iJpegFd > 0) { |
| 383 | struct BUF_INFO stBufInfo; |
| 384 | |
| 385 | if (t_bFlagExcute) { |
| 386 | t_v4l2StreamOff(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); |
| 387 | t_v4l2StreamOff(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); |
| 388 | } |
| 389 | |
| 390 | if (t_bFlagExcute) { |
| 391 | stBufInfo.numOfPlanes = iInBufs; |
| 392 | stBufInfo.memory = V4L2_MEMORY_MMAP; |
| 393 | |
| 394 | stBufInfo.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 395 | t_v4l2Reqbufs(t_iJpegFd, 0, &stBufInfo); |
| 396 | |
| 397 | stBufInfo.numOfPlanes = iOutBufs; |
| 398 | stBufInfo.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 399 | t_v4l2Reqbufs(t_iJpegFd, 0, &stBufInfo); |
| 400 | } |
| 401 | |
| 402 | close(t_iJpegFd); |
| 403 | } |
| 404 | |
| 405 | t_iJpegFd = -1; |
| 406 | t_bFlagCreate = false; |
| 407 | return ERROR_NONE; |
| 408 | } |
| 409 | |
| 410 | int ExynosJpegBase::setSize(int iW, int iH) |
| 411 | { |
| 412 | if (t_bFlagCreate == false) { |
| 413 | return ERROR_JPEG_DEVICE_NOT_CREATE_YET; |
| 414 | } |
| 415 | |
| 416 | if (iW < 0 || MAX_JPG_WIDTH < iW) { |
| 417 | return ERROR_INVALID_IMAGE_SIZE; |
| 418 | } |
| 419 | |
| 420 | if (iH < 0 || MAX_JPG_HEIGHT < iH) { |
| 421 | return ERROR_INVALID_IMAGE_SIZE; |
| 422 | } |
| 423 | |
| 424 | t_stJpegConfig.width = iW; |
| 425 | t_stJpegConfig.height = iH; |
| 426 | |
| 427 | return ERROR_NONE; |
| 428 | } |
| 429 | |
| 430 | int ExynosJpegBase::setJpegConfig(enum MODE eMode, void *pConfig) |
| 431 | { |
| 432 | if (t_bFlagCreate == false) { |
| 433 | return ERROR_JPEG_DEVICE_NOT_CREATE_YET; |
| 434 | } |
| 435 | |
| 436 | if (pConfig == NULL) { |
| 437 | return ERROR_JPEG_CONFIG_POINTER_NULL; |
| 438 | } |
| 439 | |
| 440 | memcpy(&t_stJpegConfig, pConfig, sizeof(struct CONFIG)); |
| 441 | |
| 442 | switch (eMode) { |
| 443 | case MODE_ENCODE: |
| 444 | switch (t_stJpegConfig.pix.enc_fmt.in_fmt) { |
| 445 | case V4L2_PIX_FMT_YUV420: |
Jiyoung Shin | afd46e5 | 2012-04-17 18:01:11 -0700 | [diff] [blame] | 446 | case V4L2_PIX_FMT_NV16: |
Jiyoung Shin | afd46e5 | 2012-04-17 18:01:11 -0700 | [diff] [blame] | 447 | case V4L2_PIX_FMT_YUYV: |
| 448 | case V4L2_PIX_FMT_RGB565X: |
| 449 | case V4L2_PIX_FMT_BGR32: |
| 450 | case V4L2_PIX_FMT_RGB32: |
| 451 | t_iPlaneNum = 1; |
| 452 | break; |
| 453 | default: |
| 454 | JPEG_ERROR_LOG("%s::Invalid input color format(%d) fail\n", __func__, t_stJpegConfig.pix.enc_fmt.in_fmt); |
| 455 | t_iPlaneNum = 0; |
| 456 | return ERROR_INVALID_COLOR_FORMAT; |
| 457 | } |
| 458 | break; |
| 459 | case MODE_DECODE: |
| 460 | switch (t_stJpegConfig.pix.dec_fmt.out_fmt) { |
| 461 | case V4L2_PIX_FMT_YUV420: |
Jiyoung Shin | afd46e5 | 2012-04-17 18:01:11 -0700 | [diff] [blame] | 462 | case V4L2_PIX_FMT_NV16: |
Jiyoung Shin | afd46e5 | 2012-04-17 18:01:11 -0700 | [diff] [blame] | 463 | case V4L2_PIX_FMT_YUYV: |
| 464 | case V4L2_PIX_FMT_RGB565X: |
| 465 | case V4L2_PIX_FMT_BGR32: |
| 466 | case V4L2_PIX_FMT_RGB32: |
| 467 | t_iPlaneNum = 1; |
| 468 | break; |
| 469 | default: |
| 470 | JPEG_ERROR_LOG("%s::Invalid input color format(%d) fail\n", __func__, t_stJpegConfig.pix.dec_fmt.out_fmt); |
| 471 | t_iPlaneNum = 0; |
| 472 | return ERROR_INVALID_COLOR_FORMAT; |
| 473 | } |
| 474 | break; |
| 475 | default: |
| 476 | t_iPlaneNum = 0; |
| 477 | return ERROR_INVALID_JPEG_MODE; |
| 478 | break; |
| 479 | } |
| 480 | |
| 481 | return ERROR_NONE; |
| 482 | } |
| 483 | |
| 484 | void *ExynosJpegBase::getJpegConfig(void) |
| 485 | { |
| 486 | if (t_bFlagCreate == false) { |
| 487 | return NULL; |
| 488 | } |
| 489 | |
| 490 | return &t_stJpegConfig; |
| 491 | } |
| 492 | |
Sungjoong Kang | ed904e2 | 2012-07-20 22:31:51 +0900 | [diff] [blame] | 493 | int ExynosJpegBase::getBuf(bool bCreateBuf, struct BUFFER *pstBuf, int *piBuf, int *iBufSize, int iSize, int iPlaneNum) |
Jiyoung Shin | afd46e5 | 2012-04-17 18:01:11 -0700 | [diff] [blame] | 494 | { |
| 495 | if (t_bFlagCreate == false) { |
| 496 | return ERROR_JPEG_DEVICE_NOT_CREATE_YET; |
| 497 | } |
| 498 | |
| 499 | if (bCreateBuf == false) { |
| 500 | return ERROR_BUF_NOT_SET_YET; |
| 501 | } |
| 502 | |
Sungjoong Kang | ed904e2 | 2012-07-20 22:31:51 +0900 | [diff] [blame] | 503 | if ((piBuf == NULL) || (iSize == 0)) { |
Jiyoung Shin | afd46e5 | 2012-04-17 18:01:11 -0700 | [diff] [blame] | 504 | return ERROR_BUFFR_IS_NULL; |
| 505 | } |
| 506 | |
| 507 | if (iSize < iPlaneNum) { |
| 508 | return ERROR_BUFFER_TOO_SMALL; |
| 509 | } |
| 510 | |
| 511 | for (int i=0;i<iPlaneNum;i++) { |
Sungjoong Kang | ed904e2 | 2012-07-20 22:31:51 +0900 | [diff] [blame] | 512 | piBuf[i] = pstBuf->addr[i]; |
Jiyoung Shin | afd46e5 | 2012-04-17 18:01:11 -0700 | [diff] [blame] | 513 | } |
| 514 | |
| 515 | for (int i=0;i<iPlaneNum;i++) { |
| 516 | iBufSize[i] = pstBuf->size[i]; |
| 517 | } |
| 518 | |
| 519 | return ERROR_NONE; |
| 520 | } |
| 521 | |
Sungjoong Kang | ed904e2 | 2012-07-20 22:31:51 +0900 | [diff] [blame] | 522 | int ExynosJpegBase::setBuf(struct BUFFER *pstBuf, int *piBuf, int *iSize, int iPlaneNum) |
Jiyoung Shin | afd46e5 | 2012-04-17 18:01:11 -0700 | [diff] [blame] | 523 | { |
| 524 | if (t_bFlagCreate == false) { |
| 525 | return ERROR_JPEG_DEVICE_NOT_CREATE_YET; |
| 526 | } |
| 527 | |
| 528 | if (iPlaneNum <= 0) { |
| 529 | return ERROR_BUFFER_TOO_SMALL; |
| 530 | } |
| 531 | |
| 532 | for(int i=0;i<iPlaneNum;i++) { |
Sungjoong Kang | ed904e2 | 2012-07-20 22:31:51 +0900 | [diff] [blame] | 533 | if (piBuf[i] == NULL) { |
Jiyoung Shin | afd46e5 | 2012-04-17 18:01:11 -0700 | [diff] [blame] | 534 | memset(pstBuf, 0, sizeof(struct BUFFER)); |
| 535 | return ERROR_BUFFR_IS_NULL; |
| 536 | } |
| 537 | if (iSize[i] <= 0) { |
| 538 | memset(pstBuf, 0, sizeof(struct BUFFER)); |
| 539 | return ERROR_BUFFER_TOO_SMALL; |
| 540 | } |
Sungjoong Kang | ed904e2 | 2012-07-20 22:31:51 +0900 | [diff] [blame] | 541 | pstBuf->addr[i] = piBuf[i]; |
Jiyoung Shin | afd46e5 | 2012-04-17 18:01:11 -0700 | [diff] [blame] | 542 | pstBuf->size[i] = iSize[i]; |
| 543 | } |
| 544 | |
| 545 | pstBuf->numOfPlanes = iPlaneNum; |
| 546 | |
| 547 | return ERROR_NONE; |
| 548 | } |
| 549 | |
| 550 | int ExynosJpegBase::setCache(int iValue) |
| 551 | { |
| 552 | if (t_bFlagCreate == false) { |
| 553 | return ERROR_JPEG_DEVICE_NOT_CREATE_YET; |
| 554 | } |
| 555 | |
| 556 | if (t_v4l2SetCtrl(t_iJpegFd, V4L2_CID_CACHEABLE, iValue)<0) { |
| 557 | JPEG_ERROR_LOG("%s::cache setting failed\n", __func__); |
| 558 | return ERROR_CANNOT_CHANGE_CACHE_SETTING; |
| 559 | } |
| 560 | |
| 561 | return ERROR_NONE; |
| 562 | } |
| 563 | |
| 564 | int ExynosJpegBase::setColorFormat(enum MODE eMode, int iV4l2ColorFormat) |
| 565 | { |
| 566 | if (t_bFlagCreate == false) { |
| 567 | return ERROR_JPEG_DEVICE_NOT_CREATE_YET; |
| 568 | } |
| 569 | |
| 570 | switch(iV4l2ColorFormat) { |
| 571 | case V4L2_PIX_FMT_YUYV: |
| 572 | case V4L2_PIX_FMT_YUV420: |
| 573 | case V4L2_PIX_FMT_NV16: |
| 574 | case V4L2_PIX_FMT_RGB565X: |
| 575 | case V4L2_PIX_FMT_BGR32: |
| 576 | case V4L2_PIX_FMT_RGB32: |
| 577 | switch (eMode) { |
| 578 | case MODE_ENCODE: |
| 579 | t_stJpegConfig.pix.enc_fmt.in_fmt = iV4l2ColorFormat; |
| 580 | break; |
| 581 | case MODE_DECODE: |
| 582 | t_stJpegConfig.pix.dec_fmt.out_fmt = iV4l2ColorFormat; |
| 583 | break; |
| 584 | default: |
| 585 | return ERROR_INVALID_JPEG_MODE; |
| 586 | break; |
| 587 | } |
| 588 | break; |
| 589 | default: |
| 590 | JPEG_ERROR_LOG("%s::Invalid input color format(%d) fail\n", __func__, iV4l2ColorFormat); |
| 591 | t_iPlaneNum = 0; |
| 592 | return ERROR_INVALID_COLOR_FORMAT; |
| 593 | break; |
| 594 | } |
| 595 | |
| 596 | switch (iV4l2ColorFormat) { |
| 597 | case V4L2_PIX_FMT_YUV420: |
Jiyoung Shin | afd46e5 | 2012-04-17 18:01:11 -0700 | [diff] [blame] | 598 | case V4L2_PIX_FMT_NV16: |
Jiyoung Shin | afd46e5 | 2012-04-17 18:01:11 -0700 | [diff] [blame] | 599 | case V4L2_PIX_FMT_YUYV: |
| 600 | case V4L2_PIX_FMT_RGB565X: |
| 601 | case V4L2_PIX_FMT_BGR32: |
| 602 | case V4L2_PIX_FMT_RGB32: |
| 603 | t_iPlaneNum = 1; |
| 604 | break; |
| 605 | default: |
| 606 | JPEG_ERROR_LOG("%s::Invalid input color format(%d) fail\n", __func__, iV4l2ColorFormat); |
| 607 | t_iPlaneNum = 0; |
| 608 | return ERROR_INVALID_COLOR_FORMAT; |
| 609 | } |
| 610 | |
| 611 | return ERROR_NONE; |
| 612 | } |
| 613 | |
| 614 | int ExynosJpegBase::setJpegFormat(enum MODE eMode, int iV4l2JpegFormat) |
| 615 | { |
| 616 | if (t_bFlagCreate == false) { |
| 617 | return ERROR_JPEG_DEVICE_NOT_CREATE_YET; |
| 618 | } |
| 619 | |
| 620 | switch(iV4l2JpegFormat) { |
| 621 | case V4L2_PIX_FMT_JPEG_444: |
| 622 | case V4L2_PIX_FMT_JPEG_422: |
| 623 | case V4L2_PIX_FMT_JPEG_420: |
| 624 | case V4L2_PIX_FMT_JPEG_GRAY: |
| 625 | switch (eMode) { |
| 626 | case MODE_ENCODE: |
| 627 | t_stJpegConfig.pix.enc_fmt.out_fmt = iV4l2JpegFormat; |
| 628 | break; |
| 629 | case MODE_DECODE: |
| 630 | t_stJpegConfig.pix.dec_fmt.in_fmt = iV4l2JpegFormat; |
| 631 | break; |
| 632 | default: |
| 633 | return ERROR_INVALID_JPEG_MODE; |
| 634 | break; |
| 635 | } |
| 636 | break; |
| 637 | default: |
| 638 | return ERROR_INVALID_JPEG_FORMAT; |
| 639 | break; |
| 640 | } |
| 641 | |
| 642 | return ERROR_NONE; |
| 643 | } |
| 644 | |
Jiyoung Shin | 1ae2a55 | 2012-06-01 16:11:04 -0700 | [diff] [blame] | 645 | int ExynosJpegBase::setColorBufSize(enum MODE eMode, int *piBufSize, int iSize) |
| 646 | { |
| 647 | int iFormat; |
| 648 | |
| 649 | switch (eMode) { |
| 650 | case MODE_ENCODE: |
| 651 | iFormat = t_stJpegConfig.pix.enc_fmt.in_fmt; |
| 652 | break; |
| 653 | case MODE_DECODE: |
| 654 | iFormat = t_stJpegConfig.pix.dec_fmt.out_fmt; |
| 655 | break; |
| 656 | default: |
| 657 | return ERROR_INVALID_JPEG_MODE; |
| 658 | break; |
| 659 | } |
| 660 | |
| 661 | return setColorBufSize(iFormat, piBufSize, iSize, t_stJpegConfig.width, t_stJpegConfig.height); |
| 662 | } |
| 663 | |
| 664 | int ExynosJpegBase::setColorBufSize(int iFormat, int *piBufSize, int iSize, int width, int height) |
| 665 | { |
| 666 | int pBufSize[3]; |
| 667 | |
| 668 | if(iSize>3) { |
| 669 | return ERROR_INVALID_IMAGE_SIZE; |
| 670 | } |
| 671 | |
| 672 | switch (iFormat) { |
| 673 | case V4L2_PIX_FMT_YUYV: |
| 674 | case V4L2_PIX_FMT_RGB565X: |
Sungjoong Kang | ed904e2 | 2012-07-20 22:31:51 +0900 | [diff] [blame] | 675 | case V4L2_PIX_FMT_NV16: |
Jiyoung Shin | 1ae2a55 | 2012-06-01 16:11:04 -0700 | [diff] [blame] | 676 | pBufSize[0] = width*height*2; |
| 677 | pBufSize[1] = 0; |
| 678 | pBufSize[2] = 0; |
| 679 | break; |
| 680 | case V4L2_PIX_FMT_RGB32: |
| 681 | case V4L2_PIX_FMT_BGR32: |
| 682 | pBufSize[0] = width*height*4; |
| 683 | pBufSize[1] = 0; |
| 684 | pBufSize[2] = 0; |
| 685 | break; |
Jiyoung Shin | 1ae2a55 | 2012-06-01 16:11:04 -0700 | [diff] [blame] | 686 | case V4L2_PIX_FMT_YUV420: |
Sungjoong Kang | ed904e2 | 2012-07-20 22:31:51 +0900 | [diff] [blame] | 687 | pBufSize[0] = (width*height*3)/2; |
| 688 | pBufSize[1] = 0; |
| 689 | pBufSize[2] = 0; |
Jiyoung Shin | 1ae2a55 | 2012-06-01 16:11:04 -0700 | [diff] [blame] | 690 | break; |
| 691 | default: |
| 692 | pBufSize[0] = width*height*4; |
| 693 | pBufSize[1] = width*height*4; |
| 694 | pBufSize[2] = width*height*4; |
| 695 | break; |
| 696 | } |
| 697 | |
| 698 | memcpy(piBufSize, pBufSize, iSize*sizeof(int)); |
| 699 | |
| 700 | return ERROR_NONE; |
| 701 | } |
| 702 | |
Jiyoung Shin | afd46e5 | 2012-04-17 18:01:11 -0700 | [diff] [blame] | 703 | int ExynosJpegBase::updateConfig(enum MODE eMode, int iInBufs, int iOutBufs, int iInBufPlanes, int iOutBufPlanes) |
| 704 | { |
| 705 | if (t_bFlagCreate == false) { |
| 706 | return ERROR_JPEG_DEVICE_NOT_CREATE_YET; |
| 707 | } |
| 708 | |
| 709 | int iRet = ERROR_NONE; |
| 710 | |
| 711 | if (eMode == MODE_ENCODE) { |
| 712 | iRet = t_v4l2SetJpegcomp(t_iJpegFd, t_stJpegConfig.enc_qual); |
| 713 | if (iRet < 0) { |
| 714 | JPEG_ERROR_LOG("[%s,%d]: S_JPEGCOMP failed\n", __func__,iRet); |
| 715 | return ERROR_INVALID_JPEG_CONFIG; |
| 716 | } |
| 717 | } |
| 718 | |
| 719 | t_stJpegConfig.numOfPlanes = iInBufPlanes; |
| 720 | t_stJpegConfig.mode = eMode; |
| 721 | |
| 722 | iRet = t_v4l2SetFmt(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, &t_stJpegConfig); |
| 723 | if (iRet < 0) { |
| 724 | JPEG_ERROR_LOG("[%s,%d]: jpeg input S_FMT failed\n", __func__,iRet); |
| 725 | return ERROR_INVALID_JPEG_CONFIG; |
| 726 | } |
| 727 | |
| 728 | struct BUF_INFO stBufInfo; |
| 729 | |
| 730 | stBufInfo.numOfPlanes = iInBufs; |
| 731 | stBufInfo.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
Sungjoong Kang | ed904e2 | 2012-07-20 22:31:51 +0900 | [diff] [blame] | 732 | stBufInfo.memory = V4L2_MEMORY_DMABUF; |
Jiyoung Shin | afd46e5 | 2012-04-17 18:01:11 -0700 | [diff] [blame] | 733 | |
| 734 | iRet = t_v4l2Reqbufs(t_iJpegFd, iInBufs, &stBufInfo); |
| 735 | if (iRet < 0) { |
| 736 | JPEG_ERROR_LOG("[%s:%d]: Input REQBUFS failed\n", __func__, iRet); |
| 737 | return ERROR_EXCUTE_FAIL; |
| 738 | } |
| 739 | |
| 740 | t_stJpegConfig.numOfPlanes = iOutBufPlanes; |
| 741 | iRet = t_v4l2SetFmt(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, &t_stJpegConfig); |
| 742 | if (iRet < 0) { |
| 743 | JPEG_ERROR_LOG("[%s,%d]: jpeg output S_FMT failed\n", __func__,iRet); |
| 744 | return ERROR_INVALID_JPEG_CONFIG; |
| 745 | } |
| 746 | |
| 747 | stBufInfo.numOfPlanes = iOutBufs; |
| 748 | stBufInfo.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 749 | |
| 750 | iRet = t_v4l2Reqbufs(t_iJpegFd, iOutBufs, &stBufInfo); |
| 751 | if (iRet < 0) { |
| 752 | JPEG_ERROR_LOG("[%s:%d]: Output REQBUFS failed\n", __func__, iRet); |
| 753 | return ERROR_REQBUF_FAIL; |
| 754 | } |
| 755 | |
| 756 | return ERROR_NONE; |
| 757 | } |
| 758 | |
| 759 | int ExynosJpegBase::execute(int iInBufPlanes, int iOutBufPlanes) |
| 760 | { |
| 761 | if (t_bFlagCreate == false) { |
| 762 | return ERROR_JPEG_DEVICE_NOT_CREATE_YET; |
| 763 | } |
| 764 | |
| 765 | struct BUF_INFO stBufInfo; |
| 766 | int iRet = ERROR_NONE; |
| 767 | |
| 768 | t_bFlagExcute = true; |
| 769 | |
| 770 | stBufInfo.numOfPlanes = iInBufPlanes; |
| 771 | stBufInfo.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; |
| 772 | |
Sungjoong Kang | ed904e2 | 2012-07-20 22:31:51 +0900 | [diff] [blame] | 773 | stBufInfo.memory = V4L2_MEMORY_DMABUF; |
Jiyoung Shin | afd46e5 | 2012-04-17 18:01:11 -0700 | [diff] [blame] | 774 | |
| 775 | iRet = t_v4l2Qbuf(t_iJpegFd, &stBufInfo, &t_stJpegInbuf); |
| 776 | if (iRet < 0) { |
| 777 | JPEG_ERROR_LOG("[%s:%d]: Input QBUF failed\n", __func__, iRet); |
| 778 | return ERROR_EXCUTE_FAIL; |
| 779 | } |
| 780 | |
| 781 | stBufInfo.numOfPlanes = iOutBufPlanes; |
| 782 | stBufInfo.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; |
| 783 | |
| 784 | iRet = t_v4l2Qbuf(t_iJpegFd, &stBufInfo, &t_stJpegOutbuf); |
| 785 | if (iRet < 0) { |
| 786 | JPEG_ERROR_LOG("[%s:%d]: Output QBUF failed\n", __func__, iRet); |
| 787 | return ERROR_EXCUTE_FAIL; |
| 788 | } |
| 789 | |
| 790 | iRet = t_v4l2StreamOn(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); |
| 791 | if (iRet < 0) { |
| 792 | JPEG_ERROR_LOG("[%s:%d]: input stream on failed\n", __func__, iRet); |
| 793 | return ERROR_EXCUTE_FAIL; |
| 794 | } |
| 795 | iRet = t_v4l2StreamOn(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); |
| 796 | if (iRet < 0) { |
| 797 | JPEG_ERROR_LOG("[%s:%d]: output stream on failed\n", __func__, iRet); |
| 798 | return ERROR_EXCUTE_FAIL; |
| 799 | } |
| 800 | |
| 801 | iRet = t_v4l2Dqbuf(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_MMAP, iInBufPlanes); |
| 802 | if (iRet < 0) { |
| 803 | JPEG_ERROR_LOG("[%s:%d]: Intput DQBUF failed\n", __func__, iRet); |
| 804 | return ERROR_EXCUTE_FAIL; |
| 805 | } |
| 806 | iRet = t_v4l2Dqbuf(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, V4L2_MEMORY_MMAP, iOutBufPlanes); |
| 807 | if (iRet < 0) { |
| 808 | JPEG_ERROR_LOG("[%s:%d]: Output DQBUF failed\n", __func__, iRet); |
| 809 | return ERROR_EXCUTE_FAIL; |
| 810 | } |
| 811 | |
| 812 | return ERROR_NONE; |
| 813 | } |
| 814 | |