1 /*
2  * Copyright Samsung Electronics Co.,LTD.
3  * Copyright (C) 2015 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 <linux/videodev2.h>
19 
20 #include <ExynosJpegApi.h>
21 
22 #include "hwjpeg-internal.h"
23 
setJpegConfig(void * pConfig)24 int ExynosJpegEncoder::setJpegConfig(void* pConfig)
25 {
26     ExynosJpegEncoder *that = reinterpret_cast<ExynosJpegEncoder *>(pConfig);
27 
28     if (!setColorFormat(that->m_v4l2Format))
29         return -1;
30 
31     if (!setJpegFormat(that->m_jpegFormat))
32         return -1;
33 
34     if (!setSize(that->m_nWidth, that->m_nHeight))
35         return -1;
36 
37     m_iInBufType = that->m_iInBufType;
38     m_iOutBufType = that->m_iOutBufType;
39 
40     return 0;
41 }
42 
getInBuf(int * piBuf,int * piInputSize,int iSize)43 int ExynosJpegEncoder::getInBuf(int *piBuf, int *piInputSize, int iSize)
44 {
45     if (iSize < 1) {
46         ALOGE("Invalid array size %d for getInBuf()", iSize);
47         return -1;
48     }
49 
50     size_t len_buffers[iSize];
51     if (!m_hwjpeg.GetImageBuffers(piBuf, len_buffers, static_cast<unsigned int>(iSize)))
52         return -1;
53 
54     for (int i = 0; i < iSize; i++)
55         piInputSize[i] = static_cast<int>(len_buffers[i]);
56 
57     return 0;
58 }
59 
getOutBuf(int * piBuf,int * piOutputSize)60 int ExynosJpegEncoder::getOutBuf(int *piBuf, int *piOutputSize)
61 {
62     size_t len;
63     if (!m_hwjpeg.GetJpegBuffer(piBuf, &len))
64         return -1;
65 
66     *piOutputSize = static_cast<int>(len);
67     return 0;
68 }
69 
setInBuf(int * piBuf,int * iSize)70 int ExynosJpegEncoder::setInBuf(int *piBuf, int *iSize)
71 {
72     size_t buflen[3];
73     unsigned int bufnum = 3;
74 
75     if (!EnsureFormatIsApplied())
76         return -1;
77 
78     if (!m_hwjpeg.GetImageBufferSizes(buflen, &bufnum))
79         return -1;
80 
81     for (unsigned int i = 0; i < bufnum; i++)
82         buflen[i] = static_cast<size_t>(iSize[i]);
83 
84     if (!m_hwjpeg.SetImageBuffer(piBuf, buflen, bufnum))
85         return -1;
86 
87     m_iInBufType = JPEG_BUF_TYPE_DMA_BUF;
88 
89     return 0;
90 }
91 
setOutBuf(int iBuf,int iSize,int offset)92 int ExynosJpegEncoder::setOutBuf(int iBuf, int iSize, int offset)
93 {
94     if (!m_hwjpeg.SetJpegBuffer(iBuf, static_cast<size_t>(iSize), offset))
95         return -1;
96 
97     m_iOutBufType = JPEG_BUF_TYPE_DMA_BUF;
98 
99     return 0;
100 }
101 
getInBuf(char ** pcBuf,int * piInputSize,int iSize)102 int ExynosJpegEncoder::getInBuf(char **pcBuf, int *piInputSize, int iSize)
103 {
104     if (iSize < 1) {
105         ALOGE("Invalid array size %d for getInBuf()", iSize);
106         return -1;
107     }
108 
109     size_t len_buffers[iSize];
110     if (!m_hwjpeg.GetImageBuffers(pcBuf, len_buffers, static_cast<unsigned int>(iSize)))
111         return -1;
112 
113     for (int i = 0; i < iSize; i++)
114         piInputSize[i] = static_cast<int>(len_buffers[i]);
115 
116     return 0;
117 }
118 
getOutBuf(char ** pcBuf,int * piOutputSize)119 int ExynosJpegEncoder::getOutBuf(char **pcBuf, int *piOutputSize)
120 {
121     size_t len;
122     if (!m_hwjpeg.GetJpegBuffer(pcBuf, &len))
123         return -1;
124 
125     *piOutputSize = static_cast<int>(len);
126     return 0;
127 }
128 
setInBuf(char ** pcBuf,int * iSize)129 int ExynosJpegEncoder::setInBuf(char **pcBuf, int *iSize)
130 {
131     size_t buflen[3];
132     unsigned int bufnum = 3;
133 
134     if (!EnsureFormatIsApplied())
135         return -1;
136 
137     if (!m_hwjpeg.GetImageBufferSizes(buflen, &bufnum))
138         return -1;
139 
140     for (unsigned int i = 0; i < bufnum; i++)
141         buflen[i] = static_cast<size_t>(iSize[i]);
142 
143     if (!m_hwjpeg.SetImageBuffer(pcBuf, buflen, bufnum))
144         return -1;
145 
146     m_iInBufType = JPEG_BUF_TYPE_USER_PTR;
147     return 0;
148 }
149 
setOutBuf(char * pcBuf,int iSize)150 int ExynosJpegEncoder::setOutBuf(char *pcBuf, int iSize)
151 {
152     if (!m_hwjpeg.SetJpegBuffer(pcBuf, static_cast<size_t>(iSize)))
153         return -1;
154 
155     m_iOutBufType = JPEG_BUF_TYPE_USER_PTR;
156 
157     return 0;
158 }
159 
setJpegFormat(int iV4l2JpegFormat)160 int ExynosJpegEncoder::setJpegFormat(int iV4l2JpegFormat)
161 {
162     if (m_jpegFormat == iV4l2JpegFormat)
163         return 0;
164 
165     unsigned int hfactor, vfactor;
166     switch (iV4l2JpegFormat) {
167         case V4L2_PIX_FMT_JPEG_444:
168             hfactor = 1;
169             vfactor = 1;
170             break;
171         case V4L2_PIX_FMT_JPEG_422:
172             hfactor = 2;
173             vfactor = 1;
174             break;
175         case V4L2_PIX_FMT_JPEG_420:
176             hfactor = 2;
177             vfactor = 2;
178             break;
179         case V4L2_PIX_FMT_JPEG_GRAY:
180             hfactor = 0;
181             vfactor = 0;
182             break;
183         case V4L2_PIX_FMT_JPEG_422V:
184             hfactor = 1;
185             vfactor = 2;
186             break;
187         case V4L2_PIX_FMT_JPEG_411:
188             hfactor = 4;
189             vfactor = 1;
190             break;
191         default:
192             ALOGE("Unknown JPEG format `%08Xh", iV4l2JpegFormat);
193             return -1;
194     }
195 
196     if (!m_hwjpeg.SetChromaSampFactor(hfactor, vfactor))
197         return -1;
198 
199     m_jpegFormat = iV4l2JpegFormat;
200 
201     return 0;
202 }
203 
setColorBufSize(int * piBufSize,int iSize)204 int ExynosJpegEncoder::setColorBufSize(int *piBufSize, int iSize)
205 {
206     size_t len[3];
207     unsigned int num = static_cast<unsigned int>(iSize);
208 
209     if (!m_hwjpeg.GetImageBufferSizes(len, &num))
210         return -1;
211 
212     for (unsigned int i = 0; i < num; i++)
213         piBufSize[i] = static_cast<int>(len[i]);
214 
215     return 0;
216 }
217 
__EnsureFormatIsApplied()218 bool ExynosJpegEncoder::__EnsureFormatIsApplied() {
219     if (TestStateEither(STATE_SIZE_CHANGED | STATE_PIXFMT_CHANGED) &&
220             !m_hwjpeg.SetImageFormat(m_v4l2Format, m_nWidth, m_nHeight))
221         return false;
222 
223     ClearState(STATE_SIZE_CHANGED | STATE_PIXFMT_CHANGED);
224     return true;
225 }
226 
setQuality(const unsigned char q_table[])227 int ExynosJpegEncoder::setQuality(const unsigned char q_table[]) {
228     return m_hwjpeg.SetQuality(q_table) ? 0 : -1;
229 }
230