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