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
47ExynosJpegBase::ExynosJpegBase()
48{
49}
50
51ExynosJpegBase::~ExynosJpegBase()
52{
53}
54
55int 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
69int 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
85int 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
134int 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
175int ExynosJpegBase::t_v4l2Reqbufs(int iFd, int iBufCount, struct BUF_INFO *pstBufInfo)
176{
177    struct v4l2_requestbuffers req;
178    int iRet = ERROR_NONE;
179
180    memset(&req, 0, sizeof(v4l2_requestbuffers));
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
197int 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
214    if (pstBufInfo->memory == V4L2_MEMORY_DMABUF) {
215        for (i = 0; i < pstBufInfo->numOfPlanes; i++) {
216            v4l2_buf.m.planes[i].m.fd = (unsigned long)pstBuf->addr[i];
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
231int 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
261int 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
274int 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
287int 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
304int 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
320int 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
376int 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
410int 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
430int 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:
446        case V4L2_PIX_FMT_NV16:
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:
462        case V4L2_PIX_FMT_NV16:
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
484void *ExynosJpegBase::getJpegConfig(void)
485{
486    if (t_bFlagCreate == false) {
487        return NULL;
488    }
489
490    return &t_stJpegConfig;
491}
492
493int ExynosJpegBase::getBuf(bool bCreateBuf, struct BUFFER *pstBuf, int *piBuf, int *iBufSize, int iSize, int iPlaneNum)
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
503     if ((piBuf == NULL) || (iSize == 0)) {
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++) {
512        piBuf[i] = pstBuf->addr[i];
513    }
514
515    for (int i=0;i<iPlaneNum;i++) {
516        iBufSize[i] = pstBuf->size[i];
517    }
518
519    return ERROR_NONE;
520}
521
522int ExynosJpegBase::setBuf(struct BUFFER *pstBuf, int *piBuf, int *iSize, int iPlaneNum)
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++) {
533        if (piBuf[i] == NULL) {
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        }
541        pstBuf->addr[i] = piBuf[i];
542        pstBuf->size[i] = iSize[i];
543    }
544
545    pstBuf->numOfPlanes = iPlaneNum;
546
547    return ERROR_NONE;
548}
549
550int 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
564int 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:
598    case V4L2_PIX_FMT_NV16:
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
614int 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
645int 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
664int 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:
675    case V4L2_PIX_FMT_NV16:
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;
686    case V4L2_PIX_FMT_YUV420:
687        pBufSize[0] = (width*height*3)/2;
688        pBufSize[1] = 0;
689        pBufSize[2] = 0;
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
703int 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;
732    stBufInfo.memory = V4L2_MEMORY_DMABUF;
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
759int 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
773    stBufInfo.memory = V4L2_MEMORY_DMABUF;
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
815