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