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