• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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