exynos: add libion dependencies
[GitHub/LineageOS/android_hardware_samsung_slsi_exynos.git] / libhwjpeg / hwjpeg-v4l2.cpp
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
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
66 CHWJpegV4L2Compressor::~CHWJpegV4L2Compressor()
67 {
68 StopStreaming();
69
70 ALOGD("CHWJpegV4L2Compressor Destroyed: %p, FD %d", this, GetDeviceFD());
71 }
72
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
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
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
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
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
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
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
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
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
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
309 bool CHWJpegV4L2Compressor::SetJpegBuffer(int buffer, size_t len_buffer)
310 {
311 m_v4l2DstPlanes[0].m.fd = buffer;
312 m_v4l2DstPlanes[0].length = len_buffer;
313 m_v4l2DstBuffer.memory = V4L2_MEMORY_DMABUF;
314 SetFlag(HWJPEG_FLAG_DST_BUFFER);
315 return true;
316 }
317
318 bool CHWJpegV4L2Compressor::SetJpegBuffer2(char *buffer, size_t len_buffer)
319 {
320 if (!IsDeviceCapability(V4L2_CAP_EXYNOS_JPEG_B2B_COMPRESSION)) {
321 ALOGE("Back-to-back compression is not suppored by H/W");
322 return false;
323 }
324
325 m_v4l2DstPlanes[1].m.userptr = reinterpret_cast<unsigned long>(buffer);
326 m_v4l2DstPlanes[1].length = len_buffer;
327 SetFlag(HWJPEG_FLAG_DST_BUFFER2);
328 return true;
329 }
330
331 bool CHWJpegV4L2Compressor::SetJpegBuffer2(int buffer, size_t len_buffer)
332 {
333 if (!IsDeviceCapability(V4L2_CAP_EXYNOS_JPEG_B2B_COMPRESSION)) {
334 ALOGE("Back-to-back compression is not suppored by H/W");
335 return false;
336 }
337
338 m_v4l2DstPlanes[1].m.fd = buffer;
339 m_v4l2DstPlanes[1].length = len_buffer;
340 SetFlag(HWJPEG_FLAG_DST_BUFFER2);
341 return true;
342 }
343
344 bool CHWJpegV4L2Compressor::StopStreaming()
345 {
346 if (TestFlag(HWJPEG_FLAG_STREAMING)) {
347 if (!StreamOff())
348 return false;
349 ClearFlag(HWJPEG_FLAG_STREAMING);
350 }
351
352 // Stream off dequeues all queued buffers
353 ClearFlag(HWJPEG_FLAG_QBUF_OUT | HWJPEG_FLAG_QBUF_CAP);
354
355 // It is OK to skip DQBUF because STREAMOFF dequeues all queued buffers
356 if (TestFlag(HWJPEG_FLAG_REQBUFS)) {
357 if (!ReqBufs(0))
358 return false;
359 ClearFlag(HWJPEG_FLAG_REQBUFS);
360 }
361
362 return true;
363 }
364
365 ssize_t CHWJpegV4L2Compressor::Compress(size_t *secondary_stream_size, bool block_mode)
366 {
367 if (TestFlag(HWJPEG_FLAG_PIX_FMT)) {
368 if (!StopStreaming() || !SetFormat())
369 return -1;
370 }
371
372 if (!TestFlag(HWJPEG_FLAG_SRC_BUFFER)) {
373 ALOGE("Source image buffer is not specified");
374 return -1;
375 }
376
377 if (!TestFlag(HWJPEG_FLAG_DST_BUFFER)) {
378 ALOGE("Output JPEG stream buffer is not specified");
379 return -1;
380 }
381
382 m_v4l2SrcBuffer.length = m_v4l2Format.fmt.pix_mp.num_planes;
383 m_v4l2DstBuffer.length = 1;
384 if (IsB2BCompression()) {
385 if (!TestFlag(HWJPEG_FLAG_SRC_BUFFER2 | HWJPEG_FLAG_DST_BUFFER2)) {
386 ALOGE("Either of source or destination buffer of secondary image is not specified (%#x)",
387 GetFlags());
388 return -1;
389 }
390 // The SMFC Driver expects the number of buffers to be doubled
391 // if back-to-back compression is enabled
392 m_v4l2SrcBuffer.length *= 2;
393 m_v4l2DstBuffer.length = 2;
394 }
395
396 if (!!(GetAuxFlags() & EXYNOS_HWJPEG_AUXOPT_SRC_NOCACHECLEAN))
397 m_v4l2SrcBuffer.flags |= V4L2_BUF_FLAG_NO_CACHE_CLEAN;
398 if (!!(GetAuxFlags() & EXYNOS_HWJPEG_AUXOPT_DST_NOCACHECLEAN))
399 m_v4l2DstBuffer.flags |= V4L2_BUF_FLAG_NO_CACHE_CLEAN;
400
401 if (!ReqBufs() || !StreamOn() || !UpdateControls() || !QBuf())
402 return -1;
403
404 return block_mode ? DQBuf(secondary_stream_size) : 0;
405 }
406
407 bool CHWJpegV4L2Compressor::TryFormat()
408 {
409 if (ioctl(GetDeviceFD(), VIDIOC_TRY_FMT, &m_v4l2Format) < 0) {
410 ALOGERR("Failed to TRY_FMT for compression");
411 return false;
412 }
413
414 return true;
415 }
416
417 bool CHWJpegV4L2Compressor::SetFormat()
418 {
419 if (ioctl(GetDeviceFD(), VIDIOC_S_FMT, &m_v4l2Format) < 0) {
420 ALOGERR("Failed to S_FMT for image to compress");
421 return false;
422 }
423
424 v4l2_format v4l2JpegFormat;
425 memset(&v4l2JpegFormat, 0, sizeof(v4l2JpegFormat));
426
427 v4l2JpegFormat.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
428 v4l2JpegFormat.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_JPEG;
429 v4l2JpegFormat.fmt.pix_mp.width = m_v4l2Format.fmt.pix_mp.width;
430 v4l2JpegFormat.fmt.pix_mp.height = m_v4l2Format.fmt.pix_mp.height;
431
432 if (ioctl(GetDeviceFD(), VIDIOC_S_FMT, &v4l2JpegFormat) < 0) {
433 ALOGERR("Failed to S_FMT for JPEG stream to capture");
434 return false;
435 }
436
437 ClearFlag(HWJPEG_FLAG_PIX_FMT);
438
439 return true;
440 }
441
442 bool CHWJpegV4L2Compressor::UpdateControls()
443 {
444 bool enable_hwfc = !!(GetAuxFlags() & EXYNOS_HWJPEG_AUXOPT_ENABLE_HWFC);
445
446 if ((m_uiControlsToSet == 0) && (enable_hwfc == m_bEnableHWFC))
447 return true;
448
449 v4l2_ext_controls ctrls;
450 v4l2_ext_control ctrl[HWJPEG_CTRL_NUM];
451
452 memset(&ctrls, 0, sizeof(ctrls));
453 memset(&ctrl, 0, sizeof(ctrl));
454
455 ctrls.ctrl_class = V4L2_CTRL_CLASS_JPEG;
456 ctrls.controls = ctrl;
457 unsigned int idx_ctrl = 0;
458 while (m_uiControlsToSet != 0) {
459 if (m_uiControlsToSet & (1 << idx_ctrl)) {
460 ctrl[ctrls.count].id = m_v4l2Controls[idx_ctrl].id;
461 ctrl[ctrls.count].value = m_v4l2Controls[idx_ctrl].value;
462 m_uiControlsToSet &= ~(1 << idx_ctrl);
463 ctrls.count++;
464 }
465 idx_ctrl++;
466 }
467
468 if (m_bEnableHWFC != enable_hwfc) {
469 m_bEnableHWFC = enable_hwfc;
470 ctrl[ctrls.count].id = V4L2_CID_JPEG_HWFC_ENABLE;
471 ctrl[ctrls.count].value = m_bEnableHWFC ? 1 : 0;
472 ctrls.count++;
473 }
474
475 if (ioctl(GetDeviceFD(), VIDIOC_S_EXT_CTRLS, &ctrls) < 0) {
476 ALOGERR("Failed to configure %u controls", ctrls.count);
477 return false;
478 }
479
480 return true;
481 }
482
483 bool CHWJpegV4L2Compressor::ReqBufs(unsigned int count)
484 {
485 // - count > 0 && REQBUFS is set: Just return true
486 // - count > 0 && REQBUFS is unset: REQBUFS(count) is required
487 // - count == 0 && REQBUFS is set: REQBUFS(0) is required
488 // - count == 0 && REQBUFS is unset: Just return true;
489 if ((count > 0) == TestFlag(HWJPEG_FLAG_REQBUFS))
490 return true;
491
492 v4l2_requestbuffers reqbufs;
493
494 memset(&reqbufs, 0, sizeof(reqbufs));
495 reqbufs.count = count;
496 reqbufs.memory = m_v4l2SrcBuffer.memory;
497 reqbufs.type = m_v4l2SrcBuffer.type;
498 if (ioctl(GetDeviceFD(), VIDIOC_REQBUFS, &reqbufs) < 0) {
499 ALOGERR("Failed to REQBUFS(%u) of the source image", count);
500 return false;
501 }
502
503 memset(&reqbufs, 0, sizeof(reqbufs));
504 reqbufs.count = count;
505 reqbufs.memory = m_v4l2DstBuffer.memory;
506 reqbufs.type = m_v4l2DstBuffer.type;
507 if (ioctl(GetDeviceFD(), VIDIOC_REQBUFS, &reqbufs) < 0) {
508 ALOGERR("Failed to REQBUFS(%u) of the JPEG stream", count);
509 // rolling back the reqbufs for the source image
510 reqbufs.memory = m_v4l2SrcBuffer.memory;
511 reqbufs.type = m_v4l2SrcBuffer.type;
512 reqbufs.count = 0;
513 ioctl(GetDeviceFD(), VIDIOC_REQBUFS, &reqbufs); // don't care if it fails
514 return false;
515 }
516
517 if (count > 0)
518 SetFlag(HWJPEG_FLAG_REQBUFS);
519 else
520 ClearFlag(HWJPEG_FLAG_REQBUFS);
521
522 return true;
523 }
524
525 bool CHWJpegV4L2Compressor::StreamOn()
526 {
527 if (TestFlag(HWJPEG_FLAG_STREAMING))
528 return true;
529
530 if (!TestFlag(HWJPEG_FLAG_REQBUFS)) {
531 ALOGE("Trying to STREAMON before REQBUFS");
532 return false;
533 }
534
535 if (ioctl(GetDeviceFD(), VIDIOC_STREAMON, &m_v4l2SrcBuffer.type) < 0) {
536 ALOGERR("Failed to STREAMON for the source image");
537 return false;
538 }
539
540 if (ioctl(GetDeviceFD(), VIDIOC_STREAMON, &m_v4l2DstBuffer.type) < 0) {
541 ALOGERR("Failed to STREAMON for the JPEG stream");
542 ioctl(GetDeviceFD(), VIDIOC_STREAMOFF, &m_v4l2SrcBuffer.type);
543 return false;
544 }
545
546 SetFlag(HWJPEG_FLAG_STREAMING);
547
548 return true;
549 }
550
551 bool CHWJpegV4L2Compressor::StreamOff()
552 {
553 if (!TestFlag(HWJPEG_FLAG_STREAMING))
554 return true;
555
556 // error during stream off do not need further handling because of nothing to do
557 if (ioctl(GetDeviceFD(), VIDIOC_STREAMOFF, &m_v4l2SrcBuffer.type) < 0)
558 ALOGERR("Failed to STREAMOFF for the source image");
559
560 if (ioctl(GetDeviceFD(), VIDIOC_STREAMOFF, &m_v4l2DstBuffer.type) < 0)
561 ALOGERR("Failed to STREAMOFF for the JPEG stream");
562
563 ClearFlag(HWJPEG_FLAG_STREAMING);
564
565 return true;
566 }
567
568 bool CHWJpegV4L2Compressor::QBuf()
569 {
570 if (!TestFlag(HWJPEG_FLAG_REQBUFS)) {
571 ALOGE("QBuf is not permitted until REQBUFS is performed");
572 return false;
573 }
574
575 if (ioctl(GetDeviceFD(), VIDIOC_QBUF, &m_v4l2SrcBuffer) < 0) {
576 ALOGERR("QBuf of the source buffers is failed (B2B %s)",
577 IsB2BCompression() ? "enabled" : "disabled");
578 return false;
579 }
580
581 if (ioctl(GetDeviceFD(), VIDIOC_QBUF, &m_v4l2DstBuffer) < 0) {
582 ALOGERR("QBuf of the JPEG buffers is failed (B2B %s)",
583 IsB2BCompression() ? "enabled" : "disabled");
584 // Reqbufs(0) is the only way to cancel the previous queued buffer
585 StopStreaming();
586 return false;
587 }
588
589 SetFlag(HWJPEG_FLAG_QBUF_OUT | HWJPEG_FLAG_QBUF_CAP);
590
591 return true;
592 }
593
594 ssize_t CHWJpegV4L2Compressor::DQBuf(size_t *secondary_stream_size)
595 {
596 bool failed = false;
597 v4l2_buffer buffer_src, buffer_dst;
598 v4l2_plane planes_src[6], planes_dst[2];
599
600 ALOG_ASSERT(TestFlag(HWJPEG_FLAG_QBUF_OUT) == TestFlag(HWJPEG_FLAG_QBUF_CAP));
601
602 memset(&buffer_src, 0, sizeof(buffer_src));
603 memset(&buffer_dst, 0, sizeof(buffer_dst));
604 memset(&planes_src, 0, sizeof(planes_src));
605 memset(&planes_dst, 0, sizeof(planes_dst));
606
607 buffer_src.type = m_v4l2SrcBuffer.type;
608 buffer_src.memory = m_v4l2SrcBuffer.memory;
609 buffer_src.length = m_v4l2SrcBuffer.length;
610 buffer_src.m.planes = planes_src;
611
612 buffer_dst.type = m_v4l2DstBuffer.type;
613 buffer_dst.memory = m_v4l2DstBuffer.memory;
614 buffer_dst.length = m_v4l2DstBuffer.length;
615 buffer_dst.m.planes = planes_dst;
616
617 if (TestFlag(HWJPEG_FLAG_QBUF_OUT) && (ioctl(GetDeviceFD(), VIDIOC_DQBUF, &buffer_src) < 0)) {
618 ALOGERR("Failed to DQBUF of the image buffer");
619 failed = true;
620 }
621
622 if (TestFlag(HWJPEG_FLAG_QBUF_CAP) && (ioctl(GetDeviceFD(), VIDIOC_DQBUF, &buffer_dst) < 0)) {
623 ALOGERR("Failed to DQBUF of the JPEG stream buffer");
624 failed = true;
625 }
626
627 ClearFlag(HWJPEG_FLAG_QBUF_OUT | HWJPEG_FLAG_QBUF_CAP);
628
629 if (failed)
630 return -1;
631
632 if (!!((buffer_src.flags | buffer_dst.flags) & V4L2_BUF_FLAG_ERROR)) {
633 ALOGE("Error occurred during compression");
634 return -1;
635 }
636
637 // We don't need to check the length of secondary stream
638 // because it will be zero if the secondary image is not processed.
639 SetStreamSize(buffer_dst.m.planes[0].bytesused, buffer_dst.m.planes[1].bytesused);
640
641 // The driver stores the delay in usec. of JPEG compression by H/W
642 // to v4l2_buffer.reserved2.
643 m_uiHWDelay = buffer_dst.reserved2;
644
645 return GetStreamSize(secondary_stream_size);
646 }
647
648 ssize_t CHWJpegV4L2Compressor::WaitForCompression(size_t *secondary_stream_size)
649 {
650 return DQBuf(secondary_stream_size);
651 }
652
653 bool CHWJpegV4L2Compressor::GetImageBuffers(int buffers[], size_t len_buffers[],
654 unsigned int num_buffers)
655 {
656 if (m_v4l2SrcBuffer.memory != V4L2_MEMORY_DMABUF) {
657 ALOGE("Current image buffer type is not dma-buf but attempted to retrieve dma-buf buffers");
658 return false;
659 }
660
661 if (num_buffers < m_v4l2Format.fmt.pix_mp.num_planes) {
662 ALOGE("Number of planes are %u but attemts to retrieve %u buffers",
663 m_v4l2Format.fmt.pix_mp.num_planes, num_buffers);
664 return false;
665 }
666
667 for (unsigned int i = 0; i < m_v4l2Format.fmt.pix_mp.num_planes; i++) {
668 buffers[i] = m_v4l2SrcBuffer.m.planes[i].m.fd;
669 len_buffers[i] = m_v4l2SrcBuffer.m.planes[i].length;
670 }
671
672 return true;
673 }
674
675 bool CHWJpegV4L2Compressor::GetImageBuffers(char *buffers[], size_t len_buffers[],
676 unsigned int num_buffers)
677 {
678 if (m_v4l2SrcBuffer.memory != V4L2_MEMORY_USERPTR) {
679 ALOGE("Current image buffer type is not userptr but attempted to retrieve userptr buffers");
680 return false;
681 }
682
683 if (num_buffers < m_v4l2Format.fmt.pix_mp.num_planes) {
684 ALOGE("Number of planes are %u but attemts to retrieve %u buffers",
685 m_v4l2Format.fmt.pix_mp.num_planes, num_buffers);
686 return false;
687 }
688
689 for (unsigned int i = 0; i < m_v4l2Format.fmt.pix_mp.num_planes; i++) {
690 buffers[i] = reinterpret_cast<char *>(m_v4l2SrcBuffer.m.planes[i].m.userptr);
691 len_buffers[i] = m_v4l2SrcBuffer.m.planes[i].length;
692 }
693
694 return true;
695 }
696
697 bool CHWJpegV4L2Compressor::GetJpegBuffer(int *buffer, size_t *len_buffer)
698 {
699 if (m_v4l2DstBuffer.memory != V4L2_MEMORY_DMABUF) {
700 ALOGE("Current jpeg buffer type is not dma-buf but attempted to retrieve dma-buf buffer");
701 return false;
702 }
703
704 *buffer = m_v4l2DstBuffer.m.planes[0].m.fd;
705 *len_buffer = m_v4l2DstBuffer.m.planes[0].length;
706
707 return true;
708 }
709
710 bool CHWJpegV4L2Compressor::GetJpegBuffer(char **buffer, size_t *len_buffer)
711 {
712 if (m_v4l2DstBuffer.memory != V4L2_MEMORY_USERPTR) {
713 ALOGE("Current jpeg buffer type is not userptr but attempted to retrieve userptr buffer");
714 return false;
715 }
716
717 *buffer = reinterpret_cast<char *>(m_v4l2DstBuffer.m.planes[0].m.userptr);
718 *len_buffer = m_v4l2DstBuffer.m.planes[0].length;
719
720 return true;
721 }
722
723 void CHWJpegV4L2Compressor::Release()
724 {
725 StopStreaming();
726 }
727
728 /******************************************************************************/
729 /********* D E C O M P R E S S I O N S U P P O R T **************************/
730 /******************************************************************************/
731
732 CHWJpegV4L2Decompressor::CHWJpegV4L2Decompressor() : CHWJpegDecompressor("/dev/video12")
733 {
734 m_v4l2Format.type = 0; // inidication of uninitialized state
735
736 memset(&m_v4l2DstBuffer, 0, sizeof(m_v4l2DstBuffer));
737 m_v4l2DstBuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
738
739 if (Okay()) {
740 v4l2_capability cap;
741 memset(&cap, 0, sizeof(cap));
742 if (ioctl(GetDeviceFD(), VIDIOC_QUERYCAP, &cap) < 0) {
743 ALOGERR("Failed to query capability of /dev/video12");
744 } else if (!!(cap.capabilities & V4L2_CAP_DEVICE_CAPS)) {
745 SetDeviceCapabilities(cap.device_caps);
746 }
747 }
748 }
749
750 CHWJpegV4L2Decompressor::~CHWJpegV4L2Decompressor()
751 {
752 CancelCapture();
753 }
754
755 bool CHWJpegV4L2Decompressor::PrepareCapture()
756 {
757 if (m_v4l2DstBuffer.length < m_v4l2Format.fmt.pix.sizeimage) {
758 ALOGE("The size of the buffer %zu is smaller than required %u",
759 m_v4l2DstBuffer.length, m_v4l2Format.fmt.pix.sizeimage);
760 return false;
761 }
762
763 if (TestFlag(HWJPEG_FLAG_CAPTURE_READY))
764 return true;
765
766 v4l2_requestbuffers reqbufs;
767
768 memset(&reqbufs, 0, sizeof(reqbufs));
769 reqbufs.count = 1;
770 reqbufs.memory = m_v4l2DstBuffer.memory;
771 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
772
773 if (ioctl(GetDeviceFD(), VIDIOC_REQBUFS, &reqbufs) < 0) {
774 ALOGERR("Failed to REQBUFS for the decompressed image");
775 return false;
776 }
777
778 if (ioctl(GetDeviceFD(), VIDIOC_STREAMON, &reqbufs.type) < 0) {
779 ALOGERR("Failed to STREAMON for the decompressed image");
780 reqbufs.count = 0;
781 ioctl(GetDeviceFD(), VIDIOC_REQBUFS, &reqbufs);
782 return false;
783 }
784
785 SetFlag(HWJPEG_FLAG_CAPTURE_READY);
786
787 return true;
788 }
789
790 void CHWJpegV4L2Decompressor::CancelCapture()
791 {
792 if (!TestFlag(HWJPEG_FLAG_CAPTURE_READY))
793 return;
794
795 v4l2_requestbuffers reqbufs;
796
797 memset(&reqbufs, 0, sizeof(reqbufs));
798 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
799 reqbufs.memory = m_v4l2DstBuffer.memory;
800
801 ioctl(GetDeviceFD(), VIDIOC_STREAMOFF, &reqbufs.type);
802 ioctl(GetDeviceFD(), VIDIOC_REQBUFS, &reqbufs);
803
804 ClearFlag(HWJPEG_FLAG_CAPTURE_READY);
805 }
806
807 bool CHWJpegV4L2Decompressor::SetImageFormat(unsigned int v4l2_fmt,
808 unsigned int width, unsigned int height)
809 {
810 // Test if new format is the same as the current configured format
811 if (m_v4l2Format.type != 0) {
812 v4l2_pix_format *p = &m_v4l2Format.fmt.pix;
813 if ((p->pixelformat == v4l2_fmt) &&
814 (p->width == width) && (p->height == height))
815 return true;
816 }
817
818 CancelCapture();
819
820 memset(&m_v4l2Format, 0, sizeof(m_v4l2Format));
821
822 m_v4l2Format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
823 m_v4l2Format.fmt.pix.pixelformat = v4l2_fmt;
824 m_v4l2Format.fmt.pix.width = width;
825 m_v4l2Format.fmt.pix.height = height;
826
827 if (ioctl(GetDeviceFD(), VIDIOC_S_FMT, &m_v4l2Format) < 0) {
828 ALOGERR("Failed to S_FMT for decompressed image (%08X,%ux%u)",
829 v4l2_fmt, width, height);
830 return false;
831 }
832
833 return true;
834 }
835
836 bool CHWJpegV4L2Decompressor::SetImageBuffer(char *buffer, size_t len_buffer)
837 {
838 m_v4l2DstBuffer.m.userptr = reinterpret_cast<unsigned long>(buffer);
839 m_v4l2DstBuffer.bytesused = m_v4l2Format.fmt.pix.sizeimage;
840 m_v4l2DstBuffer.length = len_buffer;
841 m_v4l2DstBuffer.memory = V4L2_MEMORY_USERPTR;
842
843 return true;
844 }
845
846 bool CHWJpegV4L2Decompressor::SetImageBuffer(int buffer, size_t len_buffer)
847 {
848 m_v4l2DstBuffer.m.fd = buffer;
849 m_v4l2DstBuffer.bytesused = m_v4l2Format.fmt.pix.sizeimage;
850 m_v4l2DstBuffer.length = len_buffer;
851 m_v4l2DstBuffer.memory = V4L2_MEMORY_DMABUF;
852
853 return true;
854 }
855
856 bool CHWJpegV4L2Decompressor::PrepareStream()
857 {
858 if (TestFlag(HWJPEG_FLAG_OUTPUT_READY))
859 return true;
860
861 /*
862 * S_FMT for output stream is unneccessary because the driver assumes that
863 * the current mode is decompression if the capture stream is uncompressed
864 * format
865 */
866
867 v4l2_requestbuffers rb;
868 memset(&rb, 0, sizeof(rb));
869
870 rb.count = 1;
871 rb.memory = V4L2_MEMORY_USERPTR;
872 rb.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
873
874 // REQBUFS fails if no S_FMT is not performed
875 if (ioctl(GetDeviceFD(), VIDIOC_REQBUFS, &rb) < 0) {
876 ALOGERR("Failed to REQBUFS for the JPEG stream.");
877 return false;
878 }
879
880 if (ioctl(GetDeviceFD(), VIDIOC_STREAMON, &rb.type) < 0) {
881 ALOGERR("Failed to STREAMON for the JPEG stream.");
882
883 rb.count = 0;
884 // don't care if reqbufs(0) fails.
885 ioctl(GetDeviceFD(), VIDIOC_REQBUFS, &rb);
886
887 return false;
888 }
889
890 SetFlag(HWJPEG_FLAG_OUTPUT_READY);
891
892 return true;
893 }
894
895 void CHWJpegV4L2Decompressor::CancelStream()
896 {
897 if (!TestFlag(HWJPEG_FLAG_OUTPUT_READY))
898 return;
899
900 v4l2_requestbuffers rb;
901 memset(&rb, 0, sizeof(rb));
902 rb.count = 0;
903 rb.memory = V4L2_MEMORY_USERPTR;
904 rb.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
905
906 // ignore error during canceling
907 ioctl(GetDeviceFD(), VIDIOC_STREAMOFF, &rb.type);
908 ioctl(GetDeviceFD(), VIDIOC_REQBUFS, &rb);
909
910 ClearFlag(HWJPEG_FLAG_OUTPUT_READY);
911 }
912
913 bool CHWJpegV4L2Decompressor::QBufAndWait(const char *buffer, size_t len)
914 {
915 v4l2_buffer buf;
916 memset(&buf, 0, sizeof(buf));
917 buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
918 buf.memory = V4L2_MEMORY_USERPTR;
919 buf.bytesused = len;
920 buf.m.userptr = reinterpret_cast<unsigned long>(buffer);
921 buf.length = len;
922
923 if (ioctl(GetDeviceFD(), VIDIOC_QBUF, &buf) < 0) {
924 ALOGERR("Failed to QBUF for the JPEG stream");
925 return false;
926 }
927
928 if (ioctl(GetDeviceFD(), VIDIOC_QBUF, &m_v4l2DstBuffer) < 0) {
929 CancelStream();
930 ALOGERR("Failed to QBUF for the decompressed image");
931 return false;
932 }
933
934 bool ret = true;
935
936 if (ioctl(GetDeviceFD(), VIDIOC_DQBUF, &buf) < 0) {
937 ALOGERR("Failed to DQBUF of the stream buffer");
938 ret = false;
939 }
940
941 buf.type = m_v4l2DstBuffer.type;
942 buf.memory = m_v4l2DstBuffer.memory;
943
944 if (ioctl(GetDeviceFD(), VIDIOC_DQBUF, &buf) < 0) {
945 ALOGERR("Failed to DQBUF of the image buffer");
946 ret = false;
947 }
948
949 m_uiHWDelay = buf.reserved2;
950
951 return ret;
952 }
953
954 bool CHWJpegV4L2Decompressor::Decompress(const char *buffer, size_t len)
955 {
956 if (m_v4l2Format.type == 0) {
957 ALOGE("Decompressed image format is not specified");
958 return false;
959 }
960
961 if (m_v4l2DstBuffer.length == 0) {
962 ALOGE("Decompressed image buffer is not specified");
963 return false;
964 }
965
966 // Do not change the order of PrepareCapture() and PrepareStream().
967 // Otherwise, decompression will fail.
968 if (!PrepareCapture() || !PrepareStream())
969 return false;
970
971 if (!QBufAndWait(buffer, len))
972 return false;
973
974 return true;
975 }