2 * Copyright Samsung Electronics Co.,LTD.
3 * Copyright (C) 2015 The Android Open Source Project
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <linux/videodev2.h>
19 #include <linux/v4l2-controls.h>
21 #include <exynos-hwjpeg.h>
22 #include "hwjpeg-internal.h"
24 CHWJpegV4L2Compressor::CHWJpegV4L2Compressor(): CHWJpegCompressor("/dev/video12")
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
));
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
;
45 m_v4l2SrcBuffer
.m
.planes
= m_v4l2SrcPlanes
;
46 m_v4l2DstBuffer
.m
.planes
= m_v4l2DstPlanes
;
48 m_uiControlsToSet
= 0;
50 m_bEnableHWFC
= false;
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
);
60 // Initialy declare that s_fmt is required.
61 SetFlag(HWJPEG_FLAG_PIX_FMT
);
63 ALOGD("CHWJpegV4L2Compressor Created: %p, FD %d", this, GetDeviceFD());
66 CHWJpegV4L2Compressor::~CHWJpegV4L2Compressor()
70 ALOGD("CHWJpegV4L2Compressor Destroyed: %p, FD %d", this, GetDeviceFD());
73 bool CHWJpegV4L2Compressor::SetChromaSampFactor(
74 unsigned int horizontal
, unsigned int vertical
)
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;
85 ALOGE("Unsupported chroma subsampling %ux%u", horizontal
, vertical
);
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
;
96 bool CHWJpegV4L2Compressor::SetQuality(
97 unsigned int quality_factor
, unsigned int quality_factor2
)
99 if (quality_factor
> 100) {
100 ALOGE("Unsupported quality factor %u", quality_factor
);
104 if (quality_factor2
> 100) {
105 ALOGE("Unsupported quality factor %u for the secondary image",
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
;
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
;
125 bool CHWJpegV4L2Compressor::SetQuality(const unsigned char qtable
[])
127 v4l2_ext_controls ctrls
;
128 v4l2_ext_control ctrl
;
130 memset(&ctrls
, 0, sizeof(ctrls
));
131 memset(&ctrl
, 0, sizeof(ctrl
));
133 ctrls
.ctrl_class
= V4L2_CTRL_CLASS_JPEG
;
134 ctrls
.controls
= &ctrl
;
137 ctrl
.id
= V4L2_CID_JPEG_QTABLES2
;
138 ctrl
.size
= 128; /* two quantization tables */
139 ctrl
.p_u8
= const_cast<unsigned char *>(qtable
);
141 if (ioctl(GetDeviceFD(), VIDIOC_S_EXT_CTRLS
, &ctrls
) < 0) {
142 ALOGERR("Failed to configure %u controls", ctrls
.count
);
149 bool CHWJpegV4L2Compressor::SetImageFormat(unsigned int v4l2_fmt
,
150 unsigned int width
, unsigned int height
,
151 unsigned int width2
, unsigned int height2
)
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
)))
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
);
162 SetFlag(HWJPEG_FLAG_PIX_FMT
);
167 bool CHWJpegV4L2Compressor::GetImageBufferSizes(size_t buf_sizes
[], unsigned int *num_buffers
)
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
;
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
);
181 *num_buffers
= m_v4l2Format
.fmt
.pix_mp
.num_planes
;
187 bool CHWJpegV4L2Compressor::SetImageBuffer(char *buffers
[], size_t len_buffers
[],
188 unsigned int num_buffers
)
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
);
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
);
203 m_v4l2SrcPlanes
[i
].bytesused
= m_v4l2Format
.fmt
.pix_mp
.plane_fmt
[i
].sizeimage
;
204 m_v4l2SrcPlanes
[i
].length
= len_buffers
[i
];
207 m_v4l2SrcBuffer
.memory
= V4L2_MEMORY_USERPTR
;
209 SetFlag(HWJPEG_FLAG_SRC_BUFFER
);
214 bool CHWJpegV4L2Compressor::SetImageBuffer(int buffers
[], size_t len_buffers
[],
215 unsigned int num_buffers
)
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
);
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
);
230 m_v4l2SrcPlanes
[i
].bytesused
= m_v4l2Format
.fmt
.pix_mp
.plane_fmt
[i
].sizeimage
;
231 m_v4l2SrcPlanes
[i
].length
= len_buffers
[i
];
234 m_v4l2SrcBuffer
.memory
= V4L2_MEMORY_DMABUF
;
236 SetFlag(HWJPEG_FLAG_SRC_BUFFER
);
241 bool CHWJpegV4L2Compressor::SetImageBuffer2(char *buffers
[], size_t len_buffers
[],
242 unsigned int num_buffers
)
244 if (!IsDeviceCapability(V4L2_CAP_EXYNOS_JPEG_B2B_COMPRESSION
)) {
245 ALOGE("Back-to-back compression is not suppored by H/W");
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
);
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
];
264 // memory type is only configured by the primary image configuration
265 SetFlag(HWJPEG_FLAG_SRC_BUFFER2
);
270 bool CHWJpegV4L2Compressor::SetImageBuffer2(int buffers
[], size_t len_buffers
[],
271 unsigned int num_buffers
)
273 if (!IsDeviceCapability(V4L2_CAP_EXYNOS_JPEG_B2B_COMPRESSION
)) {
274 ALOGE("Back-to-back compression is not suppored by H/W");
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
);
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
];
293 // memory type is only configured by the primary image configuration
295 SetFlag(HWJPEG_FLAG_SRC_BUFFER2
);
300 bool CHWJpegV4L2Compressor::SetJpegBuffer(char *buffer
, size_t len_buffer
)
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
);
309 bool CHWJpegV4L2Compressor::SetJpegBuffer(int buffer
, size_t len_buffer
)
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
);
318 bool CHWJpegV4L2Compressor::SetJpegBuffer2(char *buffer
, size_t len_buffer
)
320 if (!IsDeviceCapability(V4L2_CAP_EXYNOS_JPEG_B2B_COMPRESSION
)) {
321 ALOGE("Back-to-back compression is not suppored by H/W");
325 m_v4l2DstPlanes
[1].m
.userptr
= reinterpret_cast<unsigned long>(buffer
);
326 m_v4l2DstPlanes
[1].length
= len_buffer
;
327 SetFlag(HWJPEG_FLAG_DST_BUFFER2
);
331 bool CHWJpegV4L2Compressor::SetJpegBuffer2(int buffer
, size_t len_buffer
)
333 if (!IsDeviceCapability(V4L2_CAP_EXYNOS_JPEG_B2B_COMPRESSION
)) {
334 ALOGE("Back-to-back compression is not suppored by H/W");
338 m_v4l2DstPlanes
[1].m
.fd
= buffer
;
339 m_v4l2DstPlanes
[1].length
= len_buffer
;
340 SetFlag(HWJPEG_FLAG_DST_BUFFER2
);
344 bool CHWJpegV4L2Compressor::StopStreaming()
346 if (TestFlag(HWJPEG_FLAG_STREAMING
)) {
349 ClearFlag(HWJPEG_FLAG_STREAMING
);
352 // Stream off dequeues all queued buffers
353 ClearFlag(HWJPEG_FLAG_QBUF_OUT
| HWJPEG_FLAG_QBUF_CAP
);
355 // It is OK to skip DQBUF because STREAMOFF dequeues all queued buffers
356 if (TestFlag(HWJPEG_FLAG_REQBUFS
)) {
359 ClearFlag(HWJPEG_FLAG_REQBUFS
);
365 ssize_t
CHWJpegV4L2Compressor::Compress(size_t *secondary_stream_size
, bool block_mode
)
367 if (TestFlag(HWJPEG_FLAG_PIX_FMT
)) {
368 if (!StopStreaming() || !SetFormat())
372 if (!TestFlag(HWJPEG_FLAG_SRC_BUFFER
)) {
373 ALOGE("Source image buffer is not specified");
377 if (!TestFlag(HWJPEG_FLAG_DST_BUFFER
)) {
378 ALOGE("Output JPEG stream buffer is not specified");
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)",
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;
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
;
401 if (!ReqBufs() || !StreamOn() || !UpdateControls() || !QBuf())
404 return block_mode
? DQBuf(secondary_stream_size
) : 0;
407 bool CHWJpegV4L2Compressor::TryFormat()
409 if (ioctl(GetDeviceFD(), VIDIOC_TRY_FMT
, &m_v4l2Format
) < 0) {
410 ALOGERR("Failed to TRY_FMT for compression");
417 bool CHWJpegV4L2Compressor::SetFormat()
419 if (ioctl(GetDeviceFD(), VIDIOC_S_FMT
, &m_v4l2Format
) < 0) {
420 ALOGERR("Failed to S_FMT for image to compress");
424 v4l2_format v4l2JpegFormat
;
425 memset(&v4l2JpegFormat
, 0, sizeof(v4l2JpegFormat
));
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
;
432 if (ioctl(GetDeviceFD(), VIDIOC_S_FMT
, &v4l2JpegFormat
) < 0) {
433 ALOGERR("Failed to S_FMT for JPEG stream to capture");
437 ClearFlag(HWJPEG_FLAG_PIX_FMT
);
442 bool CHWJpegV4L2Compressor::UpdateControls()
444 bool enable_hwfc
= !!(GetAuxFlags() & EXYNOS_HWJPEG_AUXOPT_ENABLE_HWFC
);
446 if ((m_uiControlsToSet
== 0) && (enable_hwfc
== m_bEnableHWFC
))
449 v4l2_ext_controls ctrls
;
450 v4l2_ext_control ctrl
[HWJPEG_CTRL_NUM
];
452 memset(&ctrls
, 0, sizeof(ctrls
));
453 memset(&ctrl
, 0, sizeof(ctrl
));
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
);
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;
475 if (ioctl(GetDeviceFD(), VIDIOC_S_EXT_CTRLS
, &ctrls
) < 0) {
476 ALOGERR("Failed to configure %u controls", ctrls
.count
);
483 bool CHWJpegV4L2Compressor::ReqBufs(unsigned int count
)
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
))
492 v4l2_requestbuffers reqbufs
;
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
);
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
;
513 ioctl(GetDeviceFD(), VIDIOC_REQBUFS
, &reqbufs
); // don't care if it fails
518 SetFlag(HWJPEG_FLAG_REQBUFS
);
520 ClearFlag(HWJPEG_FLAG_REQBUFS
);
525 bool CHWJpegV4L2Compressor::StreamOn()
527 if (TestFlag(HWJPEG_FLAG_STREAMING
))
530 if (!TestFlag(HWJPEG_FLAG_REQBUFS
)) {
531 ALOGE("Trying to STREAMON before REQBUFS");
535 if (ioctl(GetDeviceFD(), VIDIOC_STREAMON
, &m_v4l2SrcBuffer
.type
) < 0) {
536 ALOGERR("Failed to STREAMON for the source image");
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
);
546 SetFlag(HWJPEG_FLAG_STREAMING
);
551 bool CHWJpegV4L2Compressor::StreamOff()
553 if (!TestFlag(HWJPEG_FLAG_STREAMING
))
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");
560 if (ioctl(GetDeviceFD(), VIDIOC_STREAMOFF
, &m_v4l2DstBuffer
.type
) < 0)
561 ALOGERR("Failed to STREAMOFF for the JPEG stream");
563 ClearFlag(HWJPEG_FLAG_STREAMING
);
568 bool CHWJpegV4L2Compressor::QBuf()
570 if (!TestFlag(HWJPEG_FLAG_REQBUFS
)) {
571 ALOGE("QBuf is not permitted until REQBUFS is performed");
575 if (ioctl(GetDeviceFD(), VIDIOC_QBUF
, &m_v4l2SrcBuffer
) < 0) {
576 ALOGERR("QBuf of the source buffers is failed (B2B %s)",
577 IsB2BCompression() ? "enabled" : "disabled");
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
589 SetFlag(HWJPEG_FLAG_QBUF_OUT
| HWJPEG_FLAG_QBUF_CAP
);
594 ssize_t
CHWJpegV4L2Compressor::DQBuf(size_t *secondary_stream_size
)
597 v4l2_buffer buffer_src
, buffer_dst
;
598 v4l2_plane planes_src
[6], planes_dst
[2];
600 ALOG_ASSERT(TestFlag(HWJPEG_FLAG_QBUF_OUT
) == TestFlag(HWJPEG_FLAG_QBUF_CAP
));
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
));
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
;
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
;
617 if (TestFlag(HWJPEG_FLAG_QBUF_OUT
) && (ioctl(GetDeviceFD(), VIDIOC_DQBUF
, &buffer_src
) < 0)) {
618 ALOGERR("Failed to DQBUF of the image buffer");
622 if (TestFlag(HWJPEG_FLAG_QBUF_CAP
) && (ioctl(GetDeviceFD(), VIDIOC_DQBUF
, &buffer_dst
) < 0)) {
623 ALOGERR("Failed to DQBUF of the JPEG stream buffer");
627 ClearFlag(HWJPEG_FLAG_QBUF_OUT
| HWJPEG_FLAG_QBUF_CAP
);
632 if (!!((buffer_src
.flags
| buffer_dst
.flags
) & V4L2_BUF_FLAG_ERROR
)) {
633 ALOGE("Error occurred during compression");
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
);
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
;
645 return GetStreamSize(secondary_stream_size
);
648 ssize_t
CHWJpegV4L2Compressor::WaitForCompression(size_t *secondary_stream_size
)
650 return DQBuf(secondary_stream_size
);
653 bool CHWJpegV4L2Compressor::GetImageBuffers(int buffers
[], size_t len_buffers
[],
654 unsigned int num_buffers
)
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");
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
);
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
;
675 bool CHWJpegV4L2Compressor::GetImageBuffers(char *buffers
[], size_t len_buffers
[],
676 unsigned int num_buffers
)
678 if (m_v4l2SrcBuffer
.memory
!= V4L2_MEMORY_USERPTR
) {
679 ALOGE("Current image buffer type is not userptr but attempted to retrieve userptr buffers");
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
);
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
;
697 bool CHWJpegV4L2Compressor::GetJpegBuffer(int *buffer
, size_t *len_buffer
)
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");
704 *buffer
= m_v4l2DstBuffer
.m
.planes
[0].m
.fd
;
705 *len_buffer
= m_v4l2DstBuffer
.m
.planes
[0].length
;
710 bool CHWJpegV4L2Compressor::GetJpegBuffer(char **buffer
, size_t *len_buffer
)
712 if (m_v4l2DstBuffer
.memory
!= V4L2_MEMORY_USERPTR
) {
713 ALOGE("Current jpeg buffer type is not userptr but attempted to retrieve userptr buffer");
717 *buffer
= reinterpret_cast<char *>(m_v4l2DstBuffer
.m
.planes
[0].m
.userptr
);
718 *len_buffer
= m_v4l2DstBuffer
.m
.planes
[0].length
;
723 void CHWJpegV4L2Compressor::Release()
728 /******************************************************************************/
729 /********* D E C O M P R E S S I O N S U P P O R T **************************/
730 /******************************************************************************/
732 CHWJpegV4L2Decompressor::CHWJpegV4L2Decompressor() : CHWJpegDecompressor("/dev/video12")
734 m_v4l2Format
.type
= 0; // inidication of uninitialized state
736 memset(&m_v4l2DstBuffer
, 0, sizeof(m_v4l2DstBuffer
));
737 m_v4l2DstBuffer
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
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
);
750 CHWJpegV4L2Decompressor::~CHWJpegV4L2Decompressor()
755 bool CHWJpegV4L2Decompressor::PrepareCapture()
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
);
763 if (TestFlag(HWJPEG_FLAG_CAPTURE_READY
))
766 v4l2_requestbuffers reqbufs
;
768 memset(&reqbufs
, 0, sizeof(reqbufs
));
770 reqbufs
.memory
= m_v4l2DstBuffer
.memory
;
771 reqbufs
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
773 if (ioctl(GetDeviceFD(), VIDIOC_REQBUFS
, &reqbufs
) < 0) {
774 ALOGERR("Failed to REQBUFS for the decompressed image");
778 if (ioctl(GetDeviceFD(), VIDIOC_STREAMON
, &reqbufs
.type
) < 0) {
779 ALOGERR("Failed to STREAMON for the decompressed image");
781 ioctl(GetDeviceFD(), VIDIOC_REQBUFS
, &reqbufs
);
785 SetFlag(HWJPEG_FLAG_CAPTURE_READY
);
790 void CHWJpegV4L2Decompressor::CancelCapture()
792 if (!TestFlag(HWJPEG_FLAG_CAPTURE_READY
))
795 v4l2_requestbuffers reqbufs
;
797 memset(&reqbufs
, 0, sizeof(reqbufs
));
798 reqbufs
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
799 reqbufs
.memory
= m_v4l2DstBuffer
.memory
;
801 ioctl(GetDeviceFD(), VIDIOC_STREAMOFF
, &reqbufs
.type
);
802 ioctl(GetDeviceFD(), VIDIOC_REQBUFS
, &reqbufs
);
804 ClearFlag(HWJPEG_FLAG_CAPTURE_READY
);
807 bool CHWJpegV4L2Decompressor::SetImageFormat(unsigned int v4l2_fmt
,
808 unsigned int width
, unsigned int height
)
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
))
820 memset(&m_v4l2Format
, 0, sizeof(m_v4l2Format
));
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
;
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
);
836 bool CHWJpegV4L2Decompressor::SetImageBuffer(char *buffer
, size_t len_buffer
)
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
;
846 bool CHWJpegV4L2Decompressor::SetImageBuffer(int buffer
, size_t len_buffer
)
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
;
856 bool CHWJpegV4L2Decompressor::PrepareStream()
858 if (TestFlag(HWJPEG_FLAG_OUTPUT_READY
))
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
867 v4l2_requestbuffers rb
;
868 memset(&rb
, 0, sizeof(rb
));
871 rb
.memory
= V4L2_MEMORY_USERPTR
;
872 rb
.type
= V4L2_BUF_TYPE_VIDEO_OUTPUT
;
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.");
880 if (ioctl(GetDeviceFD(), VIDIOC_STREAMON
, &rb
.type
) < 0) {
881 ALOGERR("Failed to STREAMON for the JPEG stream.");
884 // don't care if reqbufs(0) fails.
885 ioctl(GetDeviceFD(), VIDIOC_REQBUFS
, &rb
);
890 SetFlag(HWJPEG_FLAG_OUTPUT_READY
);
895 void CHWJpegV4L2Decompressor::CancelStream()
897 if (!TestFlag(HWJPEG_FLAG_OUTPUT_READY
))
900 v4l2_requestbuffers rb
;
901 memset(&rb
, 0, sizeof(rb
));
903 rb
.memory
= V4L2_MEMORY_USERPTR
;
904 rb
.type
= V4L2_BUF_TYPE_VIDEO_OUTPUT
;
906 // ignore error during canceling
907 ioctl(GetDeviceFD(), VIDIOC_STREAMOFF
, &rb
.type
);
908 ioctl(GetDeviceFD(), VIDIOC_REQBUFS
, &rb
);
910 ClearFlag(HWJPEG_FLAG_OUTPUT_READY
);
913 bool CHWJpegV4L2Decompressor::QBufAndWait(const char *buffer
, size_t len
)
916 memset(&buf
, 0, sizeof(buf
));
917 buf
.type
= V4L2_BUF_TYPE_VIDEO_OUTPUT
;
918 buf
.memory
= V4L2_MEMORY_USERPTR
;
920 buf
.m
.userptr
= reinterpret_cast<unsigned long>(buffer
);
923 if (ioctl(GetDeviceFD(), VIDIOC_QBUF
, &buf
) < 0) {
924 ALOGERR("Failed to QBUF for the JPEG stream");
928 if (ioctl(GetDeviceFD(), VIDIOC_QBUF
, &m_v4l2DstBuffer
) < 0) {
930 ALOGERR("Failed to QBUF for the decompressed image");
936 if (ioctl(GetDeviceFD(), VIDIOC_DQBUF
, &buf
) < 0) {
937 ALOGERR("Failed to DQBUF of the stream buffer");
941 buf
.type
= m_v4l2DstBuffer
.type
;
942 buf
.memory
= m_v4l2DstBuffer
.memory
;
944 if (ioctl(GetDeviceFD(), VIDIOC_DQBUF
, &buf
) < 0) {
945 ALOGERR("Failed to DQBUF of the image buffer");
949 m_uiHWDelay
= buf
.reserved2
;
954 bool CHWJpegV4L2Decompressor::Decompress(const char *buffer
, size_t len
)
956 if (m_v4l2Format
.type
== 0) {
957 ALOGE("Decompressed image format is not specified");
961 if (m_v4l2DstBuffer
.length
== 0) {
962 ALOGE("Decompressed image buffer is not specified");
966 // Do not change the order of PrepareCapture() and PrepareStream().
967 // Otherwise, decompression will fail.
968 if (!PrepareCapture() || !PrepareStream())
971 if (!QBufAndWait(buffer
, len
))