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 <linux/videodev2.h>
19 #include <linux/v4l2-controls.h>
20 
21 #include <exynos-hwjpeg.h>
22 #include "hwjpeg-internal.h"
23 
CHWJpegV4L2Compressor()24 CHWJpegV4L2Compressor::CHWJpegV4L2Compressor(): CHWJpegCompressor("/dev/video12")
25 {
26     memset(&m_v4l2Format, 0, sizeof(m_v4l2Format));
27     memset(&m_v4l2SrcBuffer, 0, sizeof(m_v4l2SrcBuffer));
28     memset(&m_v4l2DstBuffer, 0, sizeof(m_v4l2DstBuffer));
29     memset(&m_v4l2SrcPlanes, 0, sizeof(m_v4l2SrcPlanes));
30     memset(&m_v4l2DstPlanes, 0, sizeof(m_v4l2DstPlanes));
31     memset(&m_v4l2Controls, 0, sizeof(m_v4l2Controls));
32 
33     m_v4l2Format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
34     // default image format is initialized by 8x8 RGB24 in order for TryFormat()
35     // to seccess at anytime.
36     // 8x8 : the smallest image size to compress
37     // RGB24(or YUV444): The image format with the smallest memory footprint
38     //                   without any image size constraints.
39     m_v4l2Format.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_RGB24;
40     m_v4l2Format.fmt.pix_mp.width = TO_IMAGE_SIZE(16, 0);
41     m_v4l2Format.fmt.pix_mp.height = TO_IMAGE_SIZE(16, 0);
42     m_v4l2SrcBuffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
43     m_v4l2DstBuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
44 
45     m_v4l2SrcBuffer.m.planes = m_v4l2SrcPlanes;
46     m_v4l2DstBuffer.m.planes = m_v4l2DstPlanes;
47 
48     m_uiControlsToSet = 0;
49 
50     m_bEnableHWFC = false;
51 
52     v4l2_capability cap;
53     memset(&cap, 0, sizeof(cap));
54     if (ioctl(GetDeviceFD(), VIDIOC_QUERYCAP, &cap) < 0) {
55         ALOGERR("Failed to query capability of /dev/video12");
56     } else if (!!(cap.capabilities & V4L2_CAP_DEVICE_CAPS)) {
57         SetDeviceCapabilities(cap.device_caps);
58     }
59 
60     // Initialy declare that s_fmt is required.
61     SetFlag(HWJPEG_FLAG_PIX_FMT);
62 
63     ALOGD("CHWJpegV4L2Compressor Created: %p, FD %d", this, GetDeviceFD());
64 }
65 
~CHWJpegV4L2Compressor()66 CHWJpegV4L2Compressor::~CHWJpegV4L2Compressor()
67 {
68     StopStreaming();
69 
70     ALOGD("CHWJpegV4L2Compressor Destroyed: %p, FD %d", this, GetDeviceFD());
71 }
72 
SetChromaSampFactor(unsigned int horizontal,unsigned int vertical)73 bool CHWJpegV4L2Compressor::SetChromaSampFactor(
74                     unsigned int horizontal, unsigned int vertical)
75 {
76     __s32 value;
77     switch ((horizontal << 4) | vertical) {
78         case 0x00: value = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY; break;
79         case 0x11: value = V4L2_JPEG_CHROMA_SUBSAMPLING_444; break;
80         case 0x21: value = V4L2_JPEG_CHROMA_SUBSAMPLING_422; break;
81         case 0x22: value = V4L2_JPEG_CHROMA_SUBSAMPLING_420; break;
82         case 0x41: value = V4L2_JPEG_CHROMA_SUBSAMPLING_411; break;
83         case 0x12:
84         default:
85            ALOGE("Unsupported chroma subsampling %ux%u", horizontal, vertical);
86            return false;
87     }
88 
89     m_v4l2Controls[HWJPEG_CTRL_CHROMFACTOR].id = V4L2_CID_JPEG_CHROMA_SUBSAMPLING;
90     m_v4l2Controls[HWJPEG_CTRL_CHROMFACTOR].value = value;
91     m_uiControlsToSet |= 1 << HWJPEG_CTRL_CHROMFACTOR;
92 
93     return true;
94 }
95 
SetQuality(unsigned int quality_factor,unsigned int quality_factor2)96 bool CHWJpegV4L2Compressor::SetQuality(
97         unsigned int quality_factor, unsigned int quality_factor2)
98 {
99     if (quality_factor > 100) {
100         ALOGE("Unsupported quality factor %u", quality_factor);
101         return false;
102     }
103 
104     if (quality_factor2 > 100) {
105         ALOGE("Unsupported quality factor %u for the secondary image",
106                  quality_factor2);
107         return false;
108     }
109 
110     if (quality_factor > 0) {
111         m_v4l2Controls[HWJPEG_CTRL_QFACTOR].id = V4L2_CID_JPEG_COMPRESSION_QUALITY;
112         m_v4l2Controls[HWJPEG_CTRL_QFACTOR].value = static_cast<__s32>(quality_factor);
113         m_uiControlsToSet |= 1 << HWJPEG_CTRL_QFACTOR;
114     }
115 
116     if (quality_factor2 > 0) {
117         m_v4l2Controls[HWJPEG_CTRL_QFACTOR2].id = V4L2_CID_JPEG_SEC_COMP_QUALITY;
118         m_v4l2Controls[HWJPEG_CTRL_QFACTOR2].value = static_cast<__s32>(quality_factor2);
119         m_uiControlsToSet |= 1 << HWJPEG_CTRL_QFACTOR2;
120     }
121 
122     return true;
123 }
124 
SetQuality(const unsigned char qtable[])125 bool CHWJpegV4L2Compressor::SetQuality(const unsigned char qtable[])
126 {
127     v4l2_ext_controls ctrls;
128     v4l2_ext_control ctrl;
129 
130     memset(&ctrls, 0, sizeof(ctrls));
131     memset(&ctrl, 0, sizeof(ctrl));
132 
133     ctrls.ctrl_class = V4L2_CTRL_CLASS_JPEG;
134     ctrls.controls = &ctrl;
135     ctrls.count = 1;
136 
137     ctrl.id = V4L2_CID_JPEG_QTABLES2;
138     ctrl.size = 128; /* two quantization tables */
139     ctrl.p_u8 = const_cast<unsigned char *>(qtable);
140 
141     if (ioctl(GetDeviceFD(), VIDIOC_S_EXT_CTRLS, &ctrls) < 0) {
142         ALOGERR("Failed to configure %u controls", ctrls.count);
143         return false;
144     }
145 
146     return true;
147 }
148 
SetImageFormat(unsigned int v4l2_fmt,unsigned int width,unsigned int height,unsigned int width2,unsigned int height2)149 bool CHWJpegV4L2Compressor::SetImageFormat(unsigned int v4l2_fmt,
150                                            unsigned int width, unsigned int height,
151                                            unsigned int width2, unsigned int height2)
152 {
153     if ((m_v4l2Format.fmt.pix_mp.pixelformat == v4l2_fmt) &&
154         (m_v4l2Format.fmt.pix_mp.width == TO_IMAGE_SIZE(width, width2)) &&
155         (m_v4l2Format.fmt.pix_mp.height == TO_IMAGE_SIZE(height, height2)))
156         return true;
157 
158     m_v4l2Format.fmt.pix_mp.pixelformat = v4l2_fmt;
159     m_v4l2Format.fmt.pix_mp.width = TO_IMAGE_SIZE(width, width2);
160     m_v4l2Format.fmt.pix_mp.height = TO_IMAGE_SIZE(height, height2);
161 
162     SetFlag(HWJPEG_FLAG_PIX_FMT);
163 
164     return TryFormat();
165 }
166 
GetImageBufferSizes(size_t buf_sizes[],unsigned int * num_buffers)167 bool CHWJpegV4L2Compressor::GetImageBufferSizes(size_t buf_sizes[], unsigned int *num_buffers)
168 {
169     if (buf_sizes) {
170         for (unsigned int i = 0; i < m_v4l2Format.fmt.pix_mp.num_planes; i++)
171             buf_sizes[i] = m_v4l2Format.fmt.pix_mp.plane_fmt[i].sizeimage;
172     }
173 
174     if (num_buffers) {
175         if (*num_buffers < m_v4l2Format.fmt.pix_mp.num_planes) {
176             ALOGE("The size array length %u is smaller than the number of required buffers %u",
177                     *num_buffers, m_v4l2Format.fmt.pix_mp.num_planes);
178             return false;
179         }
180 
181         *num_buffers = m_v4l2Format.fmt.pix_mp.num_planes;
182     }
183 
184     return true;
185 }
186 
SetImageBuffer(char * buffers[],size_t len_buffers[],unsigned int num_buffers)187 bool CHWJpegV4L2Compressor::SetImageBuffer(char *buffers[], size_t len_buffers[],
188                                            unsigned int num_buffers)
189 {
190     if (num_buffers < m_v4l2Format.fmt.pix_mp.num_planes) {
191         ALOGE("The number of buffers %u is smaller than the required %u",
192                 num_buffers,m_v4l2Format.fmt.pix_mp.num_planes);
193         return false;
194     }
195 
196     for (unsigned int i = 0; i < m_v4l2Format.fmt.pix_mp.num_planes; i++) {
197         m_v4l2SrcPlanes[i].m.userptr = reinterpret_cast<unsigned long>(buffers[i]);
198         if (len_buffers[i] < m_v4l2Format.fmt.pix_mp.plane_fmt[i].sizeimage) {
199             ALOGE("The size of the buffer[%u] %zu is smaller than required %u",
200                     i, len_buffers[i], m_v4l2Format.fmt.pix_mp.plane_fmt[i].sizeimage);
201             return false;
202         }
203         m_v4l2SrcPlanes[i].bytesused = m_v4l2Format.fmt.pix_mp.plane_fmt[i].sizeimage;
204         m_v4l2SrcPlanes[i].length = len_buffers[i];
205     }
206 
207     m_v4l2SrcBuffer.memory = V4L2_MEMORY_USERPTR;
208 
209     SetFlag(HWJPEG_FLAG_SRC_BUFFER);
210 
211     return true;
212 }
213 
SetImageBuffer(int buffers[],size_t len_buffers[],unsigned int num_buffers)214 bool CHWJpegV4L2Compressor::SetImageBuffer(int buffers[], size_t len_buffers[],
215                                            unsigned int num_buffers)
216 {
217     if (num_buffers < m_v4l2Format.fmt.pix_mp.num_planes) {
218         ALOGE("The number of buffers %u is smaller than the required %u",
219                 num_buffers,m_v4l2Format.fmt.pix_mp.num_planes);
220         return false;
221     }
222 
223     for (unsigned int i = 0; i < m_v4l2Format.fmt.pix_mp.num_planes; i++) {
224         m_v4l2SrcPlanes[i].m.fd = buffers[i];
225         if (len_buffers[i] < m_v4l2Format.fmt.pix_mp.plane_fmt[i].sizeimage) {
226             ALOGE("The size of the buffer[%u] %zu is smaller than required %u",
227                     i, len_buffers[i], m_v4l2Format.fmt.pix_mp.plane_fmt[i].sizeimage);
228             return false;
229         }
230         m_v4l2SrcPlanes[i].bytesused = m_v4l2Format.fmt.pix_mp.plane_fmt[i].sizeimage;
231         m_v4l2SrcPlanes[i].length = len_buffers[i];
232     }
233 
234     m_v4l2SrcBuffer.memory = V4L2_MEMORY_DMABUF;
235 
236     SetFlag(HWJPEG_FLAG_SRC_BUFFER);
237 
238     return true;
239 }
240 
SetImageBuffer2(char * buffers[],size_t len_buffers[],unsigned int num_buffers)241  bool CHWJpegV4L2Compressor::SetImageBuffer2(char *buffers[], size_t len_buffers[],
242                                                     unsigned int num_buffers)
243 {
244     if (!IsDeviceCapability(V4L2_CAP_EXYNOS_JPEG_B2B_COMPRESSION)) {
245         ALOGE("Back-to-back compression is not suppored by H/W");
246         return false;
247     }
248 
249     if (num_buffers < m_v4l2Format.fmt.pix_mp.num_planes) {
250         ALOGE("The number of buffers %u is smaller than the required %u (secondary)",
251                 num_buffers,m_v4l2Format.fmt.pix_mp.num_planes);
252         return false;
253     }
254 
255     unsigned int ibuf = 0;
256     for (unsigned int i = m_v4l2Format.fmt.pix_mp.num_planes;
257                                 i < (m_v4l2Format.fmt.pix_mp.num_planes * 2); i++, ibuf++) {
258         m_v4l2SrcPlanes[i].m.userptr = reinterpret_cast<unsigned long>(buffers[ibuf]);
259         // size check is ignored for the secondary image buffers
260         m_v4l2SrcPlanes[i].bytesused = len_buffers[ibuf];
261         m_v4l2SrcPlanes[i].length = len_buffers[ibuf];
262     }
263 
264     // memory type is only configured by the primary image configuration
265     SetFlag(HWJPEG_FLAG_SRC_BUFFER2);
266 
267     return true;
268 }
269 
SetImageBuffer2(int buffers[],size_t len_buffers[],unsigned int num_buffers)270  bool CHWJpegV4L2Compressor::SetImageBuffer2(int buffers[], size_t len_buffers[],
271                                                     unsigned int num_buffers)
272 {
273     if (!IsDeviceCapability(V4L2_CAP_EXYNOS_JPEG_B2B_COMPRESSION)) {
274         ALOGE("Back-to-back compression is not suppored by H/W");
275         return false;
276     }
277 
278     if (num_buffers < m_v4l2Format.fmt.pix_mp.num_planes) {
279         ALOGE("The number of buffers %u is smaller than the required %u (secondary)",
280                 num_buffers,m_v4l2Format.fmt.pix_mp.num_planes);
281         return false;
282     }
283 
284     unsigned int ibuf = 0;
285     for (unsigned int i = m_v4l2Format.fmt.pix_mp.num_planes;
286                                 i < (m_v4l2Format.fmt.pix_mp.num_planes * 2); i++, ibuf++) {
287         m_v4l2SrcPlanes[i].m.fd = buffers[ibuf];
288         // size check is ignored for the secondary image buffers
289         m_v4l2SrcPlanes[i].bytesused = len_buffers[ibuf];
290         m_v4l2SrcPlanes[i].length = len_buffers[ibuf];
291     }
292 
293     // memory type is only configured by the primary image configuration
294 
295     SetFlag(HWJPEG_FLAG_SRC_BUFFER2);
296 
297     return true;
298 }
299 
SetJpegBuffer(char * buffer,size_t len_buffer)300 bool CHWJpegV4L2Compressor::SetJpegBuffer(char *buffer, size_t len_buffer)
301 {
302     m_v4l2DstPlanes[0].m.userptr = reinterpret_cast<unsigned long>(buffer);
303     m_v4l2DstPlanes[0].length = len_buffer;
304     m_v4l2DstBuffer.memory = V4L2_MEMORY_USERPTR;
305     SetFlag(HWJPEG_FLAG_DST_BUFFER);
306     return true;
307 }
308 
SetJpegBuffer(int buffer,size_t len_buffer,int offset)309 bool CHWJpegV4L2Compressor::SetJpegBuffer(int buffer, size_t len_buffer, int offset)
310 {
311     m_v4l2DstPlanes[0].m.fd = buffer;
312     m_v4l2DstPlanes[0].length = len_buffer;
313     m_v4l2DstPlanes[0].data_offset = offset;
314     m_v4l2DstBuffer.memory = V4L2_MEMORY_DMABUF;
315     SetFlag(HWJPEG_FLAG_DST_BUFFER);
316     return true;
317 }
318 
SetJpegBuffer2(char * buffer,size_t len_buffer)319 bool CHWJpegV4L2Compressor::SetJpegBuffer2(char *buffer, size_t len_buffer)
320 {
321     if (!IsDeviceCapability(V4L2_CAP_EXYNOS_JPEG_B2B_COMPRESSION)) {
322         ALOGE("Back-to-back compression is not suppored by H/W");
323         return false;
324     }
325 
326     m_v4l2DstPlanes[1].m.userptr = reinterpret_cast<unsigned long>(buffer);
327     m_v4l2DstPlanes[1].length = len_buffer;
328     SetFlag(HWJPEG_FLAG_DST_BUFFER2);
329     return true;
330 }
331 
SetJpegBuffer2(int buffer,size_t len_buffer)332 bool CHWJpegV4L2Compressor::SetJpegBuffer2(int buffer, size_t len_buffer)
333 {
334     if (!IsDeviceCapability(V4L2_CAP_EXYNOS_JPEG_B2B_COMPRESSION)) {
335         ALOGE("Back-to-back compression is not suppored by H/W");
336         return false;
337     }
338 
339     m_v4l2DstPlanes[1].m.fd = buffer;
340     m_v4l2DstPlanes[1].length = len_buffer;
341     SetFlag(HWJPEG_FLAG_DST_BUFFER2);
342     return true;
343 }
344 
StopStreaming()345 bool CHWJpegV4L2Compressor::StopStreaming()
346 {
347     if (TestFlag(HWJPEG_FLAG_STREAMING)) {
348         if (!StreamOff())
349             return false;
350         ClearFlag(HWJPEG_FLAG_STREAMING);
351     }
352 
353     // Stream off dequeues all queued buffers
354     ClearFlag(HWJPEG_FLAG_QBUF_OUT | HWJPEG_FLAG_QBUF_CAP);
355 
356     // It is OK to skip DQBUF because STREAMOFF dequeues all queued buffers
357     if (TestFlag(HWJPEG_FLAG_REQBUFS)) {
358         if (!ReqBufs(0))
359             return false;
360         ClearFlag(HWJPEG_FLAG_REQBUFS);
361     }
362 
363     return true;
364 }
365 
Compress(size_t * secondary_stream_size,bool block_mode)366 ssize_t CHWJpegV4L2Compressor::Compress(size_t *secondary_stream_size, bool block_mode)
367 {
368     if (TestFlag(HWJPEG_FLAG_PIX_FMT)) {
369         if (!StopStreaming() || !SetFormat())
370             return -1;
371     }
372 
373     if (!TestFlag(HWJPEG_FLAG_SRC_BUFFER)) {
374         ALOGE("Source image buffer is not specified");
375         return -1;
376     }
377 
378     if (!TestFlag(HWJPEG_FLAG_DST_BUFFER)) {
379         ALOGE("Output JPEG stream buffer is not specified");
380         return -1;
381     }
382 
383     m_v4l2SrcBuffer.length = m_v4l2Format.fmt.pix_mp.num_planes;
384     m_v4l2DstBuffer.length = 1;
385     if (IsB2BCompression()) {
386         if (!TestFlag(HWJPEG_FLAG_SRC_BUFFER2 | HWJPEG_FLAG_DST_BUFFER2)) {
387             ALOGE("Either of source or destination buffer of secondary image is not specified (%#x)",
388                   GetFlags());
389             return -1;
390         }
391         // The SMFC Driver expects the number of buffers to be doubled
392         // if back-to-back compression is enabled
393         m_v4l2SrcBuffer.length *= 2;
394         m_v4l2DstBuffer.length = 2;
395     }
396 
397     if (!!(GetAuxFlags() & EXYNOS_HWJPEG_AUXOPT_SRC_NOCACHECLEAN))
398         m_v4l2SrcBuffer.flags |= V4L2_BUF_FLAG_NO_CACHE_CLEAN;
399     if (!!(GetAuxFlags() & EXYNOS_HWJPEG_AUXOPT_DST_NOCACHECLEAN))
400         m_v4l2DstBuffer.flags |= V4L2_BUF_FLAG_NO_CACHE_CLEAN;
401 
402     if (!ReqBufs() || !StreamOn() || !UpdateControls() || !QBuf())
403         return -1;
404 
405     return block_mode ? DQBuf(secondary_stream_size) : 0;
406 }
407 
TryFormat()408 bool CHWJpegV4L2Compressor::TryFormat()
409 {
410     if (ioctl(GetDeviceFD(), VIDIOC_TRY_FMT, &m_v4l2Format) < 0) {
411         ALOGERR("Failed to TRY_FMT for compression");
412         return false;
413     }
414 
415     return true;
416 }
417 
SetFormat()418 bool CHWJpegV4L2Compressor::SetFormat()
419 {
420     if (ioctl(GetDeviceFD(), VIDIOC_S_FMT, &m_v4l2Format) < 0) {
421         ALOGERR("Failed to S_FMT for image to compress");
422         return false;
423     }
424 
425     v4l2_format v4l2JpegFormat;
426     memset(&v4l2JpegFormat, 0, sizeof(v4l2JpegFormat));
427 
428     v4l2JpegFormat.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
429     v4l2JpegFormat.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_JPEG;
430     v4l2JpegFormat.fmt.pix_mp.width = m_v4l2Format.fmt.pix_mp.width;
431     v4l2JpegFormat.fmt.pix_mp.height = m_v4l2Format.fmt.pix_mp.height;
432 
433     if (ioctl(GetDeviceFD(), VIDIOC_S_FMT, &v4l2JpegFormat) < 0) {
434         ALOGERR("Failed to S_FMT for JPEG stream to capture");
435         return false;
436     }
437 
438     ClearFlag(HWJPEG_FLAG_PIX_FMT);
439 
440     return true;
441 }
442 
UpdateControls()443 bool CHWJpegV4L2Compressor::UpdateControls()
444 {
445     bool enable_hwfc = !!(GetAuxFlags() & EXYNOS_HWJPEG_AUXOPT_ENABLE_HWFC);
446 
447     if ((m_uiControlsToSet == 0) && (enable_hwfc == m_bEnableHWFC))
448         return true;
449 
450     v4l2_ext_controls ctrls;
451     v4l2_ext_control ctrl[HWJPEG_CTRL_NUM];
452 
453     memset(&ctrls, 0, sizeof(ctrls));
454     memset(&ctrl, 0, sizeof(ctrl));
455 
456     ctrls.ctrl_class = V4L2_CTRL_CLASS_JPEG;
457     ctrls.controls = ctrl;
458     unsigned int idx_ctrl = 0;
459     while (m_uiControlsToSet != 0) {
460         if (m_uiControlsToSet & (1 << idx_ctrl)) {
461             ctrl[ctrls.count].id = m_v4l2Controls[idx_ctrl].id;
462             ctrl[ctrls.count].value = m_v4l2Controls[idx_ctrl].value;
463             m_uiControlsToSet &= ~(1 << idx_ctrl);
464             ctrls.count++;
465         }
466         idx_ctrl++;
467     }
468 
469     if (m_bEnableHWFC != enable_hwfc) {
470         m_bEnableHWFC = enable_hwfc;
471         ctrl[ctrls.count].id = V4L2_CID_JPEG_HWFC_ENABLE;
472         ctrl[ctrls.count].value = m_bEnableHWFC ? 1 : 0;
473         ctrls.count++;
474     }
475 
476     if (ioctl(GetDeviceFD(), VIDIOC_S_EXT_CTRLS, &ctrls) < 0) {
477         ALOGERR("Failed to configure %u controls", ctrls.count);
478         return false;
479     }
480 
481     return true;
482 }
483 
ReqBufs(unsigned int count)484 bool CHWJpegV4L2Compressor::ReqBufs(unsigned int count)
485 {
486     // - count > 0 && REQBUFS is set: Just return true
487     // - count > 0 && REQBUFS is unset: REQBUFS(count) is required
488     // - count == 0 && REQBUFS is set: REQBUFS(0) is required
489     // - count == 0 && REQBUFS is unset: Just return true;
490     if ((count > 0) == TestFlag(HWJPEG_FLAG_REQBUFS))
491         return true;
492 
493     v4l2_requestbuffers reqbufs;
494 
495     memset(&reqbufs, 0, sizeof(reqbufs));
496     reqbufs.count = count;
497     reqbufs.memory = m_v4l2SrcBuffer.memory;
498     reqbufs.type = m_v4l2SrcBuffer.type;
499     if (ioctl(GetDeviceFD(), VIDIOC_REQBUFS, &reqbufs) < 0) {
500         ALOGERR("Failed to REQBUFS(%u) of the source image", count);
501         return false;
502     }
503 
504     memset(&reqbufs, 0, sizeof(reqbufs));
505     reqbufs.count = count;
506     reqbufs.memory = m_v4l2DstBuffer.memory;
507     reqbufs.type = m_v4l2DstBuffer.type;
508     if (ioctl(GetDeviceFD(), VIDIOC_REQBUFS, &reqbufs) < 0) {
509         ALOGERR("Failed to REQBUFS(%u) of the JPEG stream", count);
510         // rolling back the reqbufs for the source image
511         reqbufs.memory = m_v4l2SrcBuffer.memory;
512         reqbufs.type = m_v4l2SrcBuffer.type;
513         reqbufs.count = 0;
514         ioctl(GetDeviceFD(), VIDIOC_REQBUFS, &reqbufs); // don't care if it fails
515         return false;
516     }
517 
518     if (count > 0)
519         SetFlag(HWJPEG_FLAG_REQBUFS);
520     else
521         ClearFlag(HWJPEG_FLAG_REQBUFS);
522 
523     return true;
524 }
525 
StreamOn()526 bool CHWJpegV4L2Compressor::StreamOn()
527 {
528     if (TestFlag(HWJPEG_FLAG_STREAMING))
529         return true;
530 
531     if (!TestFlag(HWJPEG_FLAG_REQBUFS)) {
532         ALOGE("Trying to STREAMON before REQBUFS");
533         return false;
534     }
535 
536     if (ioctl(GetDeviceFD(), VIDIOC_STREAMON, &m_v4l2SrcBuffer.type) < 0) {
537         ALOGERR("Failed to STREAMON for the source image");
538         return false;
539     }
540 
541     if (ioctl(GetDeviceFD(), VIDIOC_STREAMON, &m_v4l2DstBuffer.type) < 0) {
542         ALOGERR("Failed to STREAMON for the JPEG stream");
543         ioctl(GetDeviceFD(), VIDIOC_STREAMOFF, &m_v4l2SrcBuffer.type);
544         return false;
545     }
546 
547     SetFlag(HWJPEG_FLAG_STREAMING);
548 
549     return true;
550 }
551 
StreamOff()552 bool CHWJpegV4L2Compressor::StreamOff()
553 {
554     if (!TestFlag(HWJPEG_FLAG_STREAMING))
555         return true;
556 
557     // error during stream off do not need further handling because of nothing to do
558     if (ioctl(GetDeviceFD(), VIDIOC_STREAMOFF, &m_v4l2SrcBuffer.type) < 0)
559         ALOGERR("Failed to STREAMOFF for the source image");
560 
561     if (ioctl(GetDeviceFD(), VIDIOC_STREAMOFF, &m_v4l2DstBuffer.type) < 0)
562         ALOGERR("Failed to STREAMOFF for the JPEG stream");
563 
564     ClearFlag(HWJPEG_FLAG_STREAMING);
565 
566     return true;
567 }
568 
QBuf()569 bool CHWJpegV4L2Compressor::QBuf()
570 {
571     if (!TestFlag(HWJPEG_FLAG_REQBUFS)) {
572         ALOGE("QBuf is not permitted until REQBUFS is performed");
573         return false;
574     }
575 
576     if (ioctl(GetDeviceFD(), VIDIOC_QBUF, &m_v4l2SrcBuffer) < 0) {
577         ALOGERR("QBuf of the source buffers is failed (B2B %s)",
578                 IsB2BCompression() ? "enabled" : "disabled");
579         return false;
580     }
581 
582     if (ioctl(GetDeviceFD(), VIDIOC_QBUF, &m_v4l2DstBuffer) < 0) {
583         ALOGERR("QBuf of the JPEG buffers is failed (B2B %s)",
584                 IsB2BCompression() ? "enabled" : "disabled");
585         // Reqbufs(0) is the only way to cancel the previous queued buffer
586         StopStreaming();
587         return false;
588     }
589 
590     SetFlag(HWJPEG_FLAG_QBUF_OUT | HWJPEG_FLAG_QBUF_CAP);
591 
592     return true;
593 }
594 
DQBuf(size_t * secondary_stream_size)595 ssize_t CHWJpegV4L2Compressor::DQBuf(size_t *secondary_stream_size)
596 {
597     bool failed = false;
598     v4l2_buffer buffer_src, buffer_dst;
599     v4l2_plane planes_src[6], planes_dst[2];
600 
601     ALOG_ASSERT(TestFlag(HWJPEG_FLAG_QBUF_OUT) == TestFlag(HWJPEG_FLAG_QBUF_CAP));
602 
603     memset(&buffer_src, 0, sizeof(buffer_src));
604     memset(&buffer_dst, 0, sizeof(buffer_dst));
605     memset(&planes_src, 0, sizeof(planes_src));
606     memset(&planes_dst, 0, sizeof(planes_dst));
607 
608     buffer_src.type = m_v4l2SrcBuffer.type;
609     buffer_src.memory = m_v4l2SrcBuffer.memory;
610     buffer_src.length = m_v4l2SrcBuffer.length;
611     buffer_src.m.planes = planes_src;
612 
613     buffer_dst.type = m_v4l2DstBuffer.type;
614     buffer_dst.memory = m_v4l2DstBuffer.memory;
615     buffer_dst.length = m_v4l2DstBuffer.length;
616     buffer_dst.m.planes = planes_dst;
617 
618     if (TestFlag(HWJPEG_FLAG_QBUF_OUT) && (ioctl(GetDeviceFD(), VIDIOC_DQBUF, &buffer_src) < 0)) {
619         ALOGERR("Failed to DQBUF of the image buffer");
620         failed = true;
621     }
622 
623     if (TestFlag(HWJPEG_FLAG_QBUF_CAP) && (ioctl(GetDeviceFD(), VIDIOC_DQBUF, &buffer_dst) < 0)) {
624         ALOGERR("Failed to DQBUF of the JPEG stream buffer");
625         failed = true;
626     }
627 
628     ClearFlag(HWJPEG_FLAG_QBUF_OUT | HWJPEG_FLAG_QBUF_CAP);
629 
630     if (failed)
631         return -1;
632 
633     if (!!((buffer_src.flags | buffer_dst.flags) & V4L2_BUF_FLAG_ERROR)) {
634         ALOGE("Error occurred during compression");
635         return -1;
636     }
637 
638     // We don't need to check the length of secondary stream
639     // because it will be zero if the secondary image is not processed.
640     SetStreamSize(buffer_dst.m.planes[0].bytesused, buffer_dst.m.planes[1].bytesused);
641 
642     // The driver stores the delay in usec. of JPEG compression by H/W
643     // to v4l2_buffer.reserved2.
644     m_uiHWDelay = buffer_dst.reserved2;
645 
646     return GetStreamSize(secondary_stream_size);
647 }
648 
WaitForCompression(size_t * secondary_stream_size)649 ssize_t CHWJpegV4L2Compressor::WaitForCompression(size_t *secondary_stream_size)
650 {
651     return DQBuf(secondary_stream_size);
652 }
653 
GetImageBuffers(int buffers[],size_t len_buffers[],unsigned int num_buffers)654 bool CHWJpegV4L2Compressor::GetImageBuffers(int buffers[], size_t len_buffers[],
655                                             unsigned int num_buffers)
656 {
657     if (m_v4l2SrcBuffer.memory != V4L2_MEMORY_DMABUF) {
658         ALOGE("Current image buffer type is not dma-buf but attempted to retrieve dma-buf buffers");
659         return false;
660     }
661 
662     if (num_buffers < m_v4l2Format.fmt.pix_mp.num_planes) {
663         ALOGE("Number of planes are %u but attemts to retrieve %u buffers",
664                 m_v4l2Format.fmt.pix_mp.num_planes, num_buffers);
665         return false;
666     }
667 
668     for (unsigned int i = 0; i < m_v4l2Format.fmt.pix_mp.num_planes; i++) {
669         buffers[i] = m_v4l2SrcBuffer.m.planes[i].m.fd;
670         len_buffers[i] = m_v4l2SrcBuffer.m.planes[i].length;
671     }
672 
673     return true;
674 }
675 
GetImageBuffers(char * buffers[],size_t len_buffers[],unsigned int num_buffers)676 bool CHWJpegV4L2Compressor::GetImageBuffers(char *buffers[], size_t len_buffers[],
677                                             unsigned int num_buffers)
678 {
679     if (m_v4l2SrcBuffer.memory != V4L2_MEMORY_USERPTR) {
680         ALOGE("Current image buffer type is not userptr but attempted to retrieve userptr buffers");
681         return false;
682     }
683 
684     if (num_buffers < m_v4l2Format.fmt.pix_mp.num_planes) {
685         ALOGE("Number of planes are %u but attemts to retrieve %u buffers",
686                 m_v4l2Format.fmt.pix_mp.num_planes, num_buffers);
687         return false;
688     }
689 
690     for (unsigned int i = 0; i < m_v4l2Format.fmt.pix_mp.num_planes; i++) {
691         buffers[i] = reinterpret_cast<char *>(m_v4l2SrcBuffer.m.planes[i].m.userptr);
692         len_buffers[i] = m_v4l2SrcBuffer.m.planes[i].length;
693     }
694 
695     return true;
696 }
697 
GetJpegBuffer(int * buffer,size_t * len_buffer)698 bool CHWJpegV4L2Compressor::GetJpegBuffer(int *buffer, size_t *len_buffer)
699 {
700     if (m_v4l2DstBuffer.memory != V4L2_MEMORY_DMABUF) {
701         ALOGE("Current jpeg buffer type is not dma-buf but attempted to retrieve dma-buf buffer");
702         return false;
703     }
704 
705     *buffer = m_v4l2DstBuffer.m.planes[0].m.fd;
706     *len_buffer = m_v4l2DstBuffer.m.planes[0].length;
707 
708     return true;
709 }
710 
GetJpegBuffer(char ** buffer,size_t * len_buffer)711 bool CHWJpegV4L2Compressor::GetJpegBuffer(char **buffer, size_t *len_buffer)
712 {
713     if (m_v4l2DstBuffer.memory != V4L2_MEMORY_USERPTR) {
714         ALOGE("Current jpeg buffer type is not userptr but attempted to retrieve userptr buffer");
715         return false;
716     }
717 
718     *buffer = reinterpret_cast<char *>(m_v4l2DstBuffer.m.planes[0].m.userptr);
719     *len_buffer = m_v4l2DstBuffer.m.planes[0].length;
720 
721     return true;
722 }
723 
Release()724 void CHWJpegV4L2Compressor::Release()
725 {
726     StopStreaming();
727 }
728 
729 /******************************************************************************/
730 /********* D E C O M P R E S S I O N   S U P P O R T **************************/
731 /******************************************************************************/
732 
CHWJpegV4L2Decompressor()733 CHWJpegV4L2Decompressor::CHWJpegV4L2Decompressor() : CHWJpegDecompressor("/dev/video12")
734 {
735     m_v4l2Format.type = 0; // inidication of uninitialized state
736 
737     memset(&m_v4l2DstBuffer, 0, sizeof(m_v4l2DstBuffer));
738     m_v4l2DstBuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
739 
740     if (Okay()) {
741         v4l2_capability cap;
742         memset(&cap, 0, sizeof(cap));
743         if (ioctl(GetDeviceFD(), VIDIOC_QUERYCAP, &cap) < 0) {
744             ALOGERR("Failed to query capability of /dev/video12");
745         } else if (!!(cap.capabilities & V4L2_CAP_DEVICE_CAPS)) {
746             SetDeviceCapabilities(cap.device_caps);
747         }
748     }
749 }
750 
~CHWJpegV4L2Decompressor()751 CHWJpegV4L2Decompressor::~CHWJpegV4L2Decompressor()
752 {
753     CancelCapture();
754 }
755 
PrepareCapture()756 bool CHWJpegV4L2Decompressor::PrepareCapture()
757 {
758     if (m_v4l2DstBuffer.length < m_v4l2Format.fmt.pix.sizeimage) {
759         ALOGE("The size of the buffer %u is smaller than required %u",
760               m_v4l2DstBuffer.length, m_v4l2Format.fmt.pix.sizeimage);
761         return false;
762     }
763 
764     if (TestFlag(HWJPEG_FLAG_CAPTURE_READY))
765         return true;
766 
767     v4l2_requestbuffers reqbufs;
768 
769     memset(&reqbufs, 0, sizeof(reqbufs));
770     reqbufs.count = 1;
771     reqbufs.memory = m_v4l2DstBuffer.memory;
772     reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
773 
774     if (ioctl(GetDeviceFD(), VIDIOC_REQBUFS, &reqbufs) < 0) {
775         ALOGERR("Failed to REQBUFS for the decompressed image");
776         return false;
777     }
778 
779     if (ioctl(GetDeviceFD(), VIDIOC_STREAMON, &reqbufs.type) < 0) {
780         ALOGERR("Failed to STREAMON for the decompressed image");
781         reqbufs.count = 0;
782         ioctl(GetDeviceFD(), VIDIOC_REQBUFS, &reqbufs);
783         return false;
784     }
785 
786     SetFlag(HWJPEG_FLAG_CAPTURE_READY);
787 
788     return true;
789 }
790 
CancelCapture()791 void CHWJpegV4L2Decompressor::CancelCapture()
792 {
793     if (!TestFlag(HWJPEG_FLAG_CAPTURE_READY))
794         return;
795 
796     v4l2_requestbuffers reqbufs;
797 
798     memset(&reqbufs, 0, sizeof(reqbufs));
799     reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
800     reqbufs.memory = m_v4l2DstBuffer.memory;
801 
802     ioctl(GetDeviceFD(), VIDIOC_STREAMOFF, &reqbufs.type);
803     ioctl(GetDeviceFD(), VIDIOC_REQBUFS, &reqbufs);
804 
805     ClearFlag(HWJPEG_FLAG_CAPTURE_READY);
806 }
807 
SetImageFormat(unsigned int v4l2_fmt,unsigned int width,unsigned int height)808 bool CHWJpegV4L2Decompressor::SetImageFormat(unsigned int v4l2_fmt,
809                                          unsigned int width, unsigned int height)
810 {
811     // Test if new format is the same as the current configured format
812     if (m_v4l2Format.type != 0) {
813         v4l2_pix_format *p = &m_v4l2Format.fmt.pix;
814         if ((p->pixelformat == v4l2_fmt) &&
815             (p->width == width) && (p->height == height))
816             return true;
817     }
818 
819     CancelCapture();
820 
821     memset(&m_v4l2Format, 0, sizeof(m_v4l2Format));
822 
823     m_v4l2Format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
824     m_v4l2Format.fmt.pix.pixelformat = v4l2_fmt;
825     m_v4l2Format.fmt.pix.width = width;
826     m_v4l2Format.fmt.pix.height = height;
827 
828     if (ioctl(GetDeviceFD(), VIDIOC_S_FMT, &m_v4l2Format) < 0) {
829         ALOGERR("Failed to S_FMT for decompressed image (%08X,%ux%u)",
830                 v4l2_fmt, width, height);
831         return false;
832     }
833 
834     return true;
835 }
836 
SetImageBuffer(char * buffer,size_t len_buffer)837 bool CHWJpegV4L2Decompressor::SetImageBuffer(char *buffer, size_t len_buffer)
838 {
839     m_v4l2DstBuffer.m.userptr = reinterpret_cast<unsigned long>(buffer);
840     m_v4l2DstBuffer.bytesused = m_v4l2Format.fmt.pix.sizeimage;
841     m_v4l2DstBuffer.length = len_buffer;
842     m_v4l2DstBuffer.memory = V4L2_MEMORY_USERPTR;
843 
844     return true;
845 }
846 
SetImageBuffer(int buffer,size_t len_buffer)847 bool CHWJpegV4L2Decompressor::SetImageBuffer(int buffer, size_t len_buffer)
848 {
849     m_v4l2DstBuffer.m.fd = buffer;
850     m_v4l2DstBuffer.bytesused = m_v4l2Format.fmt.pix.sizeimage;
851     m_v4l2DstBuffer.length = len_buffer;
852     m_v4l2DstBuffer.memory = V4L2_MEMORY_DMABUF;
853 
854     return true;
855 }
856 
PrepareStream()857 bool CHWJpegV4L2Decompressor::PrepareStream()
858 {
859     if (TestFlag(HWJPEG_FLAG_OUTPUT_READY))
860         return true;
861 
862     /*
863      * S_FMT for output stream is unneccessary because the driver assumes that
864      * the current mode is decompression if the capture stream is uncompressed
865      * format
866      */
867 
868     v4l2_requestbuffers rb;
869     memset(&rb, 0, sizeof(rb));
870 
871     rb.count = 1;
872     rb.memory = V4L2_MEMORY_USERPTR;
873     rb.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
874 
875     // REQBUFS fails if no S_FMT is not performed
876     if (ioctl(GetDeviceFD(), VIDIOC_REQBUFS, &rb) < 0) {
877         ALOGERR("Failed to REQBUFS for the JPEG stream.");
878         return false;
879     }
880 
881     if (ioctl(GetDeviceFD(), VIDIOC_STREAMON, &rb.type) < 0) {
882         ALOGERR("Failed to STREAMON for the JPEG stream.");
883 
884         rb.count = 0;
885         // don't care if reqbufs(0) fails.
886         ioctl(GetDeviceFD(), VIDIOC_REQBUFS, &rb);
887 
888         return false;
889     }
890 
891     SetFlag(HWJPEG_FLAG_OUTPUT_READY);
892 
893     return true;
894 }
895 
CancelStream()896 void CHWJpegV4L2Decompressor::CancelStream()
897 {
898     if (!TestFlag(HWJPEG_FLAG_OUTPUT_READY))
899         return;
900 
901     v4l2_requestbuffers rb;
902     memset(&rb, 0, sizeof(rb));
903     rb.count = 0;
904     rb.memory = V4L2_MEMORY_USERPTR;
905     rb.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
906 
907     // ignore error during canceling
908     ioctl(GetDeviceFD(), VIDIOC_STREAMOFF, &rb.type);
909     ioctl(GetDeviceFD(), VIDIOC_REQBUFS, &rb);
910 
911     ClearFlag(HWJPEG_FLAG_OUTPUT_READY);
912 }
913 
QBufAndWait(const char * buffer,size_t len)914 bool CHWJpegV4L2Decompressor::QBufAndWait(const char *buffer, size_t len)
915 {
916     v4l2_buffer buf;
917     memset(&buf, 0, sizeof(buf));
918     buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
919     buf.memory = V4L2_MEMORY_USERPTR;
920     buf.bytesused = len;
921     buf.m.userptr = reinterpret_cast<unsigned long>(buffer);
922     buf.length = len;
923 
924     if (ioctl(GetDeviceFD(), VIDIOC_QBUF, &buf) < 0) {
925         ALOGERR("Failed to QBUF for the JPEG stream");
926         return false;
927     }
928 
929     if (ioctl(GetDeviceFD(), VIDIOC_QBUF, &m_v4l2DstBuffer) < 0) {
930         CancelStream();
931         ALOGERR("Failed to QBUF for the decompressed image");
932         return false;
933     }
934 
935     bool ret = true;
936 
937     if (ioctl(GetDeviceFD(), VIDIOC_DQBUF, &buf) < 0) {
938         ALOGERR("Failed to DQBUF of the stream buffer");
939         ret = false;
940     }
941 
942     buf.type = m_v4l2DstBuffer.type;
943     buf.memory = m_v4l2DstBuffer.memory;
944 
945     if (ioctl(GetDeviceFD(), VIDIOC_DQBUF, &buf) < 0) {
946         ALOGERR("Failed to DQBUF of the image buffer");
947         ret = false;
948     }
949 
950     m_uiHWDelay = buf.reserved2;
951 
952     return ret;
953 }
954 
Decompress(const char * buffer,size_t len)955 bool CHWJpegV4L2Decompressor::Decompress(const char *buffer, size_t len)
956 {
957     if (m_v4l2Format.type == 0) {
958         ALOGE("Decompressed image format is not specified");
959         return false;
960     }
961 
962     if (m_v4l2DstBuffer.length == 0) {
963         ALOGE("Decompressed image buffer is not specified");
964         return false;
965     }
966 
967     // Do not change the order of PrepareCapture() and PrepareStream().
968     // Otherwise, decompression will fail.
969     if (!PrepareCapture() || !PrepareStream())
970         return false;
971 
972     if (!QBufAndWait(buffer, len))
973         return false;
974 
975     return true;
976 }
977