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