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 "hwjpeg-internal.h"
19 #include "LibScalerForJpeg.h"
20
21 #define SCALER_DEV_NODE "/dev/video50"
22
getBufTypeString(unsigned int buftype)23 static const char *getBufTypeString(unsigned int buftype)
24 {
25 if (buftype == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
26 return "destination";
27 if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
28 return "source";
29 return "unknown";
30 }
31
RunStream(int srcBuf[SCALER_MAX_PLANES],int __unused srcLen[SCALER_MAX_PLANES],int dstBuf,size_t __unused dstLen)32 bool LibScalerForJpeg::RunStream(int srcBuf[SCALER_MAX_PLANES], int __unused srcLen[SCALER_MAX_PLANES], int dstBuf, size_t __unused dstLen)
33 {
34 if (!mSrcImage.begin(V4L2_MEMORY_DMABUF) || !mDstImage.begin(V4L2_MEMORY_DMABUF))
35 return false;
36
37 return queue(srcBuf, dstBuf);
38 }
39
RunStream(char * srcBuf[SCALER_MAX_PLANES],int __unused srcLen[SCALER_MAX_PLANES],int dstBuf,size_t __unused dstLen)40 bool LibScalerForJpeg::RunStream(char *srcBuf[SCALER_MAX_PLANES], int __unused srcLen[SCALER_MAX_PLANES], int dstBuf, size_t __unused dstLen)
41 {
42 if (!mSrcImage.begin(V4L2_MEMORY_USERPTR) || !mDstImage.begin(V4L2_MEMORY_DMABUF))
43 return false;
44
45 return queue(srcBuf, dstBuf);
46 }
47
set(unsigned int width,unsigned int height,unsigned int format)48 bool LibScalerForJpeg::Image::set(unsigned int width, unsigned int height, unsigned int format)
49 {
50 if (same(width, height, format))
51 return true;
52
53 if (memoryType != 0) {
54 if (!mDevice.requestBuffers(bufferType, memoryType, 0))
55 return false;
56 }
57
58 if (!mDevice.setFormat(bufferType, format, width, height, planeLen))
59 return false;
60
61 memoryType = 0; // new reqbufs is required.
62
63 return true;
64 }
65
begin(unsigned int memtype)66 bool LibScalerForJpeg::Image::begin(unsigned int memtype)
67 {
68 if (memoryType != memtype) {
69 if (memoryType != 0) {
70 if (!mDevice.requestBuffers(bufferType, memoryType, 0))
71 return false;
72 }
73
74 if (!mDevice.requestBuffers(bufferType, memtype, 1))
75 return false;
76
77 if (!mDevice.streamOn(bufferType))
78 return false;
79
80 memoryType = memtype;
81 }
82
83 return true;
84 }
85
cancelBuffer()86 bool LibScalerForJpeg::Image::cancelBuffer()
87 {
88 if (!mDevice.streamOff(bufferType))
89 return false;
90
91 if (!mDevice.streamOn(bufferType))
92 return false;
93
94 return true;
95 }
96
Device()97 LibScalerForJpeg::Device::Device()
98 {
99 mFd = ::open(SCALER_DEV_NODE, O_RDWR);
100 if (mFd < 0)
101 ALOGERR("failed to open %s", SCALER_DEV_NODE);
102 }
103
~Device()104 LibScalerForJpeg::Device::~Device()
105 {
106 if (mFd >= 0)
107 ::close(mFd);
108 }
109
requestBuffers(unsigned int buftype,unsigned int memtype,unsigned int count)110 bool LibScalerForJpeg::Device::requestBuffers(unsigned int buftype, unsigned int memtype, unsigned int count)
111 {
112 // count==0 means this port should be reconfigured and it is successful under streaming is finished.
113 if (!count)
114 streamOff(buftype);
115
116 v4l2_requestbuffers reqbufs{};
117
118 reqbufs.type = buftype;
119 reqbufs.memory = memtype;
120 reqbufs.count = count;
121
122 if (ioctl(mFd, VIDIOC_REQBUFS, &reqbufs) < 0) {
123 ALOGERR("failed REQBUFS(%s, mem=%d, count=%d)", getBufTypeString(buftype), memtype, count);
124 return false;
125 }
126
127 return true;
128 }
129
setFormat(unsigned int buftype,unsigned int format,unsigned int width,unsigned int height,unsigned int planelen[SCALER_MAX_PLANES])130 bool LibScalerForJpeg::Device::setFormat(unsigned int buftype, unsigned int format, unsigned int width, unsigned int height, unsigned int planelen[SCALER_MAX_PLANES])
131 {
132 v4l2_format fmt{};
133
134 fmt.type = buftype;
135 fmt.fmt.pix_mp.pixelformat = format;
136 fmt.fmt.pix_mp.width = width;
137 fmt.fmt.pix_mp.height = height;
138
139 if (ioctl(mFd, VIDIOC_S_FMT, &fmt) < 0) {
140 ALOGERR("failed S_FMT(%s, fmt=h'%x, %ux%u)", getBufTypeString(buftype), format, width, height);
141 return false;
142 }
143
144 for (uint32_t i = 0; i < fmt.fmt.pix_mp.num_planes ; i++) {
145 planelen[i] = fmt.fmt.pix_mp.plane_fmt[i].sizeimage;
146 }
147
148 return true;
149 }
150
streamOn(unsigned int buftype)151 bool LibScalerForJpeg::Device::streamOn(unsigned int buftype)
152 {
153 if (ioctl(mFd, VIDIOC_STREAMON, &buftype) < 0) {
154 ALOGERR("failed STREAMON for %s", getBufTypeString(buftype));
155 return false;
156 }
157
158 return true;
159 }
160
streamOff(unsigned int buftype)161 bool LibScalerForJpeg::Device::streamOff(unsigned int buftype)
162 {
163 if (ioctl(mFd, VIDIOC_STREAMOFF, &buftype) < 0) {
164 ALOGERR("failed STREAMOFF for %s", getBufTypeString(buftype));
165 return false;
166 }
167
168 return true;
169 }
170
queueBuffer(unsigned int buftype,std::function<void (v4l2_buffer &)> bufferFiller)171 bool LibScalerForJpeg::Device::queueBuffer(unsigned int buftype, std::function<void(v4l2_buffer &)> bufferFiller)
172 {
173 v4l2_buffer buffer{};
174 v4l2_plane plane[SCALER_MAX_PLANES];
175
176 memset(&plane, 0, sizeof(plane));
177
178 buffer.type = buftype;
179 buffer.m.planes = plane;
180
181 bufferFiller(buffer);
182
183 return ioctl(mFd, VIDIOC_QBUF, &buffer) >= 0;
184 }
185
queueBuffer(unsigned int buftype,int buf[SCALER_MAX_PLANES],unsigned int len[SCALER_MAX_PLANES])186 bool LibScalerForJpeg::Device::queueBuffer(unsigned int buftype, int buf[SCALER_MAX_PLANES], unsigned int len[SCALER_MAX_PLANES])
187 {
188 if (!queueBuffer(buftype, [buf, len] (v4l2_buffer &buffer) {
189 buffer.memory = V4L2_MEMORY_DMABUF;
190 buffer.length = SCALER_MAX_PLANES;
191 for (unsigned int i = 0; i < SCALER_MAX_PLANES; i++) {
192 buffer.m.planes[i].m.fd = buf[i];
193 buffer.m.planes[i].length = len[i];
194 } })) {
195 ALOGERR("failed QBUF(%s, fd[]=%d %d, len[0]=%d %d)", getBufTypeString(buftype), buf[0], buf[1], len[0], len[1]);
196 return false;
197 }
198
199 return true;
200 }
201
queueBuffer(unsigned int buftype,char * buf[SCALER_MAX_PLANES],unsigned int len[SCALER_MAX_PLANES])202 bool LibScalerForJpeg::Device::queueBuffer(unsigned int buftype, char *buf[SCALER_MAX_PLANES], unsigned int len[SCALER_MAX_PLANES])
203 {
204 if (!queueBuffer(buftype, [buf, len] (v4l2_buffer &buffer) {
205 buffer.memory = V4L2_MEMORY_USERPTR;
206 buffer.length = SCALER_MAX_PLANES;
207 for (unsigned int i = 0; i < SCALER_MAX_PLANES; i++) {
208 buffer.m.planes[i].m.userptr = reinterpret_cast<unsigned long>(buf[i]);
209 buffer.m.planes[i].length = len[i];
210 } })) {
211 ALOGERR("failed QBUF(%s, ptr[]=%p %p, len[0]=%d %d)", getBufTypeString(buftype), buf[0], buf[1], len[0], len[1]);
212 return false;
213 }
214
215 return true;
216 }
217
queueBuffer(unsigned int buftype,int buf,unsigned int len[SCALER_MAX_PLANES])218 bool LibScalerForJpeg::Device::queueBuffer(unsigned int buftype, int buf, unsigned int len[SCALER_MAX_PLANES])
219 {
220 if (!queueBuffer(buftype, [buf, len] (v4l2_buffer &buffer)
221 {
222 buffer.memory = V4L2_MEMORY_DMABUF;
223 buffer.length = 1;
224 buffer.m.planes[0].m.fd = buf;
225 buffer.m.planes[0].length = len[0];
226 })) {
227 ALOGERR("failed QBUF(%s, fd=%d, len=%d", getBufTypeString(buftype), buf, len[0]);
228 return false;
229 }
230
231 return true;
232 }
233
dequeueBuffer(unsigned int buftype,unsigned int memtype)234 bool LibScalerForJpeg::Device::dequeueBuffer(unsigned int buftype, unsigned int memtype)
235 {
236 v4l2_buffer buffer{};
237 v4l2_plane plane[SCALER_MAX_PLANES];
238
239 memset(&plane, 0, sizeof(plane));
240
241 buffer.type = buftype;
242 buffer.memory = memtype;
243 buffer.length = SCALER_MAX_PLANES;
244
245 buffer.m.planes = plane;
246
247 if (ioctl(mFd, VIDIOC_DQBUF, &buffer) < 0 ) {
248 ALOGERR("failed DQBUF(%s)", getBufTypeString(buftype));
249 return false;
250 }
251
252 return true;
253 }
254