import exynos 7570 bsp
[GitHub/LineageOS/android_hardware_samsung_slsi_exynos.git] / libcamera / common_v2 / Pipes2 / ExynosCameraPipeGSC.cpp
1 /*
2 **
3 ** Copyright 2013, Samsung Electronics Co. LTD
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 /* #define LOG_NDEBUG 0 */
19 #define LOG_TAG "ExynosCameraPipeGSC"
20 #include <cutils/log.h>
21
22 #include "ExynosCameraPipeGSC.h"
23
24 namespace android {
25
26 ExynosCameraPipeGSC::~ExynosCameraPipeGSC()
27 {
28 this->destroy();
29 }
30
31 status_t ExynosCameraPipeGSC::create(__unused int32_t *sensorIds)
32 {
33 CSC_METHOD cscMethod = CSC_METHOD_HW;
34
35 m_csc = csc_init(cscMethod);
36 if (m_csc == NULL) {
37 CLOGE("ERR(%s):csc_init() fail", __FUNCTION__);
38 return INVALID_OPERATION;
39 }
40
41 csc_set_hw_property(m_csc, m_property, m_gscNum);
42
43 m_mainThread = ExynosCameraThreadFactory::createThread(this, &ExynosCameraPipeGSC::m_mainThreadFunc, "GSCThread");
44
45 m_inputFrameQ = new frame_queue_t(m_mainThread);
46
47 CLOGI("INFO(%s[%d]):create() is succeed (%d)", __FUNCTION__, __LINE__, getPipeId());
48
49 return NO_ERROR;
50 }
51
52 status_t ExynosCameraPipeGSC::destroy(void)
53 {
54 if (m_csc != NULL)
55 csc_deinit(m_csc);
56 m_csc = NULL;
57
58 if (m_inputFrameQ != NULL) {
59 m_inputFrameQ->release();
60 delete m_inputFrameQ;
61 m_inputFrameQ = NULL;
62 }
63
64 CLOGI("INFO(%s[%d]):destroy() is succeed (%d)", __FUNCTION__, __LINE__, getPipeId());
65
66 return NO_ERROR;
67 }
68
69 status_t ExynosCameraPipeGSC::start(void)
70 {
71 CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__);
72
73 m_flagTryStop = false;
74
75 return NO_ERROR;
76 }
77
78 status_t ExynosCameraPipeGSC::stop(void)
79 {
80 CLOGD("DEBUG(%s[%d])", __FUNCTION__, __LINE__);
81 int ret = 0;
82
83 m_flagTryStop = true;
84
85 m_mainThread->requestExitAndWait();
86
87 CLOGD("DEBUG(%s[%d]): thead exited", __FUNCTION__, __LINE__);
88
89 m_inputFrameQ->release();
90
91 m_flagTryStop = false;
92
93 return NO_ERROR;
94 }
95
96 status_t ExynosCameraPipeGSC::startThread(void)
97 {
98 CLOGV("DEBUG(%s[%d])", __FUNCTION__, __LINE__);
99
100 if (m_outputFrameQ == NULL) {
101 CLOGE("ERR(%s):outputFrameQ is NULL, cannot start", __FUNCTION__);
102 return INVALID_OPERATION;
103 }
104
105 m_mainThread->run();
106
107 CLOGI("INFO(%s[%d]):startThread is succeed (%d)", __FUNCTION__, __LINE__, getPipeId());
108
109 return NO_ERROR;
110 }
111
112 status_t ExynosCameraPipeGSC::m_run(void)
113 {
114 ExynosCameraFrame *newFrame = NULL;
115 ExynosCameraBuffer srcBuffer;
116 ExynosCameraBuffer dstBuffer;
117 ExynosRect srcRect;
118 ExynosRect dstRect;
119 ExynosCameraFrameEntity *entity = NULL;
120
121 int ret = 0;
122 int rotation = 0;
123 int flipHorizontal = 0;
124 int flipVertical = 0;
125
126 ret = m_inputFrameQ->waitAndPopProcessQ(&newFrame);
127 if (ret < 0) {
128 /* TODO: We need to make timeout duration depends on FPS */
129 if (ret == TIMED_OUT) {
130 CLOGW("WARN(%s):wait timeout", __FUNCTION__);
131 } else {
132 CLOGE("ERR(%s):wait and pop fail, ret(%d)", __FUNCTION__, ret);
133 /* TODO: doing exception handling */
134 }
135 return ret;
136 }
137
138 if (newFrame == NULL) {
139 CLOGE("ERR(%s):new frame is NULL", __FUNCTION__);
140 return NO_ERROR;
141 }
142
143 entity = newFrame->searchEntityByPipeId(getPipeId());
144 if (entity == NULL || entity->getSrcBufState() == ENTITY_BUFFER_STATE_ERROR) {
145 CLOGE("ERR(%s[%d]):frame(%d) entityState(ENTITY_BUFFER_STATE_ERROR), skip msc", __FUNCTION__, __LINE__, newFrame->getFrameCount());
146 goto func_exit;
147 }
148
149 rotation = newFrame->getRotation(getPipeId());
150 CLOGV("INFO(%s[%d]): getPipeId(%d), rotation(%d)", __FUNCTION__, __LINE__, getPipeId(), rotation);
151
152 #ifdef PERFRAME_CONTROL_FOR_FLIP
153 flipHorizontal = newFrame->getFlipHorizontal(getPipeId());
154 flipVertical = newFrame->getFlipVertical(getPipeId());
155 #else
156 flipHorizontal = m_parameters->getFlipHorizontal();
157 flipVertical = m_parameters->getFlipVertical();
158 #endif
159
160 ret = newFrame->getSrcRect(getPipeId(), &srcRect);
161 ret = newFrame->getDstRect(getPipeId(), &dstRect);
162
163 switch (srcRect.colorFormat) {
164 case V4L2_PIX_FMT_NV21:
165 srcRect.fullH = ALIGN_UP(srcRect.fullH, 2);
166 break;
167 default:
168 srcRect.fullH = ALIGN_UP(srcRect.fullH, GSCALER_IMG_ALIGN);
169 break;
170 }
171
172 csc_set_src_format(m_csc,
173 ALIGN_UP(srcRect.fullW, GSCALER_IMG_ALIGN),
174 srcRect.fullH,
175 srcRect.x, srcRect.y, srcRect.w, srcRect.h,
176 V4L2_PIX_2_HAL_PIXEL_FORMAT(srcRect.colorFormat),
177 0);
178
179 csc_set_dst_format(m_csc,
180 dstRect.fullW, dstRect.fullH,
181 dstRect.x, dstRect.y, dstRect.fullW, dstRect.fullH,
182 V4L2_PIX_2_HAL_PIXEL_FORMAT(dstRect.colorFormat),
183 0);
184
185 ret = newFrame->getSrcBuffer(getPipeId(), &srcBuffer);
186 if (ret < 0) {
187 CLOGE("ERR(%s[%d]):frame get src buffer fail, ret(%d)", __FUNCTION__, __LINE__, ret);
188 /* TODO: doing exception handling */
189 return OK;
190 }
191
192 ret = newFrame->getDstBuffer(getPipeId(), &dstBuffer);
193 if (ret < 0) {
194 CLOGE("ERR(%s[%d]):frame get dst buffer fail, ret(%d)", __FUNCTION__, __LINE__, ret);
195 /* TODO: doing exception handling */
196 return OK;
197 }
198
199 csc_set_src_buffer(m_csc,
200 (void **)srcBuffer.fd, CSC_MEMORY_TYPE);
201
202 csc_set_dst_buffer(m_csc,
203 (void **)dstBuffer.fd, CSC_MEMORY_TYPE);
204
205 if (csc_convert_with_rotation(m_csc, rotation, flipHorizontal, flipVertical) != 0)
206 CLOGE("ERR(%s):csc_convert() fail", __FUNCTION__);
207
208 CLOGV("DEBUG(%s[%d]):Rotation(%d), flip horizontal(%d), vertical(%d)",
209 __FUNCTION__, __LINE__, rotation, flipHorizontal, flipVertical);
210
211 CLOGV("DEBUG(%s[%d]):CSC(%d) converting done", __FUNCTION__, __LINE__, m_gscNum);
212
213 ret = newFrame->setEntityState(getPipeId(), ENTITY_STATE_FRAME_DONE);
214 if (ret < 0) {
215 CLOGE("ERR(%s[%d]):set entity state fail, ret(%d)", __FUNCTION__, __LINE__, ret);
216 /* TODO: doing exception handling */
217 return OK;
218 }
219
220 m_outputFrameQ->pushProcessQ(&newFrame);
221
222 return NO_ERROR;
223
224 func_exit:
225
226 ret = newFrame->setEntityState(getPipeId(), ENTITY_STATE_FRAME_DONE);
227 if (ret < 0) {
228 CLOGE("ERR(%s[%d]):set entity state fail, ret(%d)", __FUNCTION__, __LINE__, ret);
229 /* TODO: doing exception handling */
230 return OK;
231 }
232
233 m_outputFrameQ->pushProcessQ(&newFrame);
234 return NO_ERROR;
235 }
236
237 bool ExynosCameraPipeGSC::m_mainThreadFunc(void)
238 {
239 int ret = 0;
240
241 ret = m_run();
242 if (ret < 0) {
243 if (ret != TIMED_OUT)
244 CLOGE("ERR(%s):m_putBuffer fail", __FUNCTION__);
245 }
246
247 return m_checkThreadLoop();
248 }
249
250 void ExynosCameraPipeGSC::m_init(int32_t *nodeNums)
251 {
252 if (nodeNums == NULL)
253 m_gscNum = -1;
254 else
255 m_gscNum = nodeNums[0];
256
257 m_csc = NULL;
258 m_property = (nodeNums == NULL) ? CSC_HW_PROPERTY_DEFAULT : CSC_HW_PROPERTY_FIXED_NODE;
259 }
260
261 }; /* namespace android */