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