blob: fd0c9c45ce8ba4ed2a942c1c52cc062e2cb21f68 [file] [log] [blame]
Thierry Strudel3d639192016-09-09 11:52:26 -07001/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
2*
3* Redistribution and use in source and binary forms, with or without
4* modification, are permitted provided that the following conditions are
5* met:
6* * Redistributions of source code must retain the above copyright
7* notice, this list of conditions and the following disclaimer.
8* * Redistributions in binary form must reproduce the above
9* copyright notice, this list of conditions and the following
10* disclaimer in the documentation and/or other materials provided
11* with the distribution.
12* * Neither the name of The Linux Foundation nor the names of its
13* contributors may be used to endorse or promote products derived
14* from this software without specific prior written permission.
15*
16* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27*
28*/
29
Thierry Strudelc2ee3302016-11-17 12:33:12 -080030
Thierry Strudel3d639192016-09-09 11:52:26 -070031#define LOG_TAG "QCamera3Channel"
32
33// To remove
34#include <cutils/properties.h>
35
36// System dependencies
37#include <fcntl.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include "hardware/gralloc.h"
41#include <utils/Timers.h>
Vineeta Srivastavafd5889f2017-03-03 20:17:32 -080042#include <sys/stat.h>
Thierry Strudel3d639192016-09-09 11:52:26 -070043
44// Camera dependencies
45#include "QCamera3Channel.h"
46#include "QCamera3HWI.h"
47#include "QCameraTrace.h"
48#include "QCameraFormat.h"
49extern "C" {
50#include "mm_camera_dbg.h"
51}
52
53using namespace android;
54
55namespace qcamera {
56#define IS_BUFFER_ERROR(x) (((x) & V4L2_BUF_FLAG_ERROR) == V4L2_BUF_FLAG_ERROR)
57
58/*===========================================================================
59 * FUNCTION : QCamera3Channel
60 *
61 * DESCRIPTION: constrcutor of QCamera3Channel
62 *
63 * PARAMETERS :
64 * @cam_handle : camera handle
65 * @cam_ops : ptr to camera ops table
66 *
67 * RETURN : none
68 *==========================================================================*/
69QCamera3Channel::QCamera3Channel(uint32_t cam_handle,
70 uint32_t channel_handle,
71 mm_camera_ops_t *cam_ops,
72 channel_cb_routine cb_routine,
Thierry Strudelc2ee3302016-11-17 12:33:12 -080073 channel_cb_buffer_err cb_buffer_err,
Thierry Strudel3d639192016-09-09 11:52:26 -070074 cam_padding_info_t *paddingInfo,
75 cam_feature_mask_t postprocess_mask,
76 void *userData, uint32_t numBuffers)
77{
78 m_camHandle = cam_handle;
79 m_handle = channel_handle;
80 m_camOps = cam_ops;
81 m_bIsActive = false;
Thierry Strudel2896d122017-02-23 19:18:03 -080082 m_bUBWCenable = true;
Thierry Strudel3d639192016-09-09 11:52:26 -070083
84 m_numStreams = 0;
85 memset(mStreams, 0, sizeof(mStreams));
86 mUserData = userData;
87
88 mStreamInfoBuf = NULL;
89 mChannelCB = cb_routine;
Thierry Strudelc2ee3302016-11-17 12:33:12 -080090 mChannelCbBufErr = cb_buffer_err;
Thierry Strudel3d639192016-09-09 11:52:26 -070091 mPaddingInfo = *paddingInfo;
92 mPaddingInfo.offset_info.offset_x = 0;
93 mPaddingInfo.offset_info.offset_y = 0;
94
95 mPostProcMask = postprocess_mask;
96
97 mIsType = IS_TYPE_NONE;
98 mNumBuffers = numBuffers;
99 mPerFrameMapUnmapEnable = true;
100 mDumpFrmCnt = 0;
Emilian Peev49c4c6b2017-04-24 10:21:34 +0100101 mNRMode = 0;
Shuzhen Wangb57ec912017-07-31 13:24:27 -0700102
103 mYUVDump = property_get_int32("persist.camera.dumpimg", 0);
Shuzhen Wang063deb52017-08-15 17:24:26 -0700104 mMapStreamBuffers = mYUVDump;
Thierry Strudel3d639192016-09-09 11:52:26 -0700105}
106
107/*===========================================================================
108 * FUNCTION : ~QCamera3Channel
109 *
110 * DESCRIPTION: destructor of QCamera3Channel
111 *
112 * PARAMETERS : none
113 *
114 * RETURN : none
115 *==========================================================================*/
116QCamera3Channel::~QCamera3Channel()
117{
118}
119
120/*===========================================================================
121 * FUNCTION : destroy
122 *
123 * DESCRIPTION: internal destructor of QCamera3Channel called by the subclasses
124 * this destructor will call pure virtual functions. stop will eventuall call
125 * QCamera3Stream::putBufs. The putBufs function will
126 * call QCamera3Channel::putStreamBufs which is pure virtual
127 *
128 * PARAMETERS : none
129 *
130 * RETURN : none
131 *==========================================================================*/
132void QCamera3Channel::destroy()
133{
134 if (m_bIsActive)
135 stop();
136
137 for (uint32_t i = 0; i < m_numStreams; i++) {
138 if (mStreams[i] != NULL) {
139 delete mStreams[i];
140 mStreams[i] = 0;
141 }
142 }
143 m_numStreams = 0;
144}
145
146/*===========================================================================
147 * FUNCTION : addStream
148 *
149 * DESCRIPTION: add a stream into channel
150 *
151 * PARAMETERS :
152 * @streamType : stream type
153 * @streamFormat : stream format
154 * @streamDim : stream dimension
155 * @streamRotation : rotation of the stream
156 * @minStreamBufNum : minimal buffer count for particular stream type
157 * @postprocessMask : post-proccess feature mask
158 * @isType : type of image stabilization required on the stream
159 *
160 * RETURN : int32_t type of status
161 * NO_ERROR -- success
162 * none-zero failure code
163 *==========================================================================*/
164int32_t QCamera3Channel::addStream(cam_stream_type_t streamType,
165 cam_format_t streamFormat,
166 cam_dimension_t streamDim,
167 cam_rotation_t streamRotation,
168 uint8_t minStreamBufNum,
169 cam_feature_mask_t postprocessMask,
170 cam_is_type_t isType,
171 uint32_t batchSize)
172{
173 int32_t rc = NO_ERROR;
174
175 if (m_numStreams >= 1) {
176 LOGE("Only one stream per channel supported in v3 Hal");
177 return BAD_VALUE;
178 }
179
180 if (m_numStreams >= MAX_STREAM_NUM_IN_BUNDLE) {
181 LOGE("stream number (%d) exceeds max limit (%d)",
182 m_numStreams, MAX_STREAM_NUM_IN_BUNDLE);
183 return BAD_VALUE;
184 }
185 QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
186 m_handle,
187 m_camOps,
188 &mPaddingInfo,
Shuzhen Wang063deb52017-08-15 17:24:26 -0700189 this,
190 mMapStreamBuffers);
Thierry Strudel3d639192016-09-09 11:52:26 -0700191 if (pStream == NULL) {
192 LOGE("No mem for Stream");
193 return NO_MEMORY;
194 }
195 LOGD("batch size is %d", batchSize);
196
197 rc = pStream->init(streamType, streamFormat, streamDim, streamRotation,
198 NULL, minStreamBufNum, postprocessMask, isType, batchSize,
199 streamCbRoutine, this);
200 if (rc == 0) {
201 mStreams[m_numStreams] = pStream;
202 m_numStreams++;
203 } else {
204 delete pStream;
205 }
206 return rc;
207}
208
209/*===========================================================================
210 * FUNCTION : start
211 *
212 * DESCRIPTION: start channel, which will start all streams belong to this channel
213 *
214 * PARAMETERS :
215 *
216 * RETURN : int32_t type of status
217 * NO_ERROR -- success
218 * none-zero failure code
219 *==========================================================================*/
220int32_t QCamera3Channel::start()
221{
Thierry Strudele80ad7c2016-12-06 10:16:27 -0800222 ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_CH_START);
Thierry Strudel3d639192016-09-09 11:52:26 -0700223 int32_t rc = NO_ERROR;
224
225 if (m_numStreams > 1) {
226 LOGW("bundle not supported");
227 } else if (m_numStreams == 0) {
228 return NO_INIT;
229 }
230
231 if(m_bIsActive) {
232 LOGW("Attempt to start active channel");
233 return rc;
234 }
235
236 for (uint32_t i = 0; i < m_numStreams; i++) {
237 if (mStreams[i] != NULL) {
238 mStreams[i]->start();
239 }
240 }
241
242 m_bIsActive = true;
243
244 return rc;
245}
246
247/*===========================================================================
248 * FUNCTION : stop
249 *
250 * DESCRIPTION: stop a channel, which will stop all streams belong to this channel
251 *
252 * PARAMETERS : none
253 *
254 * RETURN : int32_t type of status
255 * NO_ERROR -- success
256 * none-zero failure code
257 *==========================================================================*/
258int32_t QCamera3Channel::stop()
259{
Thierry Strudele80ad7c2016-12-06 10:16:27 -0800260 ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_CH_STOP);
Thierry Strudel3d639192016-09-09 11:52:26 -0700261 int32_t rc = NO_ERROR;
262 if(!m_bIsActive) {
263 LOGE("Attempt to stop inactive channel");
264 return rc;
265 }
266
267 for (uint32_t i = 0; i < m_numStreams; i++) {
268 if (mStreams[i] != NULL) {
269 mStreams[i]->stop();
270 }
271 }
272
273 m_bIsActive = false;
274 return rc;
275}
276
277/*===========================================================================
278 * FUNCTION : setBatchSize
279 *
280 * DESCRIPTION: Set batch size for the channel. This is a dummy implementation
281 * for the base class
282 *
283 * PARAMETERS :
284 * @batchSize : Number of image buffers in a batch
285 *
286 * RETURN : int32_t type of status
287 * NO_ERROR -- success always
288 * none-zero failure code
289 *==========================================================================*/
290int32_t QCamera3Channel::setBatchSize(uint32_t batchSize)
291{
292 LOGD("Dummy method. batchSize: %d unused ", batchSize);
293 return NO_ERROR;
294}
295
296/*===========================================================================
297 * FUNCTION : queueBatchBuf
298 *
299 * DESCRIPTION: This is a dummy implementation for the base class
300 *
301 * PARAMETERS :
302 *
303 * RETURN : int32_t type of status
304 * NO_ERROR -- success always
305 * none-zero failure code
306 *==========================================================================*/
307int32_t QCamera3Channel::queueBatchBuf()
308{
309 LOGD("Dummy method. Unused ");
310 return NO_ERROR;
311}
312
313/*===========================================================================
314 * FUNCTION : setPerFrameMapUnmap
315 *
316 * DESCRIPTION: Sets internal enable flag
317 *
318 * PARAMETERS :
319 * @enable : Bool value for the enable flag
320 *
321 * RETURN : int32_t type of status
322 * NO_ERROR -- success always
323 * none-zero failure code
324 *==========================================================================*/
325int32_t QCamera3Channel::setPerFrameMapUnmap(bool enable)
326{
327 mPerFrameMapUnmapEnable = enable;
328 return NO_ERROR;
329}
330
331/*===========================================================================
332 * FUNCTION : flush
333 *
334 * DESCRIPTION: flush a channel
335 *
336 * PARAMETERS : none
337 *
338 * RETURN : int32_t type of status
339 * NO_ERROR -- success
340 * none-zero failure code
341 *==========================================================================*/
342int32_t QCamera3Channel::flush()
343{
Thierry Strudele80ad7c2016-12-06 10:16:27 -0800344 ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_CH_FLUSH);
Thierry Strudel3d639192016-09-09 11:52:26 -0700345 return NO_ERROR;
346}
347
348/*===========================================================================
349 * FUNCTION : bufDone
350 *
351 * DESCRIPTION: return a stream buf back to kernel
352 *
353 * PARAMETERS :
354 * @recvd_frame : stream buf frame to be returned
355 *
356 * RETURN : int32_t type of status
357 * NO_ERROR -- success
358 * none-zero failure code
359 *==========================================================================*/
360int32_t QCamera3Channel::bufDone(mm_camera_super_buf_t *recvd_frame)
361{
362 int32_t rc = NO_ERROR;
363 for (uint32_t i = 0; i < recvd_frame->num_bufs; i++) {
364 if (recvd_frame->bufs[i] != NULL) {
365 for (uint32_t j = 0; j < m_numStreams; j++) {
366 if (mStreams[j] != NULL &&
367 mStreams[j]->getMyHandle() == recvd_frame->bufs[i]->stream_id) {
368 rc = mStreams[j]->bufDone(recvd_frame->bufs[i]->buf_idx);
369 break; // break loop j
370 }
371 }
372 }
373 }
374
375 return rc;
376}
377
378int32_t QCamera3Channel::setBundleInfo(const cam_bundle_config_t &bundleInfo)
379{
380 int32_t rc = NO_ERROR;
381 cam_stream_parm_buffer_t param;
382 memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
383 param.type = CAM_STREAM_PARAM_TYPE_SET_BUNDLE_INFO;
384 param.bundleInfo = bundleInfo;
Thierry Strudel295a0ca2016-11-03 18:38:47 -0700385 if (m_numStreams > 0 && mStreams[0]) {
386 rc = mStreams[0]->setParameter(param);
387 if (rc != NO_ERROR) {
388 LOGE("stream setParameter for set bundle failed");
389 }
Thierry Strudel3d639192016-09-09 11:52:26 -0700390 }
Thierry Strudel3d639192016-09-09 11:52:26 -0700391 return rc;
392}
393
394/*===========================================================================
395 * FUNCTION : getStreamTypeMask
396 *
397 * DESCRIPTION: Get bit mask of all stream types in this channel
398 *
399 * PARAMETERS : None
400 *
401 * RETURN : Bit mask of all stream types in this channel
402 *==========================================================================*/
403uint32_t QCamera3Channel::getStreamTypeMask()
404{
405 uint32_t mask = 0;
406 for (uint32_t i = 0; i < m_numStreams; i++) {
407 mask |= (1U << mStreams[i]->getMyType());
408 }
409 return mask;
410}
411
412/*===========================================================================
413 * FUNCTION : getStreamID
414 *
415 * DESCRIPTION: Get StreamID of requested stream type
416 *
417 * PARAMETERS : streamMask
418 *
419 * RETURN : Stream ID
420 *==========================================================================*/
421uint32_t QCamera3Channel::getStreamID(uint32_t streamMask)
422{
423 uint32_t streamID = 0;
424 for (uint32_t i = 0; i < m_numStreams; i++) {
425 if (streamMask == (uint32_t )(0x1 << mStreams[i]->getMyType())) {
426 streamID = mStreams[i]->getMyServerID();
427 break;
428 }
429 }
430 return streamID;
431}
432
433/*===========================================================================
434 * FUNCTION : getStreamByHandle
435 *
436 * DESCRIPTION: return stream object by stream handle
437 *
438 * PARAMETERS :
439 * @streamHandle : stream handle
440 *
441 * RETURN : stream object. NULL if not found
442 *==========================================================================*/
443QCamera3Stream *QCamera3Channel::getStreamByHandle(uint32_t streamHandle)
444{
445 for (uint32_t i = 0; i < m_numStreams; i++) {
446 if (mStreams[i] != NULL && mStreams[i]->getMyHandle() == streamHandle) {
447 return mStreams[i];
448 }
449 }
450 return NULL;
451}
452
453/*===========================================================================
454 * FUNCTION : getStreamByIndex
455 *
456 * DESCRIPTION: return stream object by index
457 *
458 * PARAMETERS :
459 * @streamHandle : stream handle
460 *
461 * RETURN : stream object. NULL if not found
462 *==========================================================================*/
463QCamera3Stream *QCamera3Channel::getStreamByIndex(uint32_t index)
464{
465 if (index < m_numStreams) {
466 return mStreams[index];
467 }
468 return NULL;
469}
470
471/*===========================================================================
472 * FUNCTION : streamCbRoutine
473 *
474 * DESCRIPTION: callback routine for stream
475 *
476 * PARAMETERS :
477 * @streamHandle : stream handle
478 *
479 * RETURN : stream object. NULL if not found
480 *==========================================================================*/
481void QCamera3Channel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
482 QCamera3Stream *stream, void *userdata)
483{
484 QCamera3Channel *channel = (QCamera3Channel *)userdata;
485 if (channel == NULL) {
486 LOGE("invalid channel pointer");
487 return;
488 }
489 channel->streamCbRoutine(super_frame, stream);
490}
491
492/*===========================================================================
493 * FUNCTION : dumpYUV
494 *
495 * DESCRIPTION: function to dump the YUV data from ISP/pproc
496 *
497 * PARAMETERS :
498 * @frame : frame to be dumped
499 * @dim : dimension of the stream
500 * @offset : offset of the data
501 * @name : 1 if it is ISP output/pproc input, 2 if it is pproc output
502 *
503 * RETURN :
504 *==========================================================================*/
505void QCamera3Channel::dumpYUV(mm_camera_buf_def_t *frame, cam_dimension_t dim,
506 cam_frame_len_offset_t offset, uint8_t dump_type)
507{
508 char buf[FILENAME_MAX];
509 memset(buf, 0, sizeof(buf));
510 static int counter = 0;
Thierry Strudel3d639192016-09-09 11:52:26 -0700511 if (mYUVDump & dump_type) {
512 mFrmNum = ((mYUVDump & 0xffff0000) >> 16);
513 if (mFrmNum == 0) {
514 mFrmNum = 10;
515 }
516 if (mFrmNum > 256) {
517 mFrmNum = 256;
518 }
519 mSkipMode = ((mYUVDump & 0x0000ff00) >> 8);
520 if (mSkipMode == 0) {
521 mSkipMode = 1;
522 }
523 if (mDumpSkipCnt == 0) {
524 mDumpSkipCnt = 1;
525 }
526 if (mDumpSkipCnt % mSkipMode == 0) {
Thierry Strudelcca4d9c2016-10-20 08:25:53 -0700527 if (mDumpFrmCnt < mFrmNum) {
Thierry Strudel3d639192016-09-09 11:52:26 -0700528 /* Note that the image dimension will be the unrotated stream dimension.
529 * If you feel that the image would have been rotated during reprocess
530 * then swap the dimensions while opening the file
531 * */
532 switch (dump_type) {
533 case QCAMERA_DUMP_FRM_PREVIEW:
534 snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"p_%d_%d_%dx%d.yuv",
535 counter, frame->frame_idx, dim.width, dim.height);
536 break;
537 case QCAMERA_DUMP_FRM_VIDEO:
538 snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"v_%d_%d_%dx%d.yuv",
539 counter, frame->frame_idx, dim.width, dim.height);
540 break;
Thierry Strudelcca4d9c2016-10-20 08:25:53 -0700541 case QCAMERA_DUMP_FRM_INPUT_JPEG:
Thierry Strudel3d639192016-09-09 11:52:26 -0700542 snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"s_%d_%d_%dx%d.yuv",
543 counter, frame->frame_idx, dim.width, dim.height);
544 break;
545 case QCAMERA_DUMP_FRM_INPUT_REPROCESS:
546 snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"ir_%d_%d_%dx%d.yuv",
547 counter, frame->frame_idx, dim.width, dim.height);
548 break;
549 case QCAMERA_DUMP_FRM_CALLBACK:
550 snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"c_%d_%d_%dx%d.yuv",
551 counter, frame->frame_idx, dim.width, dim.height);
552 break;
Thierry Strudelcca4d9c2016-10-20 08:25:53 -0700553 case QCAMERA_DUMP_FRM_OUTPUT_JPEG:
554 snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"j_%d_%d_%dx%d.jpg",
555 counter, frame->frame_idx, dim.width, dim.height);
556 break;
Thierry Strudel3d639192016-09-09 11:52:26 -0700557 default :
558 LOGE("dumping not enabled for stream type %d",dump_type);
559 break;
560 }
561 counter++;
562 int file_fd = open(buf, O_RDWR | O_CREAT, 0777);
563 ssize_t written_len = 0;
564 if (file_fd >= 0) {
565 void *data = NULL;
566 fchmod(file_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Thierry Strudelcca4d9c2016-10-20 08:25:53 -0700567 if( dump_type == QCAMERA_DUMP_FRM_OUTPUT_JPEG ) {
568 written_len = write(file_fd, frame->buffer, frame->frame_len);
569 }
570 else {
571 for (uint32_t i = 0; i < offset.num_planes; i++) {
572 uint32_t index = offset.mp[i].offset;
573 if (i > 0) {
574 index += offset.mp[i-1].len;
575 }
576 for (int j = 0; j < offset.mp[i].height; j++) {
577 data = (void *)((uint8_t *)frame->buffer + index);
578 written_len += write(file_fd, data,
579 (size_t)offset.mp[i].width);
580 index += (uint32_t)offset.mp[i].stride;
581 }
Thierry Strudel3d639192016-09-09 11:52:26 -0700582 }
583 }
584 LOGH("written number of bytes %ld\n", written_len);
585 mDumpFrmCnt++;
Thierry Strudel295a0ca2016-11-03 18:38:47 -0700586 frame->cache_flags |= CPU_HAS_READ;
Thierry Strudel3d639192016-09-09 11:52:26 -0700587 close(file_fd);
588 } else {
589 LOGE("failed to open file to dump image");
590 }
591 }
592 } else {
593 mDumpSkipCnt++;
594 }
595 }
596}
597
598/*===========================================================================
599 * FUNCTION : isUBWCEnabled
600 *
601 * DESCRIPTION: Function to get UBWC hardware support.
602 *
603 * PARAMETERS : None
604 *
605 * RETURN : TRUE -- UBWC format supported
606 * FALSE -- UBWC is not supported.
607 *==========================================================================*/
608bool QCamera3Channel::isUBWCEnabled()
609{
610#ifdef UBWC_PRESENT
611 char value[PROPERTY_VALUE_MAX];
612 int prop_value = 0;
613 memset(value, 0, sizeof(value));
614 property_get("debug.gralloc.gfx_ubwc_disable", value, "0");
615 prop_value = atoi(value);
616 if (prop_value) {
617 return FALSE;
618 }
619
620 //Disable UBWC if Eztune is enabled
621 //EzTune process CPP output frame and cannot understand UBWC.
622 memset(value, 0, sizeof(value));
623 property_get("persist.camera.eztune.enable", value, "0");
624 prop_value = atoi(value);
625 if (prop_value) {
626 return FALSE;
627 }
628 return TRUE;
629#else
630 return FALSE;
631#endif
632}
633
634/*===========================================================================
Thierry Strudel2896d122017-02-23 19:18:03 -0800635 * FUNCTION : setUBWCEnabled
636 *
637 * DESCRIPTION: set UBWC enable
638 *
639 * PARAMETERS : UBWC enable value
640 *
641 * RETURN : none
642 *
643 *==========================================================================*/
644void QCamera3Channel::setUBWCEnabled(bool val)
645{
646 m_bUBWCenable = val;
647}
648
649/*===========================================================================
Thierry Strudel3d639192016-09-09 11:52:26 -0700650 * FUNCTION : getStreamDefaultFormat
651 *
652 * DESCRIPTION: return default buffer format for the stream
653 *
654 * PARAMETERS : type : Stream type
655 *
656 ** RETURN : format for stream type
657 *
658 *==========================================================================*/
Thierry Strudelcca4d9c2016-10-20 08:25:53 -0700659cam_format_t QCamera3Channel::getStreamDefaultFormat(cam_stream_type_t type,
Jason Leec4cf5032017-05-24 18:31:41 -0700660 uint32_t width, uint32_t height, bool forcePreviewUBWC, cam_is_type_t isType)
Thierry Strudel3d639192016-09-09 11:52:26 -0700661{
662 cam_format_t streamFormat;
663
664 switch (type) {
665 case CAM_STREAM_TYPE_PREVIEW:
666 if (isUBWCEnabled()) {
Binhao Line406f062017-05-03 14:39:44 -0700667
Thierry Strudel3d639192016-09-09 11:52:26 -0700668 char prop[PROPERTY_VALUE_MAX];
669 int pFormat;
670 memset(prop, 0, sizeof(prop));
671 property_get("persist.camera.preview.ubwc", prop, "1");
672 pFormat = atoi(prop);
Binhao Line406f062017-05-03 14:39:44 -0700673
674 // When goog_zoom is linked to the preview stream, disable ubwc to preview
675 property_get("persist.camera.gzoom.at", prop, "0");
Jason Leec4cf5032017-05-24 18:31:41 -0700676 bool is_goog_zoom_preview_enabled = ((atoi(prop) & 2) > 0) && isType == IS_TYPE_EIS_3_0;
Binhao Line406f062017-05-03 14:39:44 -0700677
678 if (pFormat == 1 && forcePreviewUBWC && !is_goog_zoom_preview_enabled) {
Thierry Strudel3d639192016-09-09 11:52:26 -0700679 streamFormat = CAM_FORMAT_YUV_420_NV12_UBWC;
680 } else {
681 /* Changed to macro to ensure format sent to gralloc for preview
682 is also changed if the preview format is changed at camera HAL */
683 streamFormat = PREVIEW_STREAM_FORMAT;
684 }
685 } else {
686 /* Changed to macro to ensure format sent to gralloc for preview
687 is also changed if the preview format is changed at camera HAL */
688 streamFormat = PREVIEW_STREAM_FORMAT;
689 }
690 break;
691 case CAM_STREAM_TYPE_VIDEO:
Thierry Strudelcca4d9c2016-10-20 08:25:53 -0700692 {
693 /* Disable UBWC for smaller video resolutions due to CPP downscale
694 limits. Refer cpp_hw_params.h::CPP_DOWNSCALE_LIMIT_UBWC */
695 if (isUBWCEnabled() && (width >= 640) && (height >= 480)) {
Binhao Line406f062017-05-03 14:39:44 -0700696 // When goog_zoom is linked to the video stream, disable ubwc to video
697 char prop[PROPERTY_VALUE_MAX];
698 property_get("persist.camera.gzoom.at", prop, "0");
Jason Leec4cf5032017-05-24 18:31:41 -0700699 bool is_goog_zoom_video_enabled = ((atoi(prop) & 1) > 0) && isType == IS_TYPE_EIS_3_0;
Binhao Line406f062017-05-03 14:39:44 -0700700
701 property_get("persist.camera.gzoom.4k", prop, "0");
702 bool is_goog_zoom_4k_enabled = (atoi(prop) > 0);
703 bool is_4k_video = (width >= 3840 && height >= 2160);
704
705 if ((QCameraCommon::isVideoUBWCEnabled()) && (!is_goog_zoom_video_enabled
706 || (is_4k_video && !is_goog_zoom_4k_enabled))) {
Thierry Strudel3d639192016-09-09 11:52:26 -0700707 streamFormat = CAM_FORMAT_YUV_420_NV12_UBWC;
708 } else {
709 streamFormat = CAM_FORMAT_YUV_420_NV12_VENUS;
710 }
711 } else {
712#if VENUS_PRESENT
713 streamFormat = CAM_FORMAT_YUV_420_NV12_VENUS;
714#else
715 streamFormat = CAM_FORMAT_YUV_420_NV12;
716#endif
717 }
718 break;
Thierry Strudelcca4d9c2016-10-20 08:25:53 -0700719 }
Thierry Strudel3d639192016-09-09 11:52:26 -0700720 case CAM_STREAM_TYPE_SNAPSHOT:
721 streamFormat = CAM_FORMAT_YUV_420_NV21;
722 break;
723 case CAM_STREAM_TYPE_CALLBACK:
724 /* Changed to macro to ensure format sent to gralloc for callback
725 is also changed if the preview format is changed at camera HAL */
726 streamFormat = CALLBACK_STREAM_FORMAT;
727 break;
728 case CAM_STREAM_TYPE_RAW:
729 streamFormat = CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG;
730 break;
731 default:
732 streamFormat = CAM_FORMAT_YUV_420_NV21;
733 break;
734 }
735 return streamFormat;
736}
737
738
739/* QCamera3ProcessingChannel methods */
740
741/*===========================================================================
742 * FUNCTION : QCamera3ProcessingChannel
743 *
744 * DESCRIPTION: constructor of QCamera3ProcessingChannel
745 *
746 * PARAMETERS :
747 * @cam_handle : camera handle
748 * @cam_ops : ptr to camera ops table
749 * @cb_routine : callback routine to frame aggregator
750 * @paddingInfo: stream padding info
751 * @userData : HWI handle
752 * @stream : camera3_stream_t structure
753 * @stream_type: Channel stream type
754 * @postprocess_mask: the postprocess mask for streams of this channel
755 * @metadataChannel: handle to the metadataChannel
756 * @numBuffers : number of max dequeued buffers
757 * RETURN : none
758 *==========================================================================*/
759QCamera3ProcessingChannel::QCamera3ProcessingChannel(uint32_t cam_handle,
760 uint32_t channel_handle,
761 mm_camera_ops_t *cam_ops,
762 channel_cb_routine cb_routine,
Thierry Strudelc2ee3302016-11-17 12:33:12 -0800763 channel_cb_buffer_err cb_buffer_err,
Thierry Strudel3d639192016-09-09 11:52:26 -0700764 cam_padding_info_t *paddingInfo,
765 void *userData,
766 camera3_stream_t *stream,
767 cam_stream_type_t stream_type,
768 cam_feature_mask_t postprocess_mask,
769 QCamera3Channel *metadataChannel,
770 uint32_t numBuffers) :
771 QCamera3Channel(cam_handle, channel_handle, cam_ops, cb_routine,
Thierry Strudelc2ee3302016-11-17 12:33:12 -0800772 cb_buffer_err, paddingInfo, postprocess_mask, userData, numBuffers),
Thierry Strudel3d639192016-09-09 11:52:26 -0700773 m_postprocessor(this),
774 mFrameCount(0),
775 mLastFrameCount(0),
776 mLastFpsTime(0),
777 mMemory(numBuffers),
778 mCamera3Stream(stream),
779 mNumBufs(CAM_MAX_NUM_BUFS_PER_STREAM),
780 mStreamType(stream_type),
781 mPostProcStarted(false),
782 mInputBufferConfig(false),
783 m_pMetaChannel(metadataChannel),
784 mMetaFrame(NULL),
785 mOfflineMemory(0),
Shuzhen Wang3c077d72017-04-20 22:48:59 -0700786 mOfflineMetaMemory(numBuffers + (MAX_REPROCESS_PIPELINE_STAGES - 1))
Thierry Strudel3d639192016-09-09 11:52:26 -0700787{
788 char prop[PROPERTY_VALUE_MAX];
789 property_get("persist.debug.sf.showfps", prop, "0");
790 mDebugFPS = (uint8_t) atoi(prop);
791
792 int32_t rc = m_postprocessor.init(&mMemory);
793 if (rc != 0) {
794 LOGE("Init Postprocessor failed");
795 }
796}
797
798/*===========================================================================
799 * FUNCTION : ~QCamera3ProcessingChannel
800 *
801 * DESCRIPTION: destructor of QCamera3ProcessingChannel
802 *
803 * PARAMETERS : none
804 *
805 * RETURN : none
806 *==========================================================================*/
807QCamera3ProcessingChannel::~QCamera3ProcessingChannel()
808{
809 destroy();
810
811 int32_t rc = m_postprocessor.deinit();
812 if (rc != 0) {
813 LOGE("De-init Postprocessor failed");
814 }
815
816 if (0 < mOfflineMetaMemory.getCnt()) {
817 mOfflineMetaMemory.deallocate();
818 }
819 if (0 < mOfflineMemory.getCnt()) {
820 mOfflineMemory.unregisterBuffers();
821 }
822
823}
824
825/*===========================================================================
826 * FUNCTION : streamCbRoutine
827 *
828 * DESCRIPTION:
829 *
830 * PARAMETERS :
831 * @super_frame : the super frame with filled buffer
832 * @stream : stream on which the buffer was requested and filled
833 *
834 * RETURN : none
835 *==========================================================================*/
836void QCamera3ProcessingChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
837 QCamera3Stream *stream)
838{
Thierry Strudel9ec39c62016-12-28 11:30:05 -0800839 if (mStreamType == CAM_STREAM_TYPE_PREVIEW) {
840 KPI_ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_PREVIEW_STRM_CB);
841 } else {
842 ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_PROC_CH_STRM_CB);
843 }
Thierry Strudel3d639192016-09-09 11:52:26 -0700844 //FIXME Q Buf back in case of error?
845 uint8_t frameIndex;
846 buffer_handle_t *resultBuffer;
847 int32_t resultFrameNumber;
848 camera3_stream_buffer_t result;
849 cam_dimension_t dim;
850 cam_frame_len_offset_t offset;
851
852 memset(&dim, 0, sizeof(dim));
853 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
854 if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
855 LOGE("Error with the stream callback");
856 return;
857 }
858
859 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
860 if(frameIndex >= mNumBufs) {
861 LOGE("Error, Invalid index for buffer");
862 stream->bufDone(frameIndex);
863 return;
864 }
865
866 if (mDebugFPS) {
867 showDebugFPS(stream->getMyType());
868 }
869 stream->getFrameDimension(dim);
870 stream->getFrameOffset(offset);
871 if (stream->getMyType() == CAM_STREAM_TYPE_PREVIEW) {
872 dumpYUV(super_frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_PREVIEW);
873 } else if (stream->getMyType() == CAM_STREAM_TYPE_VIDEO) {
874 dumpYUV(super_frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_VIDEO);
875 } else if (stream->getMyType() == CAM_STREAM_TYPE_CALLBACK) {
876 dumpYUV(super_frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_CALLBACK);
877 }
Thierry Strudel3d639192016-09-09 11:52:26 -0700878
Thierry Strudelc2ee3302016-11-17 12:33:12 -0800879 do {
Thierry Strudel3d639192016-09-09 11:52:26 -0700880
Thierry Strudelc2ee3302016-11-17 12:33:12 -0800881 //Use below data to issue framework callback
882 resultBuffer = (buffer_handle_t *)mMemory.getBufferHandle(frameIndex);
883 resultFrameNumber = mMemory.getFrameNumber(frameIndex);
884 uint32_t oldestBufIndex;
885 int32_t lowestFrameNumber = mMemory.getOldestFrameNumber(oldestBufIndex);
886 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
887 if ((lowestFrameNumber != -1 ) && (lowestFrameNumber < resultFrameNumber) &&
888 hal_obj->mOpMode != CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE) {
889 LOGE("Error buffer dropped for framenumber:%d with bufidx:%d",
890 lowestFrameNumber, oldestBufIndex);
891 if (mOutOfSequenceBuffers.empty()) {
892 stream->cancelBuffer(oldestBufIndex);
893 }
Gaoxiang Chen932756c2017-06-14 21:52:40 +0800894
895 //push in order!
896 auto itr = mOutOfSequenceBuffers.begin();
897 for (; itr != mOutOfSequenceBuffers.end(); itr++) {
898 mm_camera_super_buf_t *super_buf = *itr;
899 uint32_t buf_idx = super_buf->bufs[0]->buf_idx;
900 int32_t frame_num = mMemory.getFrameNumber(buf_idx);
901 if (resultFrameNumber < frame_num) {
902 LOGE("Out of order frame!! set buffer status error flag!");
903 mOutOfSequenceBuffers.insert(itr, super_frame);
904 super_buf->bufs[0]->flags |= V4L2_BUF_FLAG_ERROR;
905 break;
906 }
907 }
908
909 if (itr == mOutOfSequenceBuffers.end()) {
910 LOGE("Add the frame to the end of mOutOfSequenceBuffers");
911 // add the buffer
912 mOutOfSequenceBuffers.push_back(super_frame);
913 }
Thierry Strudelc2ee3302016-11-17 12:33:12 -0800914 return;
915 }
Thierry Strudel3d639192016-09-09 11:52:26 -0700916
Thierry Strudel54dc9782017-02-15 12:12:10 -0800917 if(hal_obj->mStreamConfig == true) {
918 switch (stream->getMyType()) {
919 case CAM_STREAM_TYPE_PREVIEW:
920 LOGH("[KPI Perf] : PROFILE_FIRST_PREVIEW_FRAME");
921 break;
922 case CAM_STREAM_TYPE_VIDEO:
923 LOGH("[KPI Perf] : PROFILE_FIRST_VIDEO_FRAME");
924 break;
925 default:
926 break;
927 }
928 hal_obj->mStreamConfig = false;
929 }
930
Thierry Strudelc2ee3302016-11-17 12:33:12 -0800931 result.stream = mCamera3Stream;
932 result.buffer = resultBuffer;
933 if (IS_BUFFER_ERROR(super_frame->bufs[0]->flags)) {
934 result.status = CAMERA3_BUFFER_STATUS_ERROR;
935 LOGW("CAMERA3_BUFFER_STATUS_ERROR for stream_type: %d",
936 mStreams[0]->getMyType());
937 mChannelCbBufErr(this, resultFrameNumber, CAMERA3_BUFFER_STATUS_ERROR, mUserData);
938 } else {
939 result.status = CAMERA3_BUFFER_STATUS_OK;
940 }
941 result.acquire_fence = -1;
942 result.release_fence = -1;
943 if(mPerFrameMapUnmapEnable) {
944 int32_t rc = stream->bufRelease(frameIndex);
945 if (NO_ERROR != rc) {
946 LOGE("Error %d releasing stream buffer %d",
947 rc, frameIndex);
948 }
949
950 rc = mMemory.unregisterBuffer(frameIndex);
951 if (NO_ERROR != rc) {
952 LOGE("Error %d unregistering stream buffer %d",
953 rc, frameIndex);
954 }
955 }
956
957 if (0 <= resultFrameNumber) {
958 if (mChannelCB) {
959 mChannelCB(NULL, &result, (uint32_t)resultFrameNumber, false, mUserData);
960 }
961 } else {
962 LOGE("Bad frame number");
963 }
964 free(super_frame);
965 super_frame = NULL;
966 if (mOutOfSequenceBuffers.empty()) {
967 break;
968 } else {
969 auto itr = mOutOfSequenceBuffers.begin();
970 super_frame = *itr;
971 frameIndex = super_frame->bufs[0]->buf_idx;
972 resultFrameNumber = mMemory.getFrameNumber(frameIndex);
973 lowestFrameNumber = mMemory.getOldestFrameNumber(oldestBufIndex);
974 LOGE("Attempting to recover next frame: result Frame#: %d, resultIdx: %d, "
975 "Lowest Frame#: %d, oldestBufIndex: %d",
976 resultFrameNumber, frameIndex, lowestFrameNumber, oldestBufIndex);
977 if ((lowestFrameNumber != -1) && (lowestFrameNumber < resultFrameNumber)) {
978 LOGE("Multiple frame dropped requesting cancel for frame %d, idx:%d",
979 lowestFrameNumber, oldestBufIndex);
980 stream->cancelBuffer(oldestBufIndex);
981 return;
982 } else if (lowestFrameNumber == resultFrameNumber) {
983 LOGE("Time to flush out head of list continue loop with this new super frame");
984 itr = mOutOfSequenceBuffers.erase(itr);
985 } else {
986 LOGE("Unexpected condition head of list is not the lowest frame number");
987 itr = mOutOfSequenceBuffers.erase(itr);
988 }
989 }
990 } while (1);
Thierry Strudel3d639192016-09-09 11:52:26 -0700991 return;
992}
993
994/*===========================================================================
995 * FUNCTION : putStreamBufs
996 *
997 * DESCRIPTION: release the buffers allocated to the stream
998 *
999 * PARAMETERS : NONE
1000 *
1001 * RETURN : NONE
1002 *==========================================================================*/
1003void QCamera3YUVChannel::putStreamBufs()
1004{
1005 QCamera3ProcessingChannel::putStreamBufs();
1006
1007 // Free allocated heap buffer.
1008 mMemory.deallocate();
1009 // Clear free heap buffer list.
1010 mFreeHeapBufferList.clear();
1011 // Clear offlinePpInfoList
1012 mOfflinePpInfoList.clear();
1013}
1014
1015/*===========================================================================
Thierry Strudelc2ee3302016-11-17 12:33:12 -08001016 * FUNCTION : timeoutFrame
1017 *
1018 * DESCRIPTION: Method to indicate to channel that a given frame has take too
1019 * long to be generated
1020 *
1021 * PARAMETERS : framenumber indicating the framenumber of the buffer timingout
1022 *
1023 * RETURN : int32_t type of status
1024 * NO_ERROR -- success
1025 * none-zero failure code
1026 *==========================================================================*/
1027int32_t QCamera3ProcessingChannel::timeoutFrame(uint32_t frameNumber)
1028{
1029 int32_t bufIdx;
1030
1031 bufIdx = mMemory.getBufferIndex(frameNumber);
1032
1033 if (bufIdx < 0) {
1034 LOGE("%s: Buffer not found for frame:%d", __func__, frameNumber);
1035 return -1;
1036 }
1037
1038 mStreams[0]->timeoutFrame(bufIdx);
1039 return NO_ERROR;
1040}
1041
1042/*===========================================================================
Thierry Strudel3d639192016-09-09 11:52:26 -07001043 * FUNCTION : request
1044 *
1045 * DESCRIPTION: handle the request - either with an input buffer or a direct
1046 * output request
1047 *
1048 * PARAMETERS :
1049 * @buffer : pointer to the output buffer
1050 * @frameNumber : frame number of the request
1051 * @pInputBuffer : pointer to input buffer if an input request
1052 * @metadata : parameters associated with the request
Thierry Strudele80ad7c2016-12-06 10:16:27 -08001053 * @internalreq : boolean to indicate if this is purely internal request
1054 * needing internal buffer allocation
1055 * @meteringonly : boolean indicating metering only frame subset of internal
1056 * not consumed by postprocessor
Thierry Strudel3d639192016-09-09 11:52:26 -07001057 *
1058 * RETURN : 0 on a success start of capture
1059 * -EINVAL on invalid input
1060 * -ENODEV on serious error
1061 *==========================================================================*/
1062int32_t QCamera3ProcessingChannel::request(buffer_handle_t *buffer,
1063 uint32_t frameNumber,
1064 camera3_stream_buffer_t* pInputBuffer,
Thierry Strudelc2ee3302016-11-17 12:33:12 -08001065 metadata_buffer_t* metadata,
Thierry Strudele80ad7c2016-12-06 10:16:27 -08001066 int &indexUsed,
1067 __unused bool internalRequest = false,
1068 __unused bool meteringOnly = false)
Thierry Strudel3d639192016-09-09 11:52:26 -07001069{
1070 int32_t rc = NO_ERROR;
1071 int index;
1072
1073 if (NULL == buffer || NULL == metadata) {
1074 LOGE("Invalid buffer/metadata in channel request");
1075 return BAD_VALUE;
1076 }
1077
1078 if (pInputBuffer) {
1079 //need to send to reprocessing
1080 LOGD("Got a request with input buffer, output streamType = %d", mStreamType);
1081 reprocess_config_t reproc_cfg;
1082 cam_dimension_t dim;
1083 memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
1084 memset(&dim, 0, sizeof(dim));
1085 setReprocConfig(reproc_cfg, pInputBuffer, metadata, mStreamFormat, dim);
1086 startPostProc(reproc_cfg);
1087
1088 qcamera_fwk_input_pp_data_t *src_frame = NULL;
1089 src_frame = (qcamera_fwk_input_pp_data_t *)calloc(1,
1090 sizeof(qcamera_fwk_input_pp_data_t));
1091 if (src_frame == NULL) {
1092 LOGE("No memory for src frame");
1093 return NO_MEMORY;
1094 }
1095 rc = setFwkInputPPData(src_frame, pInputBuffer, &reproc_cfg, metadata, buffer, frameNumber);
1096 if (NO_ERROR != rc) {
1097 LOGE("Error %d while setting framework input PP data", rc);
1098 free(src_frame);
1099 return rc;
1100 }
1101 LOGH("Post-process started");
1102 m_postprocessor.processData(src_frame);
1103 } else {
Thierry Strudel3d639192016-09-09 11:52:26 -07001104 index = mMemory.getMatchBufIndex((void*)buffer);
1105 if(index < 0) {
1106 rc = registerBuffer(buffer, mIsType);
1107 if (NO_ERROR != rc) {
1108 LOGE("On-the-fly buffer registration failed %d",
1109 rc);
1110 return rc;
1111 }
1112
1113 index = mMemory.getMatchBufIndex((void*)buffer);
1114 if (index < 0) {
1115 LOGE("Could not find object among registered buffers");
1116 return DEAD_OBJECT;
1117 }
1118 }
Thierry Strudelc2ee3302016-11-17 12:33:12 -08001119 rc = mMemory.markFrameNumber(index, frameNumber);
1120 if(rc != NO_ERROR) {
1121 LOGE("Error marking frame number:%d for index %d", frameNumber,
1122 index);
1123 return rc;
1124 }
Shuzhen Wang3c077d72017-04-20 22:48:59 -07001125 if (m_bIsActive) {
1126 rc = mStreams[0]->bufDone(index);
1127 if(rc != NO_ERROR) {
1128 LOGE("Failed to Q new buffer to stream");
1129 mMemory.markFrameNumber(index, -1);
1130 return rc;
1131 }
Thierry Strudel3d639192016-09-09 11:52:26 -07001132 }
Thierry Strudelc2ee3302016-11-17 12:33:12 -08001133 indexUsed = index;
Thierry Strudel3d639192016-09-09 11:52:26 -07001134 }
1135 return rc;
1136}
1137
1138/*===========================================================================
1139 * FUNCTION : initialize
1140 *
1141 * DESCRIPTION:
1142 *
1143 * PARAMETERS : isType : type of image stabilization on the buffer
1144 *
1145 * RETURN : int32_t type of status
1146 * NO_ERROR -- success
1147 * none-zero failure code
1148 *==========================================================================*/
1149int32_t QCamera3ProcessingChannel::initialize(__unused cam_is_type_t isType)
1150{
1151 int32_t rc = NO_ERROR;
1152 rc = mOfflineMetaMemory.allocateAll(sizeof(metadata_buffer_t));
1153 if (rc == NO_ERROR) {
1154 Mutex::Autolock lock(mFreeOfflineMetaBuffersLock);
1155 mFreeOfflineMetaBuffersList.clear();
1156 for (uint32_t i = 0; i < mNumBuffers + (MAX_REPROCESS_PIPELINE_STAGES - 1);
1157 i++) {
1158 mFreeOfflineMetaBuffersList.push_back(i);
1159 }
1160 } else {
1161 LOGE("Could not allocate offline meta buffers for input reprocess");
1162 }
Thierry Strudelc2ee3302016-11-17 12:33:12 -08001163 mOutOfSequenceBuffers.clear();
Thierry Strudel3d639192016-09-09 11:52:26 -07001164 return rc;
1165}
1166
1167/*===========================================================================
1168 * FUNCTION : registerBuffer
1169 *
1170 * DESCRIPTION: register streaming buffer to the channel object
1171 *
1172 * PARAMETERS :
1173 * @buffer : buffer to be registered
1174 * @isType : image stabilization type on the stream
1175 *
1176 * RETURN : int32_t type of status
1177 * NO_ERROR -- success
1178 * none-zero failure code
1179 *==========================================================================*/
1180int32_t QCamera3ProcessingChannel::registerBuffer(buffer_handle_t *buffer,
1181 cam_is_type_t isType)
1182{
Thierry Strudele80ad7c2016-12-06 10:16:27 -08001183 ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_PROC_CH_REG_BUF);
Thierry Strudel3d639192016-09-09 11:52:26 -07001184 int rc = 0;
1185 mIsType = isType;
1186 cam_stream_type_t streamType;
1187
1188 if ((uint32_t)mMemory.getCnt() > (mNumBufs - 1)) {
1189 LOGE("Trying to register more buffers than initially requested");
1190 return BAD_VALUE;
1191 }
1192
1193 if (0 == m_numStreams) {
1194 rc = initialize(mIsType);
1195 if (rc != NO_ERROR) {
1196 LOGE("Couldn't initialize camera stream %d", rc);
1197 return rc;
1198 }
1199 }
1200
1201 streamType = mStreams[0]->getMyType();
1202 rc = mMemory.registerBuffer(buffer, streamType);
1203 if (ALREADY_EXISTS == rc) {
1204 return NO_ERROR;
1205 } else if (NO_ERROR != rc) {
1206 LOGE("Buffer %p couldn't be registered %d", buffer, rc);
1207 return rc;
1208 }
1209
1210 return rc;
1211}
1212
1213/*===========================================================================
1214 * FUNCTION : setFwkInputPPData
1215 *
1216 * DESCRIPTION: fill out the framework src frame information for reprocessing
1217 *
1218 * PARAMETERS :
1219 * @src_frame : input pp data to be filled out
1220 * @pInputBuffer : input buffer for reprocessing
1221 * @reproc_cfg : pointer to the reprocess config
1222 * @metadata : pointer to the metadata buffer
1223 * @output_buffer : output buffer for reprocessing; could be NULL if not
1224 * framework allocated
1225 * @frameNumber : frame number of the request
1226 *
1227 * RETURN : int32_t type of status
1228 * NO_ERROR -- success
1229 * none-zero failure code
1230 *==========================================================================*/
1231int32_t QCamera3ProcessingChannel::setFwkInputPPData(qcamera_fwk_input_pp_data_t *src_frame,
1232 camera3_stream_buffer_t *pInputBuffer, reprocess_config_t *reproc_cfg,
1233 metadata_buffer_t *metadata, buffer_handle_t *output_buffer,
1234 uint32_t frameNumber)
1235{
1236 int32_t rc = NO_ERROR;
1237 int input_index = mOfflineMemory.getMatchBufIndex((void*)pInputBuffer->buffer);
1238 if(input_index < 0) {
1239 rc = mOfflineMemory.registerBuffer(pInputBuffer->buffer, mStreamType);
1240 if (NO_ERROR != rc) {
1241 LOGE("On-the-fly input buffer registration failed %d",
1242 rc);
1243 return rc;
1244 }
1245 input_index = mOfflineMemory.getMatchBufIndex((void*)pInputBuffer->buffer);
1246 if (input_index < 0) {
1247 LOGE("Could not find object among registered buffers");
1248 return DEAD_OBJECT;
1249 }
1250 }
1251 mOfflineMemory.markFrameNumber(input_index, frameNumber);
1252
1253 src_frame->src_frame = *pInputBuffer;
1254 rc = mOfflineMemory.getBufDef(reproc_cfg->input_stream_plane_info.plane_info,
Shuzhen Wang063deb52017-08-15 17:24:26 -07001255 src_frame->input_buffer, input_index, mMapStreamBuffers);
Thierry Strudel3d639192016-09-09 11:52:26 -07001256 if (rc != 0) {
1257 return rc;
1258 }
1259 dumpYUV(&src_frame->input_buffer, reproc_cfg->input_stream_dim,
1260 reproc_cfg->input_stream_plane_info.plane_info, QCAMERA_DUMP_FRM_INPUT_REPROCESS);
1261 cam_dimension_t dim = {sizeof(metadata_buffer_t), 1};
1262 cam_stream_buf_plane_info_t meta_planes;
1263 rc = mm_stream_calc_offset_metadata(&dim, &mPaddingInfo, &meta_planes);
1264 if (rc != 0) {
1265 LOGE("Metadata stream plane info calculation failed!");
1266 return rc;
1267 }
1268 uint32_t metaBufIdx;
1269 {
1270 Mutex::Autolock lock(mFreeOfflineMetaBuffersLock);
1271 if (mFreeOfflineMetaBuffersList.empty()) {
1272 LOGE("mFreeOfflineMetaBuffersList is null. Fatal");
1273 return BAD_VALUE;
1274 }
1275
1276 metaBufIdx = *(mFreeOfflineMetaBuffersList.begin());
1277 mFreeOfflineMetaBuffersList.erase(mFreeOfflineMetaBuffersList.begin());
1278 LOGD("erasing %d, mFreeOfflineMetaBuffersList.size %d", metaBufIdx,
1279 mFreeOfflineMetaBuffersList.size());
1280 }
1281
1282 mOfflineMetaMemory.markFrameNumber(metaBufIdx, frameNumber);
1283
1284 mm_camera_buf_def_t meta_buf;
1285 cam_frame_len_offset_t offset = meta_planes.plane_info;
Shuzhen Wang063deb52017-08-15 17:24:26 -07001286 rc = mOfflineMetaMemory.getBufDef(offset, meta_buf, metaBufIdx, true /*virtualAddr*/);
Thierry Strudel3d639192016-09-09 11:52:26 -07001287 if (NO_ERROR != rc) {
1288 return rc;
1289 }
1290 memcpy(meta_buf.buffer, metadata, sizeof(metadata_buffer_t));
1291 src_frame->metadata_buffer = meta_buf;
1292 src_frame->reproc_config = *reproc_cfg;
1293 src_frame->output_buffer = output_buffer;
1294 src_frame->frameNumber = frameNumber;
1295 return rc;
1296}
1297
1298/*===========================================================================
1299 * FUNCTION : checkStreamCbErrors
1300 *
1301 * DESCRIPTION: check the stream callback for errors
1302 *
1303 * PARAMETERS :
1304 * @super_frame : the super frame with filled buffer
1305 * @stream : stream on which the buffer was requested and filled
1306 *
1307 * RETURN : int32_t type of status
1308 * NO_ERROR -- success
1309 * none-zero failure code
1310 *==========================================================================*/
1311int32_t QCamera3ProcessingChannel::checkStreamCbErrors(mm_camera_super_buf_t *super_frame,
1312 QCamera3Stream *stream)
1313{
1314 if (NULL == stream) {
1315 LOGE("Invalid stream");
1316 return BAD_VALUE;
1317 }
1318
1319 if(NULL == super_frame) {
1320 LOGE("Invalid Super buffer");
1321 return BAD_VALUE;
1322 }
1323
1324 if(super_frame->num_bufs != 1) {
1325 LOGE("Multiple streams are not supported");
1326 return BAD_VALUE;
1327 }
1328 if(NULL == super_frame->bufs[0]) {
1329 LOGE("Error, Super buffer frame does not contain valid buffer");
1330 return BAD_VALUE;
1331 }
1332 return NO_ERROR;
1333}
1334
1335/*===========================================================================
1336 * FUNCTION : getStreamSize
1337 *
1338 * DESCRIPTION: get the size from the camera3_stream_t for the channel
1339 *
1340 * PARAMETERS :
1341 * @dim : Return the size of the stream
1342 *
1343 * RETURN : int32_t type of status
1344 * NO_ERROR -- success
1345 * none-zero failure code
1346 *==========================================================================*/
1347int32_t QCamera3ProcessingChannel::getStreamSize(cam_dimension_t &dim)
1348{
1349 if (mCamera3Stream) {
1350 dim.width = mCamera3Stream->width;
1351 dim.height = mCamera3Stream->height;
1352 return NO_ERROR;
1353 } else {
1354 return BAD_VALUE;
1355 }
1356}
1357
1358/*===========================================================================
1359 * FUNCTION : getStreamBufs
1360 *
1361 * DESCRIPTION: get the buffers allocated to the stream
1362 *
1363 * PARAMETERS :
1364 * @len : buffer length
1365 *
1366 * RETURN : int32_t type of status
1367 * NO_ERROR -- success
1368 * none-zero failure code
1369 *==========================================================================*/
1370QCamera3StreamMem* QCamera3ProcessingChannel::getStreamBufs(uint32_t /*len*/)
1371{
Thierry Strudele80ad7c2016-12-06 10:16:27 -08001372 KPI_ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_GETSTREAMBUFS);
Thierry Strudel3d639192016-09-09 11:52:26 -07001373 return &mMemory;
1374}
1375
1376/*===========================================================================
1377 * FUNCTION : putStreamBufs
1378 *
1379 * DESCRIPTION: release the buffers allocated to the stream
1380 *
1381 * PARAMETERS : NONE
1382 *
1383 * RETURN : NONE
1384 *==========================================================================*/
1385void QCamera3ProcessingChannel::putStreamBufs()
1386{
1387 mMemory.unregisterBuffers();
1388
1389 /* Reclaim all the offline metabuffers and push them to free list */
1390 {
1391 Mutex::Autolock lock(mFreeOfflineMetaBuffersLock);
1392 mFreeOfflineMetaBuffersList.clear();
1393 for (uint32_t i = 0; i < mOfflineMetaMemory.getCnt(); i++) {
1394 mFreeOfflineMetaBuffersList.push_back(i);
1395 }
1396 }
1397}
1398
1399
1400/*===========================================================================
1401 * FUNCTION : stop
1402 *
1403 * DESCRIPTION: stop processing channel, which will stop all streams within,
1404 * including the reprocessing channel in postprocessor.
1405 *
1406 * PARAMETERS : none
1407 *
1408 * RETURN : int32_t type of status
1409 * NO_ERROR -- success
1410 * none-zero failure code
1411 *==========================================================================*/
1412int32_t QCamera3ProcessingChannel::stop()
1413{
Thierry Strudel9ec39c62016-12-28 11:30:05 -08001414 if (mStreamType == CAM_STREAM_TYPE_PREVIEW) {
1415 KPI_ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_STOP_PREVIEW);
1416 }
Thierry Strudel3d639192016-09-09 11:52:26 -07001417 int32_t rc = NO_ERROR;
1418 if(!m_bIsActive) {
1419 LOGE("Attempt to stop inactive channel");
1420 return rc;
1421 }
1422
1423 m_postprocessor.stop();
1424 mPostProcStarted = false;
1425 rc |= QCamera3Channel::stop();
1426 return rc;
1427}
1428
1429/*===========================================================================
1430 * FUNCTION : startPostProc
1431 *
1432 * DESCRIPTION: figure out if the postprocessor needs to be restarted and if yes
1433 * start it
1434 *
1435 * PARAMETERS :
1436 * @inputBufExists : whether there is an input buffer for post processing
1437 * @config : reprocessing configuration
1438 * @metadata : metadata associated with the reprocessing request
1439 *
1440 * RETURN : NONE
1441 *==========================================================================*/
1442void QCamera3ProcessingChannel::startPostProc(const reprocess_config_t &config)
1443{
1444 if(!mPostProcStarted) {
1445 m_postprocessor.start(config);
1446 mPostProcStarted = true;
1447 }
1448}
1449
1450/*===========================================================================
1451 * FUNCTION : queueReprocMetadata
1452 *
1453 * DESCRIPTION: queue the reprocess metadata to the postprocessor
1454 *
1455 * PARAMETERS : metadata : the metadata corresponding to the pp frame
1456 *
1457 * RETURN : int32_t type of status
1458 * NO_ERROR -- success
1459 * none-zero failure code
1460 *==========================================================================*/
1461int32_t QCamera3ProcessingChannel::queueReprocMetadata(mm_camera_super_buf_t *metadata)
1462{
1463 return m_postprocessor.processPPMetadata(metadata);
1464}
1465
1466/*===========================================================================
1467 * FUNCTION : metadataBufDone
1468 *
1469 * DESCRIPTION: Buffer done method for a metadata buffer
1470 *
1471 * PARAMETERS :
1472 * @recvd_frame : received metadata frame
1473 *
1474 * RETURN : int32_t type of status
1475 * NO_ERROR -- success
1476 * none-zero failure code
1477 *==========================================================================*/
1478int32_t QCamera3ProcessingChannel::metadataBufDone(mm_camera_super_buf_t *recvd_frame)
1479{
1480 int32_t rc = NO_ERROR;;
1481 if ((NULL == m_pMetaChannel) || (NULL == recvd_frame)) {
1482 LOGE("Metadata channel or metadata buffer invalid");
1483 return BAD_VALUE;
1484 }
1485
1486 rc = ((QCamera3MetadataChannel*)m_pMetaChannel)->bufDone(recvd_frame);
1487
1488 return rc;
1489}
1490
1491/*===========================================================================
1492 * FUNCTION : translateStreamTypeAndFormat
1493 *
1494 * DESCRIPTION: translates the framework stream format into HAL stream type
1495 * and format
1496 *
1497 * PARAMETERS :
1498 * @streamType : translated stream type
1499 * @streamFormat : translated stream format
1500 * @stream : fwk stream
1501 *
1502 * RETURN : int32_t type of status
1503 * NO_ERROR -- success
1504 * none-zero failure code
1505 *==========================================================================*/
1506int32_t QCamera3ProcessingChannel::translateStreamTypeAndFormat(camera3_stream_t *stream,
1507 cam_stream_type_t &streamType, cam_format_t &streamFormat)
1508{
1509 switch (stream->format) {
1510 case HAL_PIXEL_FORMAT_YCbCr_420_888:
1511 if(stream->stream_type == CAMERA3_STREAM_INPUT){
1512 streamType = CAM_STREAM_TYPE_SNAPSHOT;
Thierry Strudelcca4d9c2016-10-20 08:25:53 -07001513 streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_SNAPSHOT,
Jason Leec4cf5032017-05-24 18:31:41 -07001514 stream->width, stream->height, m_bUBWCenable, mIsType);
Thierry Strudel3d639192016-09-09 11:52:26 -07001515 } else {
1516 streamType = CAM_STREAM_TYPE_CALLBACK;
Thierry Strudelcca4d9c2016-10-20 08:25:53 -07001517 streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_CALLBACK,
Jason Leec4cf5032017-05-24 18:31:41 -07001518 stream->width, stream->height, m_bUBWCenable, mIsType);
Thierry Strudel3d639192016-09-09 11:52:26 -07001519 }
1520 break;
1521 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
1522 if (stream->usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) {
1523 streamType = CAM_STREAM_TYPE_VIDEO;
Thierry Strudelcca4d9c2016-10-20 08:25:53 -07001524 streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_VIDEO,
Jason Leec4cf5032017-05-24 18:31:41 -07001525 stream->width, stream->height, m_bUBWCenable, mIsType);
Thierry Strudel3d639192016-09-09 11:52:26 -07001526 } else if(stream->stream_type == CAMERA3_STREAM_INPUT ||
1527 stream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL ||
1528 IS_USAGE_ZSL(stream->usage)){
1529 streamType = CAM_STREAM_TYPE_SNAPSHOT;
Thierry Strudelcca4d9c2016-10-20 08:25:53 -07001530 streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_SNAPSHOT,
Jason Leec4cf5032017-05-24 18:31:41 -07001531 stream->width, stream->height, m_bUBWCenable, mIsType);
Thierry Strudel3d639192016-09-09 11:52:26 -07001532 } else {
1533 streamType = CAM_STREAM_TYPE_PREVIEW;
Thierry Strudelcca4d9c2016-10-20 08:25:53 -07001534 streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_PREVIEW,
Jason Leec4cf5032017-05-24 18:31:41 -07001535 stream->width, stream->height, m_bUBWCenable, mIsType);
Thierry Strudel3d639192016-09-09 11:52:26 -07001536 }
1537 break;
1538 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
1539 case HAL_PIXEL_FORMAT_RAW16:
1540 case HAL_PIXEL_FORMAT_RAW10:
1541 streamType = CAM_STREAM_TYPE_RAW;
Emilian Peev0f3c3162017-03-15 12:57:46 +00001542 if ((HAL_DATASPACE_DEPTH == stream->data_space) &&
1543 (HAL_PIXEL_FORMAT_RAW16 == stream->format)) {
1544 streamFormat = CAM_FORMAT_META_RAW_10BIT;
1545 } else {
1546 streamFormat = CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG;
1547 }
Thierry Strudel3d639192016-09-09 11:52:26 -07001548 break;
1549 default:
1550 return -EINVAL;
1551 }
1552 LOGD("fwk_format = %d, streamType = %d, streamFormat = %d",
1553 stream->format, streamType, streamFormat);
1554 return NO_ERROR;
1555}
1556
1557/*===========================================================================
1558 * FUNCTION : setReprocConfig
1559 *
1560 * DESCRIPTION: sets the reprocessing parameters for the input buffer
1561 *
1562 * PARAMETERS :
1563 * @reproc_cfg : the configuration to be set
1564 * @pInputBuffer : pointer to the input buffer
1565 * @metadata : pointer to the reprocessing metadata buffer
1566 * @streamFormat : format of the input stream
1567 *
1568 * RETURN : int32_t type of status
1569 * NO_ERROR -- success
1570 * none-zero failure code
1571 *==========================================================================*/
1572int32_t QCamera3ProcessingChannel::setReprocConfig(reprocess_config_t &reproc_cfg,
1573 camera3_stream_buffer_t *pInputBuffer,
1574 __unused metadata_buffer_t *metadata,
1575 cam_format_t streamFormat, cam_dimension_t dim)
1576{
1577 int32_t rc = 0;
1578 reproc_cfg.padding = &mPaddingInfo;
1579 //to ensure a big enough buffer size set the height and width
1580 //padding to max(height padding, width padding)
1581 if (reproc_cfg.padding->height_padding > reproc_cfg.padding->width_padding) {
1582 reproc_cfg.padding->width_padding = reproc_cfg.padding->height_padding;
1583 } else {
1584 reproc_cfg.padding->height_padding = reproc_cfg.padding->width_padding;
1585 }
1586 if (NULL != pInputBuffer) {
1587 reproc_cfg.input_stream_dim.width = (int32_t)pInputBuffer->stream->width;
1588 reproc_cfg.input_stream_dim.height = (int32_t)pInputBuffer->stream->height;
1589 } else {
1590 reproc_cfg.input_stream_dim.width = (int32_t)dim.width;
1591 reproc_cfg.input_stream_dim.height = (int32_t)dim.height;
1592 }
1593 reproc_cfg.src_channel = this;
1594 reproc_cfg.output_stream_dim.width = mCamera3Stream->width;
1595 reproc_cfg.output_stream_dim.height = mCamera3Stream->height;
1596 reproc_cfg.reprocess_type = getReprocessType();
1597
1598 //offset calculation
1599 if (NULL != pInputBuffer) {
1600 rc = translateStreamTypeAndFormat(pInputBuffer->stream,
1601 reproc_cfg.stream_type, reproc_cfg.stream_format);
1602 if (rc != NO_ERROR) {
1603 LOGE("Stream format %d is not supported",
1604 pInputBuffer->stream->format);
1605 return rc;
1606 }
1607 } else {
1608 reproc_cfg.stream_type = mStreamType;
1609 reproc_cfg.stream_format = streamFormat;
1610 }
1611
1612 switch (reproc_cfg.stream_type) {
1613 case CAM_STREAM_TYPE_PREVIEW:
1614 if (getStreamByIndex(0) == NULL) {
1615 LOGE("Could not find stream");
1616 rc = -1;
1617 break;
1618 }
1619 rc = mm_stream_calc_offset_preview(
1620 getStreamByIndex(0)->getStreamInfo(),
1621 &reproc_cfg.input_stream_dim,
1622 reproc_cfg.padding,
1623 &reproc_cfg.input_stream_plane_info);
1624 break;
1625 case CAM_STREAM_TYPE_VIDEO:
1626 rc = mm_stream_calc_offset_video(reproc_cfg.stream_format,
1627 &reproc_cfg.input_stream_dim,
1628 &reproc_cfg.input_stream_plane_info);
1629 break;
1630 case CAM_STREAM_TYPE_RAW:
1631 rc = mm_stream_calc_offset_raw(reproc_cfg.stream_format,
1632 &reproc_cfg.input_stream_dim,
1633 reproc_cfg.padding, &reproc_cfg.input_stream_plane_info);
1634 break;
1635 case CAM_STREAM_TYPE_SNAPSHOT:
1636 case CAM_STREAM_TYPE_CALLBACK:
1637 default:
1638 rc = mm_stream_calc_offset_snapshot(streamFormat, &reproc_cfg.input_stream_dim,
1639 reproc_cfg.padding, &reproc_cfg.input_stream_plane_info);
1640 break;
1641 }
1642 if (rc != 0) {
1643 LOGE("Stream %d plane info calculation failed!", mStreamType);
1644 return rc;
1645 }
Thierry Strudele80ad7c2016-12-06 10:16:27 -08001646
1647 IF_META_AVAILABLE(cam_hdr_param_t, hdr_info, CAM_INTF_PARM_HAL_BRACKETING_HDR, metadata) {
1648 reproc_cfg.hdr_param = *hdr_info;
1649 }
1650
Thierry Strudel3d639192016-09-09 11:52:26 -07001651 return rc;
1652}
1653
1654/*===========================================================================
1655 * FUNCTION : reprocessCbRoutine
1656 *
1657 * DESCRIPTION: callback function for the reprocessed frame. This frame now
1658 * should be returned to the framework
1659 *
1660 * PARAMETERS :
1661 * @resultBuffer : buffer containing the reprocessed data
1662 * @resultFrameNumber : frame number on which the buffer was requested
1663 *
1664 * RETURN : NONE
1665 *
1666 *==========================================================================*/
1667void QCamera3ProcessingChannel::reprocessCbRoutine(buffer_handle_t *resultBuffer,
1668 uint32_t resultFrameNumber)
1669{
Thierry Strudele80ad7c2016-12-06 10:16:27 -08001670 ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_PROC_CH_REPROC_CB);
Thierry Strudel3d639192016-09-09 11:52:26 -07001671 int rc = NO_ERROR;
1672
1673 rc = releaseOfflineMemory(resultFrameNumber);
1674 if (NO_ERROR != rc) {
1675 LOGE("Error releasing offline memory %d", rc);
1676 }
1677 /* Since reprocessing is done, send the callback to release the input buffer */
1678 if (mChannelCB) {
1679 mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
1680 }
1681 issueChannelCb(resultBuffer, resultFrameNumber);
1682
1683 return;
1684}
1685
1686/*===========================================================================
1687 * FUNCTION : issueChannelCb
1688 *
1689 * DESCRIPTION: function to set the result and issue channel callback
1690 *
1691 * PARAMETERS :
1692 * @resultBuffer : buffer containing the data
1693 * @resultFrameNumber : frame number on which the buffer was requested
1694 *
1695 * RETURN : NONE
1696 *
1697 *
1698 *==========================================================================*/
1699void QCamera3ProcessingChannel::issueChannelCb(buffer_handle_t *resultBuffer,
1700 uint32_t resultFrameNumber)
1701{
1702 camera3_stream_buffer_t result;
1703 //Use below data to issue framework callback
1704 result.stream = mCamera3Stream;
1705 result.buffer = resultBuffer;
1706 result.status = CAMERA3_BUFFER_STATUS_OK;
1707 result.acquire_fence = -1;
1708 result.release_fence = -1;
1709
1710 if (mChannelCB) {
1711 mChannelCB(NULL, &result, resultFrameNumber, false, mUserData);
1712 }
1713}
1714
1715/*===========================================================================
1716 * FUNCTION : showDebugFPS
1717 *
1718 * DESCRIPTION: Function to log the fps for preview, video, callback and raw
1719 * streams
1720 *
1721 * PARAMETERS : Stream type
1722 *
1723 * RETURN : None
1724 *==========================================================================*/
1725void QCamera3ProcessingChannel::showDebugFPS(int32_t streamType)
1726{
1727 double fps = 0;
1728 mFrameCount++;
1729 nsecs_t now = systemTime();
1730 nsecs_t diff = now - mLastFpsTime;
1731 if (diff > ms2ns(250)) {
1732 fps = (((double)(mFrameCount - mLastFrameCount)) *
1733 (double)(s2ns(1))) / (double)diff;
1734 switch(streamType) {
1735 case CAM_STREAM_TYPE_PREVIEW:
1736 LOGH("PROFILE_PREVIEW_FRAMES_PER_SECOND : %.4f: mFrameCount=%d",
1737 fps, mFrameCount);
1738 break;
1739 case CAM_STREAM_TYPE_VIDEO:
1740 LOGH("PROFILE_VIDEO_FRAMES_PER_SECOND : %.4f",
1741 fps);
1742 break;
1743 case CAM_STREAM_TYPE_CALLBACK:
1744 LOGH("PROFILE_CALLBACK_FRAMES_PER_SECOND : %.4f",
1745 fps);
1746 break;
1747 case CAM_STREAM_TYPE_RAW:
1748 LOGH("PROFILE_RAW_FRAMES_PER_SECOND : %.4f",
1749 fps);
1750 break;
1751 default:
1752 LOGH("logging not supported for the stream");
1753 break;
1754 }
1755 mLastFpsTime = now;
1756 mLastFrameCount = mFrameCount;
1757 }
1758}
1759
1760/*===========================================================================
1761 * FUNCTION : releaseOfflineMemory
1762 *
1763 * DESCRIPTION: function to clean up the offline memory used for input reprocess
1764 *
1765 * PARAMETERS :
1766 * @resultFrameNumber : frame number on which the buffer was requested
1767 *
1768 * RETURN : int32_t type of status
1769 * NO_ERROR -- success
1770 * non-zero failure code
1771 *
1772 *
1773 *==========================================================================*/
1774int32_t QCamera3ProcessingChannel::releaseOfflineMemory(uint32_t resultFrameNumber)
1775{
1776 int32_t rc = NO_ERROR;
1777 int32_t inputBufIndex =
1778 mOfflineMemory.getGrallocBufferIndex(resultFrameNumber);
1779 if (0 <= inputBufIndex) {
1780 rc = mOfflineMemory.unregisterBuffer(inputBufIndex);
1781 } else {
1782 LOGW("Could not find offline input buffer, resultFrameNumber %d",
1783 resultFrameNumber);
1784 }
1785 if (rc != NO_ERROR) {
1786 LOGE("Failed to unregister offline input buffer");
1787 }
1788
1789 int32_t metaBufIndex =
1790 mOfflineMetaMemory.getHeapBufferIndex(resultFrameNumber);
1791 if (0 <= metaBufIndex) {
1792 Mutex::Autolock lock(mFreeOfflineMetaBuffersLock);
1793 mFreeOfflineMetaBuffersList.push_back((uint32_t)metaBufIndex);
1794 } else {
1795 LOGW("Could not find offline meta buffer, resultFrameNumber %d",
1796 resultFrameNumber);
1797 }
1798
1799 return rc;
1800}
1801
1802/* Regular Channel methods */
1803/*===========================================================================
1804 * FUNCTION : QCamera3RegularChannel
1805 *
1806 * DESCRIPTION: constructor of QCamera3RegularChannel
1807 *
1808 * PARAMETERS :
1809 * @cam_handle : camera handle
1810 * @cam_ops : ptr to camera ops table
1811 * @cb_routine : callback routine to frame aggregator
1812 * @stream : camera3_stream_t structure
1813 * @stream_type: Channel stream type
1814 * @postprocess_mask: feature mask for postprocessing
1815 * @metadataChannel : metadata channel for the session
1816 * @numBuffers : number of max dequeued buffers
1817 *
1818 * RETURN : none
1819 *==========================================================================*/
1820QCamera3RegularChannel::QCamera3RegularChannel(uint32_t cam_handle,
1821 uint32_t channel_handle,
1822 mm_camera_ops_t *cam_ops,
1823 channel_cb_routine cb_routine,
Thierry Strudelc2ee3302016-11-17 12:33:12 -08001824 channel_cb_buffer_err cb_buffer_err,
Thierry Strudel3d639192016-09-09 11:52:26 -07001825 cam_padding_info_t *paddingInfo,
1826 void *userData,
1827 camera3_stream_t *stream,
1828 cam_stream_type_t stream_type,
1829 cam_feature_mask_t postprocess_mask,
1830 QCamera3Channel *metadataChannel,
1831 uint32_t numBuffers) :
1832 QCamera3ProcessingChannel(cam_handle, channel_handle, cam_ops,
Thierry Strudelc2ee3302016-11-17 12:33:12 -08001833 cb_routine, cb_buffer_err, paddingInfo, userData, stream, stream_type,
Thierry Strudel3d639192016-09-09 11:52:26 -07001834 postprocess_mask, metadataChannel, numBuffers),
1835 mBatchSize(0),
1836 mRotation(ROTATE_0)
1837{
1838}
1839
1840/*===========================================================================
1841 * FUNCTION : ~QCamera3RegularChannel
1842 *
1843 * DESCRIPTION: destructor of QCamera3RegularChannel
1844 *
1845 * PARAMETERS : none
1846 *
1847 * RETURN : none
1848 *==========================================================================*/
1849QCamera3RegularChannel::~QCamera3RegularChannel()
1850{
1851 destroy();
1852}
1853
1854/*===========================================================================
1855 * FUNCTION : initialize
1856 *
1857 * DESCRIPTION: Initialize and add camera channel & stream
1858 *
1859 * PARAMETERS :
1860 * @isType : type of image stabilization required on this stream
1861 *
1862 * RETURN : int32_t type of status
1863 * NO_ERROR -- success
1864 * none-zero failure code
1865 *==========================================================================*/
1866
1867int32_t QCamera3RegularChannel::initialize(cam_is_type_t isType)
1868{
Thierry Strudele80ad7c2016-12-06 10:16:27 -08001869 ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_REG_CH_INIT);
Thierry Strudel3d639192016-09-09 11:52:26 -07001870 int32_t rc = NO_ERROR;
1871
1872 cam_dimension_t streamDim;
1873
1874 if (NULL == mCamera3Stream) {
1875 LOGE("Camera stream uninitialized");
1876 return NO_INIT;
1877 }
1878
1879 if (1 <= m_numStreams) {
1880 // Only one stream per channel supported in v3 Hal
1881 return NO_ERROR;
1882 }
1883
1884 mIsType = isType;
1885
1886 rc = translateStreamTypeAndFormat(mCamera3Stream, mStreamType,
1887 mStreamFormat);
1888 if (rc != NO_ERROR) {
1889 return -EINVAL;
1890 }
1891
1892
1893 if ((mStreamType == CAM_STREAM_TYPE_VIDEO) ||
1894 (mStreamType == CAM_STREAM_TYPE_PREVIEW)) {
1895 if ((mCamera3Stream->rotation != CAMERA3_STREAM_ROTATION_0) &&
1896 ((mPostProcMask & CAM_QCOM_FEATURE_ROTATION) == 0)) {
1897 LOGE("attempting rotation %d when rotation is disabled",
1898 mCamera3Stream->rotation);
1899 return -EINVAL;
1900 }
1901
1902 switch (mCamera3Stream->rotation) {
1903 case CAMERA3_STREAM_ROTATION_0:
1904 mRotation = ROTATE_0;
1905 break;
1906 case CAMERA3_STREAM_ROTATION_90: {
1907 mRotation = ROTATE_90;
1908 break;
1909 }
1910 case CAMERA3_STREAM_ROTATION_180:
1911 mRotation = ROTATE_180;
1912 break;
1913 case CAMERA3_STREAM_ROTATION_270: {
1914 mRotation = ROTATE_270;
1915 break;
1916 }
1917 default:
1918 LOGE("Unknown rotation: %d",
1919 mCamera3Stream->rotation);
1920 return -EINVAL;
1921 }
Thierry Strudelcca4d9c2016-10-20 08:25:53 -07001922
1923 // Camera3/HAL3 spec expecting counter clockwise rotation but CPP HW is
1924 // doing Clockwise rotation and so swap it.
1925 if (mRotation == ROTATE_90) {
1926 mRotation = ROTATE_270;
1927 } else if (mRotation == ROTATE_270) {
1928 mRotation = ROTATE_90;
1929 }
1930
Thierry Strudel3d639192016-09-09 11:52:26 -07001931 } else if (mCamera3Stream->rotation != CAMERA3_STREAM_ROTATION_0) {
1932 LOGE("Rotation %d is not supported by stream type %d",
1933 mCamera3Stream->rotation,
1934 mStreamType);
1935 return -EINVAL;
1936 }
1937
1938 streamDim.width = mCamera3Stream->width;
1939 streamDim.height = mCamera3Stream->height;
1940
1941 LOGD("batch size is %d", mBatchSize);
1942 rc = QCamera3Channel::addStream(mStreamType,
1943 mStreamFormat,
1944 streamDim,
1945 mRotation,
1946 mNumBufs,
1947 mPostProcMask,
1948 mIsType,
1949 mBatchSize);
1950
1951 return rc;
1952}
1953
1954/*===========================================================================
1955 * FUNCTION : setBatchSize
1956 *
1957 * DESCRIPTION: Set batch size for the channel.
1958 *
1959 * PARAMETERS :
1960 * @batchSize : Number of image buffers in a batch
1961 *
1962 * RETURN : int32_t type of status
1963 * NO_ERROR -- success always
1964 * none-zero failure code
1965 *==========================================================================*/
1966int32_t QCamera3RegularChannel::setBatchSize(uint32_t batchSize)
1967{
1968 int32_t rc = NO_ERROR;
1969
1970 mBatchSize = batchSize;
1971 LOGD("Batch size set: %d", mBatchSize);
1972 return rc;
1973}
1974
1975/*===========================================================================
1976 * FUNCTION : getStreamTypeMask
1977 *
1978 * DESCRIPTION: Get bit mask of all stream types in this channel.
1979 * If stream is not initialized, then generate mask based on
1980 * local streamType
1981 *
1982 * PARAMETERS : None
1983 *
1984 * RETURN : Bit mask of all stream types in this channel
1985 *==========================================================================*/
1986uint32_t QCamera3RegularChannel::getStreamTypeMask()
1987{
1988 if (mStreams[0]) {
1989 return QCamera3Channel::getStreamTypeMask();
1990 } else {
1991 return (1U << mStreamType);
1992 }
1993}
1994
1995/*===========================================================================
1996 * FUNCTION : queueBatchBuf
1997 *
1998 * DESCRIPTION: queue batch container to downstream
1999 *
2000 * PARAMETERS :
2001 *
2002 * RETURN : int32_t type of status
2003 * NO_ERROR -- success always
2004 * none-zero failure code
2005 *==========================================================================*/
2006int32_t QCamera3RegularChannel::queueBatchBuf()
2007{
2008 int32_t rc = NO_ERROR;
2009
2010 if (mStreams[0]) {
2011 rc = mStreams[0]->queueBatchBuf();
2012 }
2013 if (rc != NO_ERROR) {
2014 LOGE("stream->queueBatchContainer failed");
2015 }
2016 return rc;
2017}
2018
2019/*===========================================================================
2020 * FUNCTION : request
2021 *
2022 * DESCRIPTION: process a request from camera service. Stream on if ncessary.
2023 *
2024 * PARAMETERS :
2025 * @buffer : buffer to be filled for this request
2026 *
2027 * RETURN : 0 on a success start of capture
2028 * -EINVAL on invalid input
2029 * -ENODEV on serious error
2030 *==========================================================================*/
Thierry Strudelc2ee3302016-11-17 12:33:12 -08002031int32_t QCamera3RegularChannel::request(buffer_handle_t *buffer, uint32_t frameNumber, int &indexUsed)
Thierry Strudel3d639192016-09-09 11:52:26 -07002032{
Thierry Strudele80ad7c2016-12-06 10:16:27 -08002033 ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_REG_CH_REQ);
Thierry Strudel3d639192016-09-09 11:52:26 -07002034 //FIX ME: Return buffer back in case of failures below.
2035
2036 int32_t rc = NO_ERROR;
2037 int index;
2038
2039 if (NULL == buffer) {
2040 LOGE("Invalid buffer in channel request");
2041 return BAD_VALUE;
2042 }
2043
Thierry Strudel3d639192016-09-09 11:52:26 -07002044 index = mMemory.getMatchBufIndex((void*)buffer);
2045 if(index < 0) {
2046 rc = registerBuffer(buffer, mIsType);
2047 if (NO_ERROR != rc) {
2048 LOGE("On-the-fly buffer registration failed %d",
2049 rc);
2050 return rc;
2051 }
2052
2053 index = mMemory.getMatchBufIndex((void*)buffer);
2054 if (index < 0) {
2055 LOGE("Could not find object among registered buffers");
2056 return DEAD_OBJECT;
2057 }
2058 }
2059
Thierry Strudelc2ee3302016-11-17 12:33:12 -08002060 rc = mMemory.markFrameNumber((uint32_t)index, frameNumber);
2061 if(rc != NO_ERROR) {
2062 LOGE("Failed to mark FrameNumber:%d,idx:%d",frameNumber,index);
2063 return rc;
2064 }
Shuzhen Wang3c077d72017-04-20 22:48:59 -07002065 if (m_bIsActive) {
2066 rc = mStreams[0]->bufDone((uint32_t)index);
2067 if(rc != NO_ERROR) {
2068 LOGE("Failed to Q new buffer to stream");
2069 mMemory.markFrameNumber(index, -1);
2070 return rc;
2071 }
Thierry Strudel3d639192016-09-09 11:52:26 -07002072 }
2073
Thierry Strudelc2ee3302016-11-17 12:33:12 -08002074 indexUsed = index;
Thierry Strudel3d639192016-09-09 11:52:26 -07002075 return rc;
2076}
2077
2078/*===========================================================================
2079 * FUNCTION : getReprocessType
2080 *
2081 * DESCRIPTION: get the type of reprocess output supported by this channel
2082 *
2083 * PARAMETERS : NONE
2084 *
2085 * RETURN : reprocess_type_t : type of reprocess
2086 *==========================================================================*/
2087reprocess_type_t QCamera3RegularChannel::getReprocessType()
2088{
2089 return REPROCESS_TYPE_PRIVATE;
2090}
2091
2092
2093QCamera3MetadataChannel::QCamera3MetadataChannel(uint32_t cam_handle,
2094 uint32_t channel_handle,
2095 mm_camera_ops_t *cam_ops,
2096 channel_cb_routine cb_routine,
Thierry Strudelc2ee3302016-11-17 12:33:12 -08002097 channel_cb_buffer_err cb_buffer_err,
Thierry Strudel3d639192016-09-09 11:52:26 -07002098 cam_padding_info_t *paddingInfo,
2099 cam_feature_mask_t postprocess_mask,
2100 void *userData, uint32_t numBuffers) :
2101 QCamera3Channel(cam_handle, channel_handle, cam_ops,
Thierry Strudelc2ee3302016-11-17 12:33:12 -08002102 cb_routine, cb_buffer_err, paddingInfo, postprocess_mask,
Thierry Strudel3d639192016-09-09 11:52:26 -07002103 userData, numBuffers),
Emilian Peev662c05e2017-05-16 10:00:04 +01002104 mMemory(NULL), mDepthDataPresent(false)
Thierry Strudel3d639192016-09-09 11:52:26 -07002105{
Shuzhen Wang063deb52017-08-15 17:24:26 -07002106 mMapStreamBuffers = true;
Thierry Strudel3d639192016-09-09 11:52:26 -07002107}
2108
2109QCamera3MetadataChannel::~QCamera3MetadataChannel()
2110{
2111 destroy();
2112
2113 if (mMemory) {
2114 mMemory->deallocate();
2115 delete mMemory;
2116 mMemory = NULL;
2117 }
2118}
2119
2120int32_t QCamera3MetadataChannel::initialize(cam_is_type_t isType)
2121{
Thierry Strudele80ad7c2016-12-06 10:16:27 -08002122 ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_METADATA_CH_INIT);
Thierry Strudel3d639192016-09-09 11:52:26 -07002123 int32_t rc;
2124 cam_dimension_t streamDim;
2125
2126 if (mMemory || m_numStreams > 0) {
2127 LOGE("metadata channel already initialized");
2128 return -EINVAL;
2129 }
2130
2131 streamDim.width = (int32_t)sizeof(metadata_buffer_t),
2132 streamDim.height = 1;
2133
2134 mIsType = isType;
2135 rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_METADATA, CAM_FORMAT_MAX,
2136 streamDim, ROTATE_0, (uint8_t)mNumBuffers, mPostProcMask, mIsType);
2137 if (rc < 0) {
2138 LOGE("addStream failed");
2139 }
2140 return rc;
2141}
2142
2143int32_t QCamera3MetadataChannel::request(buffer_handle_t * /*buffer*/,
Thierry Strudelc2ee3302016-11-17 12:33:12 -08002144 uint32_t /*frameNumber*/,
2145 int& /*indexUsed*/)
Thierry Strudel3d639192016-09-09 11:52:26 -07002146{
2147 if (!m_bIsActive) {
2148 return start();
2149 }
2150 else
2151 return 0;
2152}
2153
2154void QCamera3MetadataChannel::streamCbRoutine(
2155 mm_camera_super_buf_t *super_frame,
2156 QCamera3Stream * /*stream*/)
2157{
2158 ATRACE_NAME("metadata_stream_cb_routine");
2159 uint32_t requestNumber = 0;
2160 if (super_frame == NULL || super_frame->num_bufs != 1) {
2161 LOGE("super_frame is not valid");
2162 return;
2163 }
2164 if (mChannelCB) {
2165 mChannelCB(super_frame, NULL, requestNumber, false, mUserData);
2166 }
2167}
2168
2169QCamera3StreamMem* QCamera3MetadataChannel::getStreamBufs(uint32_t len)
2170{
2171 int rc;
2172 if (len < sizeof(metadata_buffer_t)) {
2173 LOGE("Metadata buffer size less than structure %d vs %d",
2174 len,
2175 sizeof(metadata_buffer_t));
2176 return NULL;
2177 }
2178 mMemory = new QCamera3StreamMem(MIN_STREAMING_BUFFER_NUM);
2179 if (!mMemory) {
2180 LOGE("unable to create metadata memory");
2181 return NULL;
2182 }
2183 rc = mMemory->allocateAll(len);
2184 if (rc < 0) {
2185 LOGE("unable to allocate metadata memory");
2186 delete mMemory;
2187 mMemory = NULL;
2188 return NULL;
2189 }
2190 clear_metadata_buffer((metadata_buffer_t*)mMemory->getPtr(0));
Emilian Peev662c05e2017-05-16 10:00:04 +01002191
2192 for (uint32_t i = 0; i < mMemory->getCnt(); i++) {
2193 if (mMemory->valid(i)) {
2194 metadata_buffer_t *metadata_buffer_t =
2195 static_cast<::metadata_buffer_t *> (mMemory->getPtr(i));
2196 metadata_buffer_t->depth_data.depth_data = nullptr;
2197 if (mDepthDataPresent) {
2198 metadata_buffer_t->depth_data.depth_data =
Emilian Peev656e4fa2017-06-02 16:47:04 +01002199 new uint8_t[PD_DATA_SIZE];
Emilian Peev662c05e2017-05-16 10:00:04 +01002200 }
2201 } else {
2202 LOGE("Invalid meta buffer at index: %d", i);
2203 }
2204 }
2205
Thierry Strudel3d639192016-09-09 11:52:26 -07002206 return mMemory;
2207}
2208
2209void QCamera3MetadataChannel::putStreamBufs()
2210{
Emilian Peev662c05e2017-05-16 10:00:04 +01002211 for (uint32_t i = 0; i < mMemory->getCnt(); i++) {
2212 if (mMemory->valid(i)) {
2213 metadata_buffer_t *metadata_buffer_t =
2214 static_cast<::metadata_buffer_t *> (mMemory->getPtr(i));
2215 if (nullptr != metadata_buffer_t->depth_data.depth_data) {
2216 delete [] metadata_buffer_t->depth_data.depth_data;
2217 metadata_buffer_t->depth_data.depth_data = nullptr;
2218 }
2219 } else {
2220 LOGE("Invalid meta buffer at index: %d", i);
2221 }
2222 }
2223
Thierry Strudel3d639192016-09-09 11:52:26 -07002224 mMemory->deallocate();
2225 delete mMemory;
2226 mMemory = NULL;
2227}
2228/*************************************************************************************/
2229// RAW Channel related functions
2230QCamera3RawChannel::QCamera3RawChannel(uint32_t cam_handle,
2231 uint32_t channel_handle,
2232 mm_camera_ops_t *cam_ops,
2233 channel_cb_routine cb_routine,
Thierry Strudelc2ee3302016-11-17 12:33:12 -08002234 channel_cb_buffer_err cb_buffer_err,
Thierry Strudel3d639192016-09-09 11:52:26 -07002235 cam_padding_info_t *paddingInfo,
2236 void *userData,
2237 camera3_stream_t *stream,
2238 cam_feature_mask_t postprocess_mask,
2239 QCamera3Channel *metadataChannel,
2240 bool raw_16, uint32_t numBuffers) :
2241 QCamera3RegularChannel(cam_handle, channel_handle, cam_ops,
Thierry Strudelc2ee3302016-11-17 12:33:12 -08002242 cb_routine, cb_buffer_err, paddingInfo, userData, stream,
Thierry Strudel3d639192016-09-09 11:52:26 -07002243 CAM_STREAM_TYPE_RAW, postprocess_mask,
2244 metadataChannel, numBuffers),
2245 mIsRaw16(raw_16)
2246{
2247 char prop[PROPERTY_VALUE_MAX];
2248 property_get("persist.camera.raw.debug.dump", prop, "0");
2249 mRawDump = atoi(prop);
Shuzhen Wang063deb52017-08-15 17:24:26 -07002250 mMapStreamBuffers = (mRawDump || mIsRaw16);
Thierry Strudel3d639192016-09-09 11:52:26 -07002251}
2252
2253QCamera3RawChannel::~QCamera3RawChannel()
2254{
2255}
2256
2257/*===========================================================================
2258 * FUNCTION : initialize
2259 *
2260 * DESCRIPTION: Initialize and add camera channel & stream
2261 *
2262 * PARAMETERS :
2263 * @isType : image stabilization type on the stream
2264 *
2265 * RETURN : int32_t type of status
2266 * NO_ERROR -- success
2267 * none-zero failure code
2268 *==========================================================================*/
2269
2270int32_t QCamera3RawChannel::initialize(cam_is_type_t isType)
2271{
2272 return QCamera3RegularChannel::initialize(isType);
2273}
2274
2275void QCamera3RawChannel::streamCbRoutine(
2276 mm_camera_super_buf_t *super_frame,
2277 QCamera3Stream * stream)
2278{
Thierry Strudele80ad7c2016-12-06 10:16:27 -08002279 ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_RAW_CH_STRM_CB);
Thierry Strudel3d639192016-09-09 11:52:26 -07002280 /* Move this back down once verified */
2281 if (mRawDump)
2282 dumpRawSnapshot(super_frame->bufs[0]);
2283
2284 if (mIsRaw16) {
Thierry Strudelcca4d9c2016-10-20 08:25:53 -07002285 cam_format_t streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_RAW,
Jason Leec4cf5032017-05-24 18:31:41 -07002286 mCamera3Stream->width, mCamera3Stream->height, m_bUBWCenable, mIsType);
Thierry Strudelcca4d9c2016-10-20 08:25:53 -07002287 if (streamFormat == CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG)
Thierry Strudel3d639192016-09-09 11:52:26 -07002288 convertMipiToRaw16(super_frame->bufs[0]);
2289 else
2290 convertLegacyToRaw16(super_frame->bufs[0]);
Thierry Strudel3d639192016-09-09 11:52:26 -07002291
Shuzhen Wang48c509a2017-08-07 11:22:33 -07002292 //Make sure cache coherence because extra processing is done
2293 mMemory.cleanCache(super_frame->bufs[0]->buf_idx);
2294 }
Thierry Strudel3d639192016-09-09 11:52:26 -07002295
2296 QCamera3RegularChannel::streamCbRoutine(super_frame, stream);
2297 return;
2298}
2299
2300void QCamera3RawChannel::dumpRawSnapshot(mm_camera_buf_def_t *frame)
2301{
2302 QCamera3Stream *stream = getStreamByIndex(0);
2303 if (stream != NULL) {
2304 char buf[FILENAME_MAX];
2305 memset(buf, 0, sizeof(buf));
2306 cam_dimension_t dim;
2307 memset(&dim, 0, sizeof(dim));
2308 stream->getFrameDimension(dim);
2309
2310 cam_frame_len_offset_t offset;
2311 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2312 stream->getFrameOffset(offset);
2313 snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"r_%d_%dx%d.raw",
2314 frame->frame_idx, offset.mp[0].stride, offset.mp[0].scanline);
2315
2316 int file_fd = open(buf, O_RDWR| O_CREAT, 0644);
2317 if (file_fd >= 0) {
2318 ssize_t written_len = write(file_fd, frame->buffer, frame->frame_len);
2319 LOGD("written number of bytes %zd", written_len);
Thierry Strudel295a0ca2016-11-03 18:38:47 -07002320 frame->cache_flags |= CPU_HAS_READ;
Thierry Strudel3d639192016-09-09 11:52:26 -07002321 close(file_fd);
2322 } else {
2323 LOGE("failed to open file to dump image");
2324 }
2325 } else {
2326 LOGE("Could not find stream");
2327 }
2328
2329}
2330
2331void QCamera3RawChannel::convertLegacyToRaw16(mm_camera_buf_def_t *frame)
2332{
2333 // Convert image buffer from Opaque raw format to RAW16 format
2334 // 10bit Opaque raw is stored in the format of:
2335 // 0000 - p5 - p4 - p3 - p2 - p1 - p0
2336 // where p0 to p5 are 6 pixels (each is 10bit)_and most significant
2337 // 4 bits are 0s. Each 64bit word contains 6 pixels.
2338
2339 QCamera3Stream *stream = getStreamByIndex(0);
2340 if (stream != NULL) {
2341 cam_dimension_t dim;
2342 memset(&dim, 0, sizeof(dim));
2343 stream->getFrameDimension(dim);
2344
2345 cam_frame_len_offset_t offset;
2346 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2347 stream->getFrameOffset(offset);
2348
2349 uint32_t raw16_stride = ((uint32_t)dim.width + 15U) & ~15U;
2350 uint16_t* raw16_buffer = (uint16_t *)frame->buffer;
2351
2352 // In-place format conversion.
2353 // Raw16 format always occupy more memory than opaque raw10.
2354 // Convert to Raw16 by iterating through all pixels from bottom-right
2355 // to top-left of the image.
2356 // One special notes:
2357 // 1. Cross-platform raw16's stride is 16 pixels.
2358 // 2. Opaque raw10's stride is 6 pixels, and aligned to 16 bytes.
2359 for (int32_t ys = dim.height - 1; ys >= 0; ys--) {
2360 uint32_t y = (uint32_t)ys;
2361 uint64_t* row_start = (uint64_t *)frame->buffer +
2362 y * (uint32_t)offset.mp[0].stride_in_bytes / 8;
2363 for (int32_t xs = dim.width - 1; xs >= 0; xs--) {
2364 uint32_t x = (uint32_t)xs;
2365 uint16_t raw16_pixel = 0x3FF & (row_start[x/6] >> (10*(x%6)));
2366 raw16_buffer[y*raw16_stride+x] = raw16_pixel;
2367 }
2368 }
2369 } else {
2370 LOGE("Could not find stream");
2371 }
2372
2373}
2374
2375void QCamera3RawChannel::convertMipiToRaw16(mm_camera_buf_def_t *frame)
2376{
2377 // Convert image buffer from mipi10 raw format to RAW16 format
2378 // mipi10 opaque raw is stored in the format of:
2379 // P3(1:0) P2(1:0) P1(1:0) P0(1:0) P3(9:2) P2(9:2) P1(9:2) P0(9:2)
2380 // 4 pixels occupy 5 bytes, no padding needed
2381
2382 QCamera3Stream *stream = getStreamByIndex(0);
2383 if (stream != NULL) {
2384 cam_dimension_t dim;
2385 memset(&dim, 0, sizeof(dim));
2386 stream->getFrameDimension(dim);
2387
2388 cam_frame_len_offset_t offset;
2389 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2390 stream->getFrameOffset(offset);
2391
2392 uint32_t raw16_stride = ((uint32_t)dim.width + 15U) & ~15U;
2393 uint16_t* raw16_buffer = (uint16_t *)frame->buffer;
2394
2395 // In-place format conversion.
2396 // Raw16 format always occupy more memory than opaque raw10.
2397 // Convert to Raw16 by iterating through all pixels from bottom-right
2398 // to top-left of the image.
2399 // One special notes:
2400 // 1. Cross-platform raw16's stride is 16 pixels.
2401 // 2. mipi raw10's stride is 4 pixels, and aligned to 16 bytes.
2402 for (int32_t ys = dim.height - 1; ys >= 0; ys--) {
2403 uint32_t y = (uint32_t)ys;
2404 uint8_t* row_start = (uint8_t *)frame->buffer +
2405 y * (uint32_t)offset.mp[0].stride_in_bytes;
2406 for (int32_t xs = dim.width - 1; xs >= 0; xs--) {
2407 uint32_t x = (uint32_t)xs;
2408 uint8_t upper_8bit = row_start[5*(x/4)+x%4];
2409 uint8_t lower_2bit = ((row_start[5*(x/4)+4] >> (x%4)) & 0x3);
2410 uint16_t raw16_pixel =
2411 (uint16_t)(((uint16_t)upper_8bit)<<2 |
2412 (uint16_t)lower_2bit);
2413 raw16_buffer[y*raw16_stride+x] = raw16_pixel;
2414 }
2415 }
2416 } else {
2417 LOGE("Could not find stream");
2418 }
2419
2420}
2421
2422/*===========================================================================
2423 * FUNCTION : getReprocessType
2424 *
2425 * DESCRIPTION: get the type of reprocess output supported by this channel
2426 *
2427 * PARAMETERS : NONE
2428 *
2429 * RETURN : reprocess_type_t : type of reprocess
2430 *==========================================================================*/
2431reprocess_type_t QCamera3RawChannel::getReprocessType()
2432{
2433 return REPROCESS_TYPE_RAW;
2434}
2435
2436
2437/*************************************************************************************/
2438// RAW Dump Channel related functions
2439
2440/*===========================================================================
2441 * FUNCTION : QCamera3RawDumpChannel
2442 *
2443 * DESCRIPTION: Constructor for RawDumpChannel
2444 *
2445 * PARAMETERS :
2446 * @cam_handle : Handle for Camera
2447 * @cam_ops : Function pointer table
2448 * @rawDumpSize : Dimensions for the Raw stream
2449 * @paddinginfo : Padding information for stream
2450 * @userData : Cookie for parent
2451 * @pp mask : PP feature mask for this stream
2452 * @numBuffers : number of max dequeued buffers
2453 *
2454 * RETURN : NA
2455 *==========================================================================*/
2456QCamera3RawDumpChannel::QCamera3RawDumpChannel(uint32_t cam_handle,
2457 uint32_t channel_handle,
2458 mm_camera_ops_t *cam_ops,
2459 cam_dimension_t rawDumpSize,
2460 cam_padding_info_t *paddingInfo,
2461 void *userData,
2462 cam_feature_mask_t postprocess_mask, uint32_t numBuffers) :
2463 QCamera3Channel(cam_handle, channel_handle, cam_ops, NULL,
Thierry Strudelc2ee3302016-11-17 12:33:12 -08002464 NULL, paddingInfo, postprocess_mask,
Thierry Strudel3d639192016-09-09 11:52:26 -07002465 userData, numBuffers),
2466 mDim(rawDumpSize),
2467 mMemory(NULL)
2468{
2469 char prop[PROPERTY_VALUE_MAX];
2470 property_get("persist.camera.raw.dump", prop, "0");
2471 mRawDump = atoi(prop);
2472}
2473
2474/*===========================================================================
2475 * FUNCTION : QCamera3RawDumpChannel
2476 *
2477 * DESCRIPTION: Destructor for RawDumpChannel
2478 *
2479 * PARAMETERS :
2480 *
2481 * RETURN : NA
2482 *==========================================================================*/
2483
2484QCamera3RawDumpChannel::~QCamera3RawDumpChannel()
2485{
2486 destroy();
2487}
2488
2489/*===========================================================================
2490 * FUNCTION : dumpRawSnapshot
2491 *
2492 * DESCRIPTION: Helper function to dump Raw frames
2493 *
2494 * PARAMETERS :
2495 * @frame : stream buf frame to be dumped
2496 *
2497 * RETURN : NA
2498 *==========================================================================*/
2499void QCamera3RawDumpChannel::dumpRawSnapshot(mm_camera_buf_def_t *frame)
2500{
2501 QCamera3Stream *stream = getStreamByIndex(0);
2502 if (stream != NULL) {
2503 char buf[FILENAME_MAX];
2504 struct timeval tv;
2505 struct tm timeinfo_data;
2506 struct tm *timeinfo;
2507
2508 cam_dimension_t dim;
2509 memset(&dim, 0, sizeof(dim));
2510 stream->getFrameDimension(dim);
2511
2512 cam_frame_len_offset_t offset;
2513 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2514 stream->getFrameOffset(offset);
2515
2516 gettimeofday(&tv, NULL);
2517 timeinfo = localtime_r(&tv.tv_sec, &timeinfo_data);
2518
2519 if (NULL != timeinfo) {
2520 memset(buf, 0, sizeof(buf));
2521 snprintf(buf, sizeof(buf),
2522 QCAMERA_DUMP_FRM_LOCATION
2523 "%04d-%02d-%02d-%02d-%02d-%02d-%06ld_%d_%dx%d.raw",
2524 timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
2525 timeinfo->tm_mday, timeinfo->tm_hour,
2526 timeinfo->tm_min, timeinfo->tm_sec,tv.tv_usec,
2527 frame->frame_idx, dim.width, dim.height);
2528
2529 int file_fd = open(buf, O_RDWR| O_CREAT, 0777);
2530 if (file_fd >= 0) {
2531 ssize_t written_len =
2532 write(file_fd, frame->buffer, offset.frame_len);
2533 LOGD("written number of bytes %zd", written_len);
Thierry Strudel295a0ca2016-11-03 18:38:47 -07002534 frame->cache_flags |= CPU_HAS_READ;
Thierry Strudel3d639192016-09-09 11:52:26 -07002535 close(file_fd);
2536 } else {
2537 LOGE("failed to open file to dump image");
2538 }
2539 } else {
2540 LOGE("localtime_r() error");
2541 }
2542 } else {
2543 LOGE("Could not find stream");
2544 }
2545
2546}
2547
2548/*===========================================================================
2549 * FUNCTION : streamCbRoutine
2550 *
2551 * DESCRIPTION: Callback routine invoked for each frame generated for
2552 * Rawdump channel
2553 *
2554 * PARAMETERS :
2555 * @super_frame : stream buf frame generated
2556 * @stream : Underlying Stream object cookie
2557 *
2558 * RETURN : NA
2559 *==========================================================================*/
2560void QCamera3RawDumpChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
2561 __unused QCamera3Stream *stream)
2562{
2563 LOGD("E");
2564 if (super_frame == NULL || super_frame->num_bufs != 1) {
2565 LOGE("super_frame is not valid");
2566 return;
2567 }
2568
2569 if (mRawDump)
2570 dumpRawSnapshot(super_frame->bufs[0]);
2571
2572 bufDone(super_frame);
2573 free(super_frame);
2574}
2575
2576/*===========================================================================
2577 * FUNCTION : getStreamBufs
2578 *
2579 * DESCRIPTION: Callback function provided to interface to get buffers.
2580 *
2581 * PARAMETERS :
2582 * @len : Length of each buffer to be allocated
2583 *
2584 * RETURN : NULL on buffer allocation failure
2585 * QCamera3StreamMem object on sucess
2586 *==========================================================================*/
2587QCamera3StreamMem* QCamera3RawDumpChannel::getStreamBufs(uint32_t len)
2588{
2589 int rc;
2590 mMemory = new QCamera3StreamMem(mNumBuffers);
2591
2592 if (!mMemory) {
2593 LOGE("unable to create heap memory");
2594 return NULL;
2595 }
2596 rc = mMemory->allocateAll((size_t)len);
2597 if (rc < 0) {
2598 LOGE("unable to allocate heap memory");
2599 delete mMemory;
2600 mMemory = NULL;
2601 return NULL;
2602 }
2603 return mMemory;
2604}
2605
2606/*===========================================================================
2607 * FUNCTION : putStreamBufs
2608 *
2609 * DESCRIPTION: Callback function provided to interface to return buffers.
2610 * Although no handles are actually returned, implicitl assumption
2611 * that interface will no longer use buffers and channel can
2612 * deallocated if necessary.
2613 *
2614 * PARAMETERS : NA
2615 *
2616 * RETURN : NA
2617 *==========================================================================*/
2618void QCamera3RawDumpChannel::putStreamBufs()
2619{
2620 mMemory->deallocate();
2621 delete mMemory;
2622 mMemory = NULL;
2623}
2624
2625/*===========================================================================
2626 * FUNCTION : request
2627 *
2628 * DESCRIPTION: Request function used as trigger
2629 *
2630 * PARAMETERS :
2631 * @recvd_frame : buffer- this will be NULL since this is internal channel
2632 * @frameNumber : Undefined again since this is internal stream
2633 *
2634 * RETURN : int32_t type of status
2635 * NO_ERROR -- success
2636 * none-zero failure code
2637 *==========================================================================*/
2638int32_t QCamera3RawDumpChannel::request(buffer_handle_t * /*buffer*/,
Thierry Strudelc2ee3302016-11-17 12:33:12 -08002639 uint32_t /*frameNumber*/,
2640 int & /*indexUsed*/)
Thierry Strudel3d639192016-09-09 11:52:26 -07002641{
2642 if (!m_bIsActive) {
2643 return QCamera3Channel::start();
2644 }
2645 else
2646 return 0;
2647}
2648
2649/*===========================================================================
2650 * FUNCTION : intialize
2651 *
2652 * DESCRIPTION: Initializes channel params and creates underlying stream
2653 *
2654 * PARAMETERS :
2655 * @isType : type of image stabilization required on this stream
2656 *
2657 * RETURN : int32_t type of status
2658 * NO_ERROR -- success
2659 * none-zero failure code
2660 *==========================================================================*/
2661int32_t QCamera3RawDumpChannel::initialize(cam_is_type_t isType)
2662{
2663 int32_t rc;
2664
2665 mIsType = isType;
2666 rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_RAW,
2667 CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG, mDim, ROTATE_0, (uint8_t)mNumBuffers,
2668 mPostProcMask, mIsType);
2669 if (rc < 0) {
2670 LOGE("addStream failed");
2671 }
2672 return rc;
2673}
Chien-Yu Chen8e599492016-11-01 13:37:46 -07002674
2675/*************************************************************************************/
2676// HDR+ RAW Source Channel related functions
2677QCamera3HdrPlusRawSrcChannel::QCamera3HdrPlusRawSrcChannel(uint32_t cam_handle,
2678 uint32_t channel_handle,
2679 mm_camera_ops_t *cam_ops,
2680 cam_dimension_t rawDumpSize,
2681 cam_padding_info_t *paddingInfo,
2682 void *userData,
Chien-Yu Chene687bd02016-12-07 18:30:26 -08002683 cam_feature_mask_t postprocess_mask,
2684 std::shared_ptr<HdrPlusClient> hdrPlusClient,
2685 uint32_t hdrPlusStreamId,
2686 uint32_t numBuffers) :
Chien-Yu Chen8e599492016-11-01 13:37:46 -07002687 QCamera3RawDumpChannel(cam_handle, channel_handle, cam_ops, rawDumpSize, paddingInfo, userData,
Chien-Yu Chene687bd02016-12-07 18:30:26 -08002688 postprocess_mask, numBuffers),
2689 mHdrPlusClient(hdrPlusClient),
2690 mHdrPlusStreamId(hdrPlusStreamId)
Chien-Yu Chen8e599492016-11-01 13:37:46 -07002691{
Chien-Yu Chene687bd02016-12-07 18:30:26 -08002692
Chien-Yu Chen8e599492016-11-01 13:37:46 -07002693}
2694
2695QCamera3HdrPlusRawSrcChannel::~QCamera3HdrPlusRawSrcChannel()
2696{
2697}
2698
2699void QCamera3HdrPlusRawSrcChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
2700 __unused QCamera3Stream *stream)
2701{
2702 if (super_frame == NULL || super_frame->num_bufs != 1) {
2703 LOGE("super_frame is not valid");
2704 return;
2705 }
2706
Chien-Yu Chene687bd02016-12-07 18:30:26 -08002707 // Send RAW buffer to HDR+ service
2708 sendRawToHdrPlusService(super_frame->bufs[0]);
Chien-Yu Chen8e599492016-11-01 13:37:46 -07002709
2710 bufDone(super_frame);
2711 free(super_frame);
2712}
2713
Chien-Yu Chene687bd02016-12-07 18:30:26 -08002714void QCamera3HdrPlusRawSrcChannel::sendRawToHdrPlusService(mm_camera_buf_def_t *frame)
2715{
2716 QCamera3Stream *stream = getStreamByIndex(0);
2717 if (stream == nullptr) {
2718 LOGE("%s: Could not find stream.", __FUNCTION__);
2719 return;
2720 }
2721
2722 cam_frame_len_offset_t offset = {};
2723 stream->getFrameOffset(offset);
2724
2725 pbcamera::StreamBuffer buffer;
2726 buffer.streamId = mHdrPlusStreamId;
2727 buffer.data = frame->buffer;
2728 buffer.dataSize = offset.frame_len;
2729
2730 // Use the frame timestamp as mock Easel timestamp.
2731 int64_t mockEaselTimestampNs = (int64_t)frame->ts.tv_sec * 1000000000 + frame->ts.tv_nsec;
2732 mHdrPlusClient->notifyInputBuffer(buffer, mockEaselTimestampNs);
2733}
2734
Thierry Strudel3d639192016-09-09 11:52:26 -07002735/*************************************************************************************/
2736
2737/* QCamera3YUVChannel methods */
2738
2739/*===========================================================================
2740 * FUNCTION : QCamera3YUVChannel
2741 *
2742 * DESCRIPTION: constructor of QCamera3YUVChannel
2743 *
2744 * PARAMETERS :
2745 * @cam_handle : camera handle
2746 * @cam_ops : ptr to camera ops table
2747 * @cb_routine : callback routine to frame aggregator
2748 * @paddingInfo : padding information for the stream
2749 * @stream : camera3_stream_t structure
2750 * @stream_type: Channel stream type
2751 * @postprocess_mask: the postprocess mask for streams of this channel
2752 * @metadataChannel: handle to the metadataChannel
2753 * RETURN : none
2754 *==========================================================================*/
2755QCamera3YUVChannel::QCamera3YUVChannel(uint32_t cam_handle,
2756 uint32_t channel_handle,
2757 mm_camera_ops_t *cam_ops,
2758 channel_cb_routine cb_routine,
Thierry Strudelc2ee3302016-11-17 12:33:12 -08002759 channel_cb_buffer_err cb_buf_err,
Thierry Strudel3d639192016-09-09 11:52:26 -07002760 cam_padding_info_t *paddingInfo,
2761 void *userData,
2762 camera3_stream_t *stream,
2763 cam_stream_type_t stream_type,
2764 cam_feature_mask_t postprocess_mask,
2765 QCamera3Channel *metadataChannel) :
2766 QCamera3ProcessingChannel(cam_handle, channel_handle, cam_ops,
Thierry Strudelc2ee3302016-11-17 12:33:12 -08002767 cb_routine, cb_buf_err, paddingInfo, userData, stream, stream_type,
Thierry Strudel3d639192016-09-09 11:52:26 -07002768 postprocess_mask, metadataChannel)
2769{
2770
2771 mBypass = (postprocess_mask == CAM_QCOM_FEATURE_NONE);
2772 mFrameLen = 0;
2773 mEdgeMode.edge_mode = CAM_EDGE_MODE_OFF;
2774 mEdgeMode.sharpness = 0;
2775 mNoiseRedMode = CAM_NOISE_REDUCTION_MODE_OFF;
2776 memset(&mCropRegion, 0, sizeof(mCropRegion));
2777}
2778
2779/*===========================================================================
2780 * FUNCTION : ~QCamera3YUVChannel
2781 *
2782 * DESCRIPTION: destructor of QCamera3YUVChannel
2783 *
2784 * PARAMETERS : none
2785 *
2786 *
2787 * RETURN : none
2788 *==========================================================================*/
2789QCamera3YUVChannel::~QCamera3YUVChannel()
2790{
2791 // Deallocation of heap buffers allocated in mMemory is freed
2792 // automatically by its destructor
2793}
2794
2795/*===========================================================================
2796 * FUNCTION : initialize
2797 *
2798 * DESCRIPTION: Initialize and add camera channel & stream
2799 *
2800 * PARAMETERS :
2801 * @isType : the image stabilization type
2802 *
2803 * RETURN : int32_t type of status
2804 * NO_ERROR -- success
2805 * none-zero failure code
2806 *==========================================================================*/
2807int32_t QCamera3YUVChannel::initialize(cam_is_type_t isType)
2808{
Thierry Strudele80ad7c2016-12-06 10:16:27 -08002809 ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_YUV_CH_INIT);
Thierry Strudel3d639192016-09-09 11:52:26 -07002810 int32_t rc = NO_ERROR;
2811 cam_dimension_t streamDim;
2812
2813 if (NULL == mCamera3Stream) {
2814 LOGE("Camera stream uninitialized");
2815 return NO_INIT;
2816 }
2817
2818 if (1 <= m_numStreams) {
2819 // Only one stream per channel supported in v3 Hal
2820 return NO_ERROR;
2821 }
2822
2823 mIsType = isType;
Thierry Strudelcca4d9c2016-10-20 08:25:53 -07002824 mStreamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_CALLBACK,
Jason Leec4cf5032017-05-24 18:31:41 -07002825 mCamera3Stream->width, mCamera3Stream->height, m_bUBWCenable, mIsType);
Thierry Strudel3d639192016-09-09 11:52:26 -07002826 streamDim.width = mCamera3Stream->width;
2827 streamDim.height = mCamera3Stream->height;
2828
2829 rc = QCamera3Channel::addStream(mStreamType,
2830 mStreamFormat,
2831 streamDim,
2832 ROTATE_0,
2833 mNumBufs,
2834 mPostProcMask,
2835 mIsType);
2836 if (rc < 0) {
2837 LOGE("addStream failed");
2838 return rc;
2839 }
2840
2841 cam_stream_buf_plane_info_t buf_planes;
2842 cam_padding_info_t paddingInfo = mPaddingInfo;
2843
2844 memset(&buf_planes, 0, sizeof(buf_planes));
2845 //to ensure a big enough buffer size set the height and width
2846 //padding to max(height padding, width padding)
2847 paddingInfo.width_padding = MAX(paddingInfo.width_padding, paddingInfo.height_padding);
2848 paddingInfo.height_padding = paddingInfo.width_padding;
2849
2850 rc = mm_stream_calc_offset_snapshot(mStreamFormat, &streamDim, &paddingInfo,
2851 &buf_planes);
2852 if (rc < 0) {
2853 LOGE("mm_stream_calc_offset_preview failed");
2854 return rc;
2855 }
2856
2857 mFrameLen = buf_planes.plane_info.frame_len;
2858
2859 if (NO_ERROR != rc) {
2860 LOGE("Initialize failed, rc = %d", rc);
2861 return rc;
2862 }
2863
2864 /* initialize offline meta memory for input reprocess */
2865 rc = QCamera3ProcessingChannel::initialize(isType);
2866 if (NO_ERROR != rc) {
2867 LOGE("Processing Channel initialize failed, rc = %d",
2868 rc);
2869 }
2870
2871 return rc;
2872}
2873
2874/*===========================================================================
2875 * FUNCTION : request
2876 *
2877 * DESCRIPTION: entry function for a request on a YUV stream. This function
2878 * has the logic to service a request based on its type
2879 *
2880 * PARAMETERS :
2881 * @buffer : pointer to the output buffer
2882 * @frameNumber : frame number of the request
2883 * @pInputBuffer : pointer to input buffer if an input request
2884 * @metadata : parameters associated with the request
Thierry Strudele80ad7c2016-12-06 10:16:27 -08002885 * @internalreq : boolean to indicate if this is purely internal request
2886 * needing internal buffer allocation
2887 * @meteringonly : boolean indicating metering only frame subset of internal
2888 * not consumed by postprocessor
Thierry Strudel3d639192016-09-09 11:52:26 -07002889 *
2890 * RETURN : 0 on a success start of capture
2891 * -EINVAL on invalid input
2892 * -ENODEV on serious error
2893 *==========================================================================*/
2894int32_t QCamera3YUVChannel::request(buffer_handle_t *buffer,
2895 uint32_t frameNumber,
2896 camera3_stream_buffer_t* pInputBuffer,
Thierry Strudelc2ee3302016-11-17 12:33:12 -08002897 metadata_buffer_t* metadata, bool &needMetadata,
Thierry Strudele80ad7c2016-12-06 10:16:27 -08002898 int &indexUsed,
2899 __unused bool internalRequest = false,
2900 __unused bool meteringOnly = false)
Thierry Strudel3d639192016-09-09 11:52:26 -07002901{
2902 int32_t rc = NO_ERROR;
2903 Mutex::Autolock lock(mOfflinePpLock);
2904
2905 LOGD("pInputBuffer is %p frame number %d", pInputBuffer, frameNumber);
2906 if (NULL == buffer || NULL == metadata) {
2907 LOGE("Invalid buffer/metadata in channel request");
2908 return BAD_VALUE;
2909 }
2910
2911 PpInfo ppInfo;
2912 memset(&ppInfo, 0, sizeof(ppInfo));
2913 ppInfo.frameNumber = frameNumber;
2914 ppInfo.offlinePpFlag = false;
2915 if (mBypass && !pInputBuffer ) {
2916 ppInfo.offlinePpFlag = needsFramePostprocessing(metadata);
2917 ppInfo.output = buffer;
2918 mOfflinePpInfoList.push_back(ppInfo);
2919 }
2920
2921 LOGD("offlinePpFlag is %d", ppInfo.offlinePpFlag);
2922 needMetadata = ppInfo.offlinePpFlag;
2923 if (!ppInfo.offlinePpFlag) {
2924 // regular request
2925 return QCamera3ProcessingChannel::request(buffer, frameNumber,
Thierry Strudelc2ee3302016-11-17 12:33:12 -08002926 pInputBuffer, metadata, indexUsed);
Thierry Strudel3d639192016-09-09 11:52:26 -07002927 } else {
Thierry Strudel3d639192016-09-09 11:52:26 -07002928
2929 //we need to send this frame through the CPP
2930 //Allocate heap memory, then buf done on the buffer
2931 uint32_t bufIdx;
2932 if (mFreeHeapBufferList.empty()) {
2933 rc = mMemory.allocateOne(mFrameLen);
2934 if (rc < 0) {
2935 LOGE("Failed allocating heap buffer. Fatal");
2936 return BAD_VALUE;
2937 } else {
2938 bufIdx = (uint32_t)rc;
2939 }
2940 } else {
2941 bufIdx = *(mFreeHeapBufferList.begin());
2942 mFreeHeapBufferList.erase(mFreeHeapBufferList.begin());
2943 }
2944
2945 /* Configure and start postproc if necessary */
2946 reprocess_config_t reproc_cfg;
2947 cam_dimension_t dim;
2948 memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
2949 memset(&dim, 0, sizeof(dim));
2950 mStreams[0]->getFrameDimension(dim);
2951 setReprocConfig(reproc_cfg, NULL, metadata, mStreamFormat, dim);
2952
2953 // Start postprocessor without input buffer
2954 startPostProc(reproc_cfg);
2955
2956 LOGD("erasing %d", bufIdx);
2957
2958 mMemory.markFrameNumber(bufIdx, frameNumber);
Thierry Strudelc2ee3302016-11-17 12:33:12 -08002959 indexUsed = bufIdx;
Shuzhen Wang3c077d72017-04-20 22:48:59 -07002960 if (m_bIsActive) {
2961 mStreams[0]->bufDone(bufIdx);
2962 }
Thierry Strudel3d639192016-09-09 11:52:26 -07002963
2964 }
2965 return rc;
2966}
2967
2968/*===========================================================================
2969 * FUNCTION : streamCbRoutine
2970 *
2971 * DESCRIPTION:
2972 *
2973 * PARAMETERS :
2974 * @super_frame : the super frame with filled buffer
2975 * @stream : stream on which the buffer was requested and filled
2976 *
2977 * RETURN : none
2978 *==========================================================================*/
2979void QCamera3YUVChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
2980 QCamera3Stream *stream)
2981{
Thierry Strudele80ad7c2016-12-06 10:16:27 -08002982 ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_YUV_CH_STRM_CB);
Thierry Strudel3d639192016-09-09 11:52:26 -07002983 uint8_t frameIndex;
2984 int32_t resultFrameNumber;
2985
2986 if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
2987 LOGE("Error with the stream callback");
2988 return;
2989 }
2990
2991 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
2992 if(frameIndex >= mNumBufs) {
2993 LOGE("Error, Invalid index for buffer");
2994 stream->bufDone(frameIndex);
2995 return;
2996 }
2997
2998 if (mBypass) {
Emilian Peev37ca0b42017-06-29 18:24:40 -07002999 {
3000 List<PpInfo>::iterator ppInfo;
Thierry Strudel3d639192016-09-09 11:52:26 -07003001
Emilian Peev37ca0b42017-06-29 18:24:40 -07003002 Mutex::Autolock lock(mOfflinePpLock);
3003 resultFrameNumber = mMemory.getFrameNumber(frameIndex);
3004 for (ppInfo = mOfflinePpInfoList.begin();
3005 ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
3006 if (ppInfo->frameNumber == (uint32_t)resultFrameNumber) {
3007 break;
3008 }
Thierry Strudel3d639192016-09-09 11:52:26 -07003009 }
Emilian Peev37ca0b42017-06-29 18:24:40 -07003010 LOGD("frame index %d, frame number %d", frameIndex,
3011 resultFrameNumber);
3012 //check the reprocessing required flag against the frame number
3013 if (ppInfo == mOfflinePpInfoList.end()) {
3014 LOGE("Error, request for frame number is a reprocess.");
3015 stream->bufDone(frameIndex);
3016 return;
3017 }
3018
3019 if (ppInfo->offlinePpFlag) {
3020 mm_camera_super_buf_t *frame =
3021 (mm_camera_super_buf_t *)malloc(sizeof(
3022 mm_camera_super_buf_t));
3023 if (frame == NULL) {
3024 LOGE("Error allocating memory to save received_frame structure.");
3025 if(stream) {
3026 stream->bufDone(frameIndex);
3027 }
3028 return;
3029 }
3030
3031 *frame = *super_frame;
3032 m_postprocessor.processData(frame, ppInfo->output,
3033 resultFrameNumber);
3034 free(super_frame);
3035 return;
3036 } else {
3037 if (ppInfo != mOfflinePpInfoList.begin()) {
3038 // There is pending reprocess buffer, cache current buffer
3039 if (ppInfo->callback_buffer != NULL) {
3040 LOGE("Fatal: cached callback_buffer is already present");
3041 }
3042 ppInfo->callback_buffer = super_frame;
3043 return;
3044 } else {
3045 mOfflinePpInfoList.erase(ppInfo);
3046 }
3047 }
Thierry Strudel3d639192016-09-09 11:52:26 -07003048 }
3049
Thierry Strudelc2ee3302016-11-17 12:33:12 -08003050 if (IS_BUFFER_ERROR(super_frame->bufs[0]->flags)) {
3051 mChannelCbBufErr(this, resultFrameNumber,
Emilian Peev37ca0b42017-06-29 18:24:40 -07003052 CAMERA3_BUFFER_STATUS_ERROR, mUserData);
Thierry Strudel3d639192016-09-09 11:52:26 -07003053 }
3054 }
3055
3056 QCamera3ProcessingChannel::streamCbRoutine(super_frame, stream);
Thierry Strudelc2ee3302016-11-17 12:33:12 -08003057
3058 /* return any pending buffers that were received out of order earlier */
3059 while((super_frame = getNextPendingCbBuffer())) {
3060 QCamera3ProcessingChannel::streamCbRoutine(super_frame, stream);
3061 }
3062
Thierry Strudel3d639192016-09-09 11:52:26 -07003063 return;
3064}
3065
3066/*===========================================================================
Thierry Strudelc2ee3302016-11-17 12:33:12 -08003067 * FUNCTION : getNextPendingCbBuffer
3068 *
3069 * DESCRIPTION: Returns the callback_buffer from the first entry of
3070 * mOfflinePpInfoList
3071 *
3072 * PARAMETERS : none
3073 *
3074 * RETURN : callback_buffer
3075 *==========================================================================*/
3076mm_camera_super_buf_t* QCamera3YUVChannel::getNextPendingCbBuffer() {
3077 mm_camera_super_buf_t* super_frame = NULL;
3078 if (mOfflinePpInfoList.size()) {
3079 if ((super_frame = mOfflinePpInfoList.begin()->callback_buffer)) {
3080 mOfflinePpInfoList.erase(mOfflinePpInfoList.begin());
3081 }
3082 }
3083 return super_frame;
3084}
3085
3086/*===========================================================================
Thierry Strudel3d639192016-09-09 11:52:26 -07003087 * FUNCTION : reprocessCbRoutine
3088 *
3089 * DESCRIPTION: callback function for the reprocessed frame. This frame now
3090 * should be returned to the framework. This same callback is
3091 * used during input reprocessing or offline postprocessing
3092 *
3093 * PARAMETERS :
3094 * @resultBuffer : buffer containing the reprocessed data
3095 * @resultFrameNumber : frame number on which the buffer was requested
3096 *
3097 * RETURN : NONE
3098 *
3099 *==========================================================================*/
3100void QCamera3YUVChannel::reprocessCbRoutine(buffer_handle_t *resultBuffer,
3101 uint32_t resultFrameNumber)
3102{
3103 LOGD("E: frame number %d", resultFrameNumber);
3104 Vector<mm_camera_super_buf_t *> pendingCbs;
3105
3106 /* release the input buffer and input metadata buffer if used */
3107 if (0 > mMemory.getHeapBufferIndex(resultFrameNumber)) {
3108 /* mOfflineMemory and mOfflineMetaMemory used only for input reprocessing */
3109 int32_t rc = releaseOfflineMemory(resultFrameNumber);
3110 if (NO_ERROR != rc) {
3111 LOGE("Error releasing offline memory rc = %d", rc);
3112 }
3113 /* Since reprocessing is done, send the callback to release the input buffer */
3114 if (mChannelCB) {
3115 mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
3116 }
3117 }
3118
3119 if (mBypass) {
3120 int32_t rc = handleOfflinePpCallback(resultFrameNumber, pendingCbs);
3121 if (rc != NO_ERROR) {
3122 return;
3123 }
3124 }
3125
3126 issueChannelCb(resultBuffer, resultFrameNumber);
3127
3128 // Call all pending callbacks to return buffers
3129 for (size_t i = 0; i < pendingCbs.size(); i++) {
3130 QCamera3ProcessingChannel::streamCbRoutine(
3131 pendingCbs[i], mStreams[0]);
3132 }
3133
3134}
3135
3136/*===========================================================================
3137 * FUNCTION : needsFramePostprocessing
3138 *
3139 * DESCRIPTION:
3140 *
3141 * PARAMETERS :
3142 *
3143 * RETURN :
3144 * TRUE if frame needs to be postprocessed
3145 * FALSE is frame does not need to be postprocessed
3146 *
3147 *==========================================================================*/
3148bool QCamera3YUVChannel::needsFramePostprocessing(metadata_buffer_t *meta)
3149{
3150 bool ppNeeded = false;
3151
3152 //sharpness
3153 IF_META_AVAILABLE(cam_edge_application_t, edgeMode,
3154 CAM_INTF_META_EDGE_MODE, meta) {
3155 mEdgeMode = *edgeMode;
3156 }
3157
3158 //wnr
3159 IF_META_AVAILABLE(uint32_t, noiseRedMode,
3160 CAM_INTF_META_NOISE_REDUCTION_MODE, meta) {
3161 mNoiseRedMode = *noiseRedMode;
3162 }
3163
3164 //crop region
3165 IF_META_AVAILABLE(cam_crop_region_t, scalerCropRegion,
3166 CAM_INTF_META_SCALER_CROP_REGION, meta) {
3167 mCropRegion = *scalerCropRegion;
3168 }
3169
3170 if ((CAM_EDGE_MODE_OFF != mEdgeMode.edge_mode) &&
3171 (CAM_EDGE_MODE_ZERO_SHUTTER_LAG != mEdgeMode.edge_mode)) {
3172 ppNeeded = true;
3173 }
3174 if ((CAM_NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG != mNoiseRedMode) &&
3175 (CAM_NOISE_REDUCTION_MODE_OFF != mNoiseRedMode) &&
3176 (CAM_NOISE_REDUCTION_MODE_MINIMAL != mNoiseRedMode)) {
3177 ppNeeded = true;
3178 }
3179 if ((mCropRegion.width < (int32_t)mCamera3Stream->width) ||
3180 (mCropRegion.height < (int32_t)mCamera3Stream->height)) {
3181 ppNeeded = true;
3182 }
3183
3184 return ppNeeded;
3185}
3186
3187/*===========================================================================
3188 * FUNCTION : handleOfflinePpCallback
3189 *
3190 * DESCRIPTION: callback function for the reprocessed frame from offline
3191 * postprocessing.
3192 *
3193 * PARAMETERS :
3194 * @resultFrameNumber : frame number on which the buffer was requested
3195 * @pendingCbs : pending buffers to be returned first
3196 *
3197 * RETURN : int32_t type of status
3198 * NO_ERROR -- success
3199 * none-zero failure code
3200 *==========================================================================*/
3201int32_t QCamera3YUVChannel::handleOfflinePpCallback(uint32_t resultFrameNumber,
3202 Vector<mm_camera_super_buf_t *>& pendingCbs)
3203{
3204 Mutex::Autolock lock(mOfflinePpLock);
3205 List<PpInfo>::iterator ppInfo;
3206
3207 for (ppInfo = mOfflinePpInfoList.begin();
3208 ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
3209 if (ppInfo->frameNumber == resultFrameNumber) {
3210 break;
3211 }
3212 }
3213
3214 if (ppInfo == mOfflinePpInfoList.end()) {
3215 LOGI("Request of frame number %d is reprocessing",
3216 resultFrameNumber);
3217 return NO_ERROR;
3218 } else if (ppInfo != mOfflinePpInfoList.begin()) {
3219 LOGE("callback for frame number %d should be head of list",
3220 resultFrameNumber);
3221 return BAD_VALUE;
3222 }
3223
3224 if (ppInfo->offlinePpFlag) {
3225 // Need to get the input buffer frame index from the
3226 // mMemory object and add that to the free heap buffers list.
3227 int32_t bufferIndex =
3228 mMemory.getHeapBufferIndex(resultFrameNumber);
3229 if (bufferIndex < 0) {
3230 LOGE("Fatal %d: no buffer index for frame number %d",
3231 bufferIndex, resultFrameNumber);
3232 return BAD_VALUE;
3233 }
Thierry Strudel9e74aae2016-09-22 17:10:18 -07003234 mMemory.markFrameNumber(bufferIndex, -1);
Thierry Strudelc2ee3302016-11-17 12:33:12 -08003235 mFreeHeapBufferList.push_back(bufferIndex);
Thierry Strudel9e74aae2016-09-22 17:10:18 -07003236 //Move heap buffer into free pool and invalidate the frame number
Thierry Strudel3d639192016-09-09 11:52:26 -07003237 ppInfo = mOfflinePpInfoList.erase(ppInfo);
3238
Thierry Strudelc2ee3302016-11-17 12:33:12 -08003239 /* return any pending buffers that were received out of order
3240 earlier */
3241 mm_camera_super_buf_t* super_frame;
3242 while((super_frame = getNextPendingCbBuffer())) {
3243 pendingCbs.push_back(super_frame);
Thierry Strudel3d639192016-09-09 11:52:26 -07003244 }
Thierry Strudel3d639192016-09-09 11:52:26 -07003245 } else {
3246 LOGE("Fatal: request of frame number %d doesn't need"
3247 " offline postprocessing. However there is"
3248 " reprocessing callback.",
3249 resultFrameNumber);
3250 return BAD_VALUE;
3251 }
3252
3253 return NO_ERROR;
3254}
3255
3256/*===========================================================================
3257 * FUNCTION : getReprocessType
3258 *
3259 * DESCRIPTION: get the type of reprocess output supported by this channel
3260 *
3261 * PARAMETERS : NONE
3262 *
3263 * RETURN : reprocess_type_t : type of reprocess
3264 *==========================================================================*/
3265reprocess_type_t QCamera3YUVChannel::getReprocessType()
3266{
3267 return REPROCESS_TYPE_YUV;
3268}
3269
3270/* QCamera3PicChannel methods */
3271
3272/*===========================================================================
3273 * FUNCTION : jpegEvtHandle
3274 *
3275 * DESCRIPTION: Function registerd to mm-jpeg-interface to handle jpeg events.
3276 Construct result payload and call mChannelCb to deliver buffer
3277 to framework.
3278 *
3279 * PARAMETERS :
3280 * @status : status of jpeg job
3281 * @client_hdl: jpeg client handle
3282 * @jobId : jpeg job Id
3283 * @p_ouput : ptr to jpeg output result struct
3284 * @userdata : user data ptr
3285 *
3286 * RETURN : none
3287 *==========================================================================*/
3288void QCamera3PicChannel::jpegEvtHandle(jpeg_job_status_t status,
3289 uint32_t /*client_hdl*/,
3290 uint32_t jobId,
3291 mm_jpeg_output_t *p_output,
3292 void *userdata)
3293{
Thierry Strudele80ad7c2016-12-06 10:16:27 -08003294 ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_PIC_CH_JPEG_EVT_HANDLE);
Thierry Strudel3d639192016-09-09 11:52:26 -07003295 buffer_handle_t *resultBuffer = NULL;
3296 buffer_handle_t *jpegBufferHandle = NULL;
3297 int resultStatus = CAMERA3_BUFFER_STATUS_OK;
3298 camera3_stream_buffer_t result;
3299 camera3_jpeg_blob_t jpegHeader;
3300
Thierry Strudel3d639192016-09-09 11:52:26 -07003301 QCamera3PicChannel *obj = (QCamera3PicChannel *)userdata;
3302 if (obj) {
3303 //Construct payload for process_capture_result. Call mChannelCb
3304
3305 qcamera_hal3_jpeg_data_t *job = obj->m_postprocessor.findJpegJobByJobId(jobId);
3306
3307 if ((job == NULL) || (status == JPEG_JOB_STATUS_ERROR)) {
3308 LOGE("Error in jobId: (%d) with status: %d", jobId, status);
3309 resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
3310 }
3311
3312 if (NULL != job) {
3313 uint32_t bufIdx = (uint32_t)job->jpeg_settings->out_buf_index;
3314 LOGD("jpeg out_buf_index: %d", bufIdx);
3315
3316 //Construct jpeg transient header of type camera3_jpeg_blob_t
3317 //Append at the end of jpeg image of buf_filled_len size
3318
3319 jpegHeader.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
3320 if (JPEG_JOB_STATUS_DONE == status) {
3321 jpegHeader.jpeg_size = (uint32_t)p_output->buf_filled_len;
3322 char* jpeg_buf = (char *)p_output->buf_vaddr;
Thierry Strudelcca4d9c2016-10-20 08:25:53 -07003323 cam_frame_len_offset_t offset;
3324 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
3325 mm_camera_buf_def_t *jpeg_dump_buffer = NULL;
3326 cam_dimension_t dim;
3327 dim.width = obj->mCamera3Stream->width;
3328 dim.height = obj->mCamera3Stream->height;
3329 jpeg_dump_buffer = (mm_camera_buf_def_t *)malloc(sizeof(mm_camera_buf_def_t));
3330 if(!jpeg_dump_buffer) {
3331 LOGE("Could not allocate jpeg dump buffer");
3332 } else {
3333 jpeg_dump_buffer->buffer = p_output->buf_vaddr;
3334 jpeg_dump_buffer->frame_len = p_output->buf_filled_len;
3335 jpeg_dump_buffer->frame_idx = obj->mMemory.getFrameNumber(bufIdx);
3336 obj->dumpYUV(jpeg_dump_buffer, dim, offset, QCAMERA_DUMP_FRM_OUTPUT_JPEG);
3337 free(jpeg_dump_buffer);
3338 }
Thierry Strudel3d639192016-09-09 11:52:26 -07003339
3340 ssize_t maxJpegSize = -1;
3341
3342 // Gralloc buffer may have additional padding for 4K page size
3343 // Follow size guidelines based on spec since framework relies
3344 // on that to reach end of buffer and with it the header
3345
3346 //Handle same as resultBuffer, but for readablity
3347 jpegBufferHandle =
3348 (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx);
3349
3350 if (NULL != jpegBufferHandle) {
3351 maxJpegSize = ((private_handle_t*)(*jpegBufferHandle))->width;
3352 if (maxJpegSize > obj->mMemory.getSize(bufIdx)) {
3353 maxJpegSize = obj->mMemory.getSize(bufIdx);
3354 }
3355
3356 size_t jpeg_eof_offset =
3357 (size_t)(maxJpegSize - (ssize_t)sizeof(jpegHeader));
3358 char *jpeg_eof = &jpeg_buf[jpeg_eof_offset];
3359 memcpy(jpeg_eof, &jpegHeader, sizeof(jpegHeader));
3360 obj->mMemory.cleanInvalidateCache(bufIdx);
3361 } else {
3362 LOGE("JPEG buffer not found and index: %d",
3363 bufIdx);
3364 resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
3365 }
3366 }
3367
3368 ////Use below data to issue framework callback
3369 resultBuffer =
3370 (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx);
3371 int32_t resultFrameNumber = obj->mMemory.getFrameNumber(bufIdx);
3372 int32_t rc = obj->mMemory.unregisterBuffer(bufIdx);
3373 if (NO_ERROR != rc) {
3374 LOGE("Error %d unregistering stream buffer %d",
3375 rc, bufIdx);
3376 }
3377
3378 result.stream = obj->mCamera3Stream;
3379 result.buffer = resultBuffer;
3380 result.status = resultStatus;
3381 result.acquire_fence = -1;
3382 result.release_fence = -1;
3383
3384 // Release any snapshot buffers before calling
3385 // the user callback. The callback can potentially
3386 // unblock pending requests to snapshot stream.
3387 int32_t snapshotIdx = -1;
3388 mm_camera_super_buf_t* src_frame = NULL;
3389
3390 if (job->src_reproc_frame)
3391 src_frame = job->src_reproc_frame;
3392 else
3393 src_frame = job->src_frame;
3394
3395 if (src_frame) {
3396 if (obj->mStreams[0]->getMyHandle() ==
3397 src_frame->bufs[0]->stream_id) {
3398 snapshotIdx = (int32_t)src_frame->bufs[0]->buf_idx;
Shuzhen Wang72c75ca2016-03-08 14:25:06 -08003399 if (0 <= snapshotIdx) {
3400 Mutex::Autolock lock(obj->mFreeBuffersLock);
3401 obj->mFreeBufferList.push_back((uint32_t)snapshotIdx);
3402 }
Thierry Strudel3d639192016-09-09 11:52:26 -07003403 }
3404 }
Thierry Strudel3d639192016-09-09 11:52:26 -07003405
3406 LOGI("Issue Jpeg Callback frameNumber = %d status = %d",
3407 resultFrameNumber, resultStatus);
Shuzhen Wang850a7c22017-05-02 14:48:23 -07003408 ATRACE_ASYNC_END("SNAPSHOT", resultFrameNumber);
Thierry Strudel3d639192016-09-09 11:52:26 -07003409 if (obj->mChannelCB) {
3410 obj->mChannelCB(NULL,
3411 &result,
3412 (uint32_t)resultFrameNumber,
3413 false,
3414 obj->mUserData);
3415 }
3416
3417 // release internal data for jpeg job
3418 if ((NULL != job->fwk_frame) || (NULL != job->fwk_src_buffer)) {
3419 /* unregister offline input buffer */
3420 int32_t inputBufIndex =
3421 obj->mOfflineMemory.getGrallocBufferIndex((uint32_t)resultFrameNumber);
3422 if (0 <= inputBufIndex) {
3423 rc = obj->mOfflineMemory.unregisterBuffer(inputBufIndex);
3424 } else {
3425 LOGE("could not find the input buf index, frame number %d",
3426 resultFrameNumber);
3427 }
3428 if (NO_ERROR != rc) {
3429 LOGE("Error %d unregistering input buffer %d",
3430 rc, bufIdx);
3431 }
3432
3433 /* unregister offline meta buffer */
3434 int32_t metaBufIndex =
3435 obj->mOfflineMetaMemory.getHeapBufferIndex((uint32_t)resultFrameNumber);
3436 if (0 <= metaBufIndex) {
3437 Mutex::Autolock lock(obj->mFreeOfflineMetaBuffersLock);
3438 obj->mFreeOfflineMetaBuffersList.push_back((uint32_t)metaBufIndex);
3439 } else {
3440 LOGE("could not find the input meta buf index, frame number %d",
3441 resultFrameNumber);
3442 }
3443 }
3444 obj->m_postprocessor.releaseOfflineBuffers(false);
3445 obj->m_postprocessor.releaseJpegJobData(job);
3446 free(job);
3447 }
3448
3449 return;
3450 // }
3451 } else {
3452 LOGE("Null userdata in jpeg callback");
3453 }
3454}
3455
3456QCamera3PicChannel::QCamera3PicChannel(uint32_t cam_handle,
3457 uint32_t channel_handle,
3458 mm_camera_ops_t *cam_ops,
3459 channel_cb_routine cb_routine,
Thierry Strudelc2ee3302016-11-17 12:33:12 -08003460 channel_cb_buffer_err cb_buf_err,
Thierry Strudel3d639192016-09-09 11:52:26 -07003461 cam_padding_info_t *paddingInfo,
3462 void *userData,
3463 camera3_stream_t *stream,
3464 cam_feature_mask_t postprocess_mask,
3465 __unused bool is4KVideo,
3466 bool isInputStreamConfigured,
3467 QCamera3Channel *metadataChannel,
3468 uint32_t numBuffers) :
3469 QCamera3ProcessingChannel(cam_handle, channel_handle,
Thierry Strudelc2ee3302016-11-17 12:33:12 -08003470 cam_ops, cb_routine, cb_buf_err, paddingInfo, userData,
Thierry Strudel3d639192016-09-09 11:52:26 -07003471 stream, CAM_STREAM_TYPE_SNAPSHOT,
3472 postprocess_mask, metadataChannel, numBuffers),
3473 mNumSnapshotBufs(0),
3474 mInputBufferHint(isInputStreamConfigured),
3475 mYuvMemory(NULL),
3476 mFrameLen(0)
3477{
3478 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
3479 m_max_pic_dim = hal_obj->calcMaxJpegDim();
3480 mYuvWidth = stream->width;
3481 mYuvHeight = stream->height;
3482 mStreamType = CAM_STREAM_TYPE_SNAPSHOT;
3483 // Use same pixelformat for 4K video case
Thierry Strudelcca4d9c2016-10-20 08:25:53 -07003484 mStreamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_SNAPSHOT,
Jason Leec4cf5032017-05-24 18:31:41 -07003485 stream->width, stream->height, m_bUBWCenable, IS_TYPE_NONE);
Thierry Strudel3d639192016-09-09 11:52:26 -07003486 int32_t rc = m_postprocessor.initJpeg(jpegEvtHandle, &m_max_pic_dim, this);
3487 if (rc != 0) {
3488 LOGE("Init Postprocessor failed");
3489 }
3490}
3491
3492/*===========================================================================
3493 * FUNCTION : flush
3494 *
3495 * DESCRIPTION: flush pic channel, which will stop all processing within, including
3496 * the reprocessing channel in postprocessor and YUV stream.
3497 *
3498 * PARAMETERS : none
3499 *
3500 * RETURN : int32_t type of status
3501 * NO_ERROR -- success
3502 * none-zero failure code
3503 *==========================================================================*/
3504int32_t QCamera3PicChannel::flush()
3505{
3506 int32_t rc = NO_ERROR;
3507 if(!m_bIsActive) {
3508 LOGE("Attempt to flush inactive channel");
3509 return NO_INIT;
3510 }
3511
3512 rc = m_postprocessor.flush();
3513 if (rc == 0) {
3514 LOGE("Postprocessor flush failed, rc = %d", rc);
3515 return rc;
3516 }
3517
3518 if (0 < mOfflineMetaMemory.getCnt()) {
3519 mOfflineMetaMemory.deallocate();
3520 }
3521 if (0 < mOfflineMemory.getCnt()) {
3522 mOfflineMemory.unregisterBuffers();
3523 }
3524 Mutex::Autolock lock(mFreeBuffersLock);
3525 mFreeBufferList.clear();
Thierry Strudele80ad7c2016-12-06 10:16:27 -08003526
Thierry Strudel3d639192016-09-09 11:52:26 -07003527 for (uint32_t i = 0; i < mCamera3Stream->max_buffers; i++) {
3528 mFreeBufferList.push_back(i);
3529 }
3530 return rc;
3531}
3532
3533
3534QCamera3PicChannel::~QCamera3PicChannel()
3535{
Shuzhen Wang3c077d72017-04-20 22:48:59 -07003536 if (mYuvMemory != nullptr) {
3537 mYuvMemory->deallocate();
3538 delete mYuvMemory;
3539 mYuvMemory = nullptr;
3540 }
Thierry Strudel3d639192016-09-09 11:52:26 -07003541}
3542
Chien-Yu Chene687bd02016-12-07 18:30:26 -08003543/*===========================================================================
3544 * FUNCTION : metadataBufDone
3545 *
3546 * DESCRIPTION: Buffer done method for a metadata buffer
3547 *
3548 * PARAMETERS :
3549 * @recvd_frame : received metadata frame
3550 *
3551 * RETURN : int32_t type of status
3552 * OK -- success
3553 * none-zero failure code
3554 *==========================================================================*/
3555int32_t QCamera3PicChannel::metadataBufDone(mm_camera_super_buf_t *recvd_frame)
3556{
3557 // Check if this is an external metadata
3558 if (recvd_frame != nullptr && recvd_frame->num_bufs == 1) {
3559 Mutex::Autolock lock(mPendingExternalMetadataLock);
3560 auto iter = mPendingExternalMetadata.begin();
3561 while (iter != mPendingExternalMetadata.end()) {
3562 if (iter->get() == recvd_frame->bufs[0]->buffer) {
3563 // Remove the metadata allocated externally.
3564 mPendingExternalMetadata.erase(iter);
3565 return OK;
3566 }
3567
3568 iter++;
3569 }
3570 }
3571
3572 // If this is not an external metadata, return the metadata.
3573 return QCamera3ProcessingChannel::metadataBufDone(recvd_frame);
3574}
3575
Thierry Strudel3d639192016-09-09 11:52:26 -07003576int32_t QCamera3PicChannel::initialize(cam_is_type_t isType)
3577{
3578 int32_t rc = NO_ERROR;
3579 cam_dimension_t streamDim;
3580 cam_stream_type_t streamType;
3581 cam_format_t streamFormat;
3582
3583 if (NULL == mCamera3Stream) {
3584 LOGE("Camera stream uninitialized");
3585 return NO_INIT;
3586 }
3587
3588 if (1 <= m_numStreams) {
3589 // Only one stream per channel supported in v3 Hal
3590 return NO_ERROR;
3591 }
3592
3593 mIsType = isType;
3594 streamType = mStreamType;
3595 streamFormat = mStreamFormat;
3596 streamDim.width = (int32_t)mYuvWidth;
3597 streamDim.height = (int32_t)mYuvHeight;
3598
3599 mNumSnapshotBufs = mCamera3Stream->max_buffers;
3600 rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
3601 ROTATE_0, (uint8_t)mCamera3Stream->max_buffers, mPostProcMask,
3602 mIsType);
3603
3604 if (NO_ERROR != rc) {
3605 LOGE("Initialize failed, rc = %d", rc);
3606 return rc;
3607 }
3608
Shuzhen Wang3c077d72017-04-20 22:48:59 -07003609 mYuvMemory = new QCamera3StreamMem(mCamera3Stream->max_buffers);
3610 if (!mYuvMemory) {
3611 LOGE("unable to create YUV buffers");
3612 return NO_MEMORY;
3613 }
3614 cam_stream_buf_plane_info_t buf_planes;
3615 cam_padding_info_t paddingInfo = mPaddingInfo;
3616
3617 memset(&buf_planes, 0, sizeof(buf_planes));
3618 //to ensure a big enough buffer size set the height and width
3619 //padding to max(height padding, width padding)
3620 paddingInfo.width_padding = MAX(paddingInfo.width_padding, paddingInfo.height_padding);
3621 paddingInfo.height_padding = paddingInfo.width_padding;
3622
3623 rc = mm_stream_calc_offset_snapshot(mStreamFormat, &streamDim, &paddingInfo,
3624 &buf_planes);
3625 if (rc < 0) {
3626 LOGE("mm_stream_calc_offset_preview failed");
3627 return rc;
3628 }
3629 mFrameLen = buf_planes.plane_info.frame_len;
3630
Thierry Strudel3d639192016-09-09 11:52:26 -07003631 /* initialize offline meta memory for input reprocess */
3632 rc = QCamera3ProcessingChannel::initialize(isType);
3633 if (NO_ERROR != rc) {
3634 LOGE("Processing Channel initialize failed, rc = %d",
3635 rc);
3636 }
3637
3638 return rc;
3639}
3640
3641/*===========================================================================
3642 * FUNCTION : request
3643 *
3644 * DESCRIPTION: handle the request - either with an input buffer or a direct
3645 * output request
3646 *
3647 * PARAMETERS :
3648 * @buffer : pointer to the output buffer
3649 * @frameNumber : frame number of the request
3650 * @pInputBuffer : pointer to input buffer if an input request
3651 * @metadata : parameters associated with the request
Thierry Strudele80ad7c2016-12-06 10:16:27 -08003652 * @internalreq : boolean to indicate if this is purely internal request
3653 * needing internal buffer allocation
3654 * @meteringonly : boolean indicating metering only frame subset of internal
3655 * not consumed by postprocessor
Thierry Strudel3d639192016-09-09 11:52:26 -07003656 *
3657 * RETURN : 0 on a success start of capture
3658 * -EINVAL on invalid input
3659 * -ENODEV on serious error
3660 *==========================================================================*/
3661int32_t QCamera3PicChannel::request(buffer_handle_t *buffer,
3662 uint32_t frameNumber,
3663 camera3_stream_buffer_t *pInputBuffer,
Thierry Strudele80ad7c2016-12-06 10:16:27 -08003664 metadata_buffer_t *metadata, int &indexUsed,
3665 bool internalRequest, bool meteringOnly)
Thierry Strudel3d639192016-09-09 11:52:26 -07003666{
Thierry Strudele80ad7c2016-12-06 10:16:27 -08003667 ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_PIC_CH_REQ);
Thierry Strudel3d639192016-09-09 11:52:26 -07003668 //FIX ME: Return buffer back in case of failures below.
3669
3670 int32_t rc = NO_ERROR;
3671
3672 reprocess_config_t reproc_cfg;
3673 cam_dimension_t dim;
3674 memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
3675 //make sure to set the correct input stream dim in case of YUV size override
3676 //and recalculate the plane info
3677 dim.width = (int32_t)mYuvWidth;
3678 dim.height = (int32_t)mYuvHeight;
Thierry Strudele80ad7c2016-12-06 10:16:27 -08003679
Thierry Strudel3d639192016-09-09 11:52:26 -07003680 setReprocConfig(reproc_cfg, pInputBuffer, metadata, mStreamFormat, dim);
3681
Thierry Strudel3d639192016-09-09 11:52:26 -07003682 // Start postprocessor
3683 startPostProc(reproc_cfg);
3684
Thierry Strudele80ad7c2016-12-06 10:16:27 -08003685 if (!internalRequest) {
3686 int index = mMemory.getMatchBufIndex((void*)buffer);
3687
3688 if(index < 0) {
3689 rc = registerBuffer(buffer, mIsType);
3690 if (NO_ERROR != rc) {
3691 LOGE("On-the-fly buffer registration failed %d",
3692 rc);
3693 return rc;
3694 }
3695
3696 index = mMemory.getMatchBufIndex((void*)buffer);
3697 if (index < 0) {
3698 LOGE("Could not find object among registered buffers");
3699 return DEAD_OBJECT;
3700 }
3701 }
3702 LOGD("buffer index %d, frameNumber: %u", index, frameNumber);
3703
3704 rc = mMemory.markFrameNumber((uint32_t)index, frameNumber);
3705
3706 // Queue jpeg settings
3707 rc = queueJpegSetting((uint32_t)index, metadata);
3708
3709 } else {
3710 LOGD("Internal request @ Picchannel");
3711 }
3712
Thierry Strudel3d639192016-09-09 11:52:26 -07003713
3714 if (pInputBuffer == NULL) {
3715 Mutex::Autolock lock(mFreeBuffersLock);
3716 uint32_t bufIdx;
3717 if (mFreeBufferList.empty()) {
Chien-Yu Chen367f2cb2017-08-24 15:08:21 -07003718 rc = mYuvMemory->allocateOne(mFrameLen, /*isCached*/false);
Thierry Strudel3d639192016-09-09 11:52:26 -07003719 if (rc < 0) {
3720 LOGE("Failed to allocate heap buffer. Fatal");
3721 return rc;
3722 } else {
3723 bufIdx = (uint32_t)rc;
3724 }
3725 } else {
3726 List<uint32_t>::iterator it = mFreeBufferList.begin();
3727 bufIdx = *it;
3728 mFreeBufferList.erase(it);
3729 }
Thierry Strudele80ad7c2016-12-06 10:16:27 -08003730 if (meteringOnly) {
3731 mYuvMemory->markFrameNumber(bufIdx, 0xFFFFFFFF);
3732 } else {
3733 mYuvMemory->markFrameNumber(bufIdx, frameNumber);
3734 }
Shuzhen Wang3c077d72017-04-20 22:48:59 -07003735 if (m_bIsActive) {
3736 mStreams[0]->bufDone(bufIdx);
3737 }
Thierry Strudelc2ee3302016-11-17 12:33:12 -08003738 indexUsed = bufIdx;
Thierry Strudel3d639192016-09-09 11:52:26 -07003739 } else {
3740 qcamera_fwk_input_pp_data_t *src_frame = NULL;
3741 src_frame = (qcamera_fwk_input_pp_data_t *)calloc(1,
3742 sizeof(qcamera_fwk_input_pp_data_t));
3743 if (src_frame == NULL) {
3744 LOGE("No memory for src frame");
3745 return NO_MEMORY;
3746 }
3747 rc = setFwkInputPPData(src_frame, pInputBuffer, &reproc_cfg, metadata,
3748 NULL /*fwk output buffer*/, frameNumber);
3749 if (NO_ERROR != rc) {
3750 LOGE("Error %d while setting framework input PP data", rc);
3751 free(src_frame);
3752 return rc;
3753 }
3754 LOGH("Post-process started");
3755 m_postprocessor.processData(src_frame);
3756 }
3757 return rc;
3758}
3759
3760
3761
3762/*===========================================================================
3763 * FUNCTION : dataNotifyCB
3764 *
3765 * DESCRIPTION: Channel Level callback used for super buffer data notify.
3766 * This function is registered with mm-camera-interface to handle
3767 * data notify
3768 *
3769 * PARAMETERS :
3770 * @recvd_frame : stream frame received
3771 * userdata : user data ptr
3772 *
3773 * RETURN : none
3774 *==========================================================================*/
3775void QCamera3PicChannel::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
3776 void *userdata)
3777{
Thierry Strudele80ad7c2016-12-06 10:16:27 -08003778 ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_PIC_CH_DATA_NOTIFY_CB);
Thierry Strudel3d639192016-09-09 11:52:26 -07003779 LOGD("E\n");
3780 QCamera3PicChannel *channel = (QCamera3PicChannel *)userdata;
3781
3782 if (channel == NULL) {
3783 LOGE("invalid channel pointer");
3784 return;
3785 }
3786
3787 if(channel->m_numStreams != 1) {
3788 LOGE("Error: Bug: This callback assumes one stream per channel");
3789 return;
3790 }
3791
3792
3793 if(channel->mStreams[0] == NULL) {
3794 LOGE("Error: Invalid Stream object");
3795 return;
3796 }
3797
3798 channel->QCamera3PicChannel::streamCbRoutine(recvd_frame, channel->mStreams[0]);
3799
3800 LOGD("X\n");
3801 return;
3802}
3803
3804/*===========================================================================
3805 * FUNCTION : streamCbRoutine
3806 *
3807 * DESCRIPTION:
3808 *
3809 * PARAMETERS :
3810 * @super_frame : the super frame with filled buffer
3811 * @stream : stream on which the buffer was requested and filled
3812 *
3813 * RETURN : none
3814 *==========================================================================*/
3815void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
3816 QCamera3Stream *stream)
3817{
Thierry Strudel9ec39c62016-12-28 11:30:05 -08003818 KPI_ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_CAPTURE_CH_CB);
Thierry Strudel3d639192016-09-09 11:52:26 -07003819 //TODO
3820 //Used only for getting YUV. Jpeg callback will be sent back from channel
3821 //directly to HWI. Refer to func jpegEvtHandle
3822
3823 //Got the yuv callback. Calling yuv callback handler in PostProc
3824 uint8_t frameIndex;
3825 mm_camera_super_buf_t* frame = NULL;
3826 cam_dimension_t dim;
3827 cam_frame_len_offset_t offset;
3828
3829 memset(&dim, 0, sizeof(dim));
3830 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
3831
3832 if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
3833 LOGE("Error with the stream callback");
3834 return;
3835 }
3836
3837 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
3838 LOGD("recvd buf_idx: %u for further processing",
3839 (uint32_t)frameIndex);
3840 if(frameIndex >= mNumSnapshotBufs) {
3841 LOGE("Error, Invalid index for buffer");
3842 if(stream) {
3843 Mutex::Autolock lock(mFreeBuffersLock);
3844 mFreeBufferList.push_back(frameIndex);
3845 stream->bufDone(frameIndex);
3846 }
3847 return;
3848 }
3849
Thierry Strudele80ad7c2016-12-06 10:16:27 -08003850 if ((uint32_t)mYuvMemory->getFrameNumber(frameIndex) == EMPTY_FRAMEWORK_FRAME_NUMBER) {
3851 LOGD("Internal Request recycle frame");
3852 Mutex::Autolock lock(mFreeBuffersLock);
3853 mFreeBufferList.push_back(frameIndex);
3854 return;
3855 }
3856
Thierry Strudel3d639192016-09-09 11:52:26 -07003857 frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
3858 if (frame == NULL) {
3859 LOGE("Error allocating memory to save received_frame structure.");
3860 if(stream) {
3861 Mutex::Autolock lock(mFreeBuffersLock);
3862 mFreeBufferList.push_back(frameIndex);
3863 stream->bufDone(frameIndex);
3864 }
3865 return;
3866 }
3867 *frame = *super_frame;
3868 stream->getFrameDimension(dim);
3869 stream->getFrameOffset(offset);
3870 dumpYUV(frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_INPUT_REPROCESS);
3871
Thierry Strudelc2ee3302016-11-17 12:33:12 -08003872 if (IS_BUFFER_ERROR(super_frame->bufs[0]->flags)) {
3873 mChannelCbBufErr(this, mYuvMemory->getFrameNumber(frameIndex),
3874 CAMERA3_BUFFER_STATUS_ERROR, mUserData);
3875 }
3876
Thierry Strudel3d639192016-09-09 11:52:26 -07003877 m_postprocessor.processData(frame);
3878 free(super_frame);
3879 return;
3880}
3881
Shuzhen Wang3c077d72017-04-20 22:48:59 -07003882QCamera3StreamMem* QCamera3PicChannel::getStreamBufs(uint32_t /*len*/)
Thierry Strudel3d639192016-09-09 11:52:26 -07003883{
Thierry Strudel3d639192016-09-09 11:52:26 -07003884 return mYuvMemory;
3885}
3886
3887void QCamera3PicChannel::putStreamBufs()
3888{
3889 QCamera3ProcessingChannel::putStreamBufs();
Emilian Peev6e7b7ad2017-07-17 19:11:37 -07003890 Mutex::Autolock lock(mFreeBuffersLock);
Thierry Strudel3d639192016-09-09 11:52:26 -07003891 mFreeBufferList.clear();
Emilian Peev6e7b7ad2017-07-17 19:11:37 -07003892
3893 if (nullptr != mYuvMemory) {
3894 uint32_t count = mYuvMemory->getCnt();
3895 for (uint32_t i = 0; i < count; i++) {
3896 mFreeBufferList.push_back(i);
3897 }
3898 }
Thierry Strudel3d639192016-09-09 11:52:26 -07003899}
3900
3901int32_t QCamera3PicChannel::queueJpegSetting(uint32_t index, metadata_buffer_t *metadata)
3902{
3903 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
3904 jpeg_settings_t *settings =
3905 (jpeg_settings_t *)malloc(sizeof(jpeg_settings_t));
3906
3907 if (!settings) {
3908 LOGE("out of memory allocating jpeg_settings");
3909 return -ENOMEM;
3910 }
3911
3912 memset(settings, 0, sizeof(jpeg_settings_t));
3913
3914 settings->out_buf_index = index;
3915
3916 settings->jpeg_orientation = 0;
3917 IF_META_AVAILABLE(int32_t, orientation, CAM_INTF_META_JPEG_ORIENTATION, metadata) {
3918 settings->jpeg_orientation = *orientation;
3919 }
3920
3921 settings->jpeg_quality = 85;
3922 IF_META_AVAILABLE(uint32_t, quality1, CAM_INTF_META_JPEG_QUALITY, metadata) {
3923 settings->jpeg_quality = (uint8_t) *quality1;
3924 }
3925
3926 IF_META_AVAILABLE(uint32_t, quality2, CAM_INTF_META_JPEG_THUMB_QUALITY, metadata) {
3927 settings->jpeg_thumb_quality = (uint8_t) *quality2;
3928 }
3929
3930 IF_META_AVAILABLE(cam_dimension_t, dimension, CAM_INTF_META_JPEG_THUMB_SIZE, metadata) {
3931 settings->thumbnail_size = *dimension;
3932 }
3933
3934 settings->gps_timestamp_valid = 0;
3935 IF_META_AVAILABLE(int64_t, timestamp, CAM_INTF_META_JPEG_GPS_TIMESTAMP, metadata) {
3936 settings->gps_timestamp = *timestamp;
3937 settings->gps_timestamp_valid = 1;
3938 }
3939
3940 settings->gps_coordinates_valid = 0;
3941 IF_META_AVAILABLE(double, coordinates, CAM_INTF_META_JPEG_GPS_COORDINATES, metadata) {
3942 memcpy(settings->gps_coordinates, coordinates, 3*sizeof(double));
3943 settings->gps_coordinates_valid = 1;
3944 }
3945
3946 IF_META_AVAILABLE(uint8_t, proc_methods, CAM_INTF_META_JPEG_GPS_PROC_METHODS, metadata) {
3947 memset(settings->gps_processing_method, 0,
3948 sizeof(settings->gps_processing_method));
3949 strlcpy(settings->gps_processing_method, (const char *)proc_methods,
3950 sizeof(settings->gps_processing_method));
3951 }
3952
Thierry Strudele80ad7c2016-12-06 10:16:27 -08003953 settings->hdr_snapshot = 0;
3954 IF_META_AVAILABLE(cam_hdr_param_t, hdr_info, CAM_INTF_PARM_HAL_BRACKETING_HDR, metadata) {
3955 if (hdr_info->hdr_enable) {
3956 settings->hdr_snapshot = 1;
3957 }
3958 }
3959
3960
Thierry Strudel3d639192016-09-09 11:52:26 -07003961 // Image description
3962 const char *eepromVersion = hal_obj->getEepromVersionInfo();
3963 const uint32_t *ldafCalib = hal_obj->getLdafCalib();
3964 if ((eepromVersion && strlen(eepromVersion)) ||
3965 ldafCalib) {
3966 int len = 0;
3967 settings->image_desc_valid = true;
3968 if (eepromVersion && strlen(eepromVersion)) {
3969 len = snprintf(settings->image_desc, sizeof(settings->image_desc),
Zhijun He7291bb52017-03-12 17:06:36 -07003970 "%s ", eepromVersion);
Thierry Strudel3d639192016-09-09 11:52:26 -07003971 }
3972 if (ldafCalib) {
3973 snprintf(settings->image_desc + len,
3974 sizeof(settings->image_desc) - len, "L:%u-%u",
3975 ldafCalib[0], ldafCalib[1]);
3976 }
3977 }
3978
3979 return m_postprocessor.processJpegSettingData(settings);
3980}
3981
3982
3983void QCamera3PicChannel::overrideYuvSize(uint32_t width, uint32_t height)
3984{
3985 mYuvWidth = width;
3986 mYuvHeight = height;
3987}
3988
3989/*===========================================================================
3990 * FUNCTION : getReprocessType
3991 *
3992 * DESCRIPTION: get the type of reprocess output supported by this channel
3993 *
3994 * PARAMETERS : NONE
3995 *
3996 * RETURN : reprocess_type_t : type of reprocess
3997 *==========================================================================*/
3998reprocess_type_t QCamera3PicChannel::getReprocessType()
3999{
4000 /* a picture channel could either use the postprocessor for reprocess+jpeg
4001 or only for reprocess */
4002 reprocess_type_t expectedReprocess;
4003 if (mPostProcMask == CAM_QCOM_FEATURE_NONE || mInputBufferHint) {
4004 expectedReprocess = REPROCESS_TYPE_JPEG;
4005 } else {
4006 expectedReprocess = REPROCESS_TYPE_NONE;
4007 }
4008 LOGH("expectedReprocess from Pic Channel is %d", expectedReprocess);
4009 return expectedReprocess;
4010}
4011
4012
4013/*===========================================================================
Thierry Strudelc2ee3302016-11-17 12:33:12 -08004014 * FUNCTION : timeoutFrame
4015 *
4016 * DESCRIPTION: Method to indicate to channel that a given frame has take too
4017 * long to be generated
4018 *
4019 * PARAMETERS : framenumber indicating the framenumber of the buffer timingout
4020 *
4021 * RETURN : int32_t type of status
4022 * NO_ERROR -- success
4023 * none-zero failure code
4024 *==========================================================================*/
4025int32_t QCamera3PicChannel::timeoutFrame(uint32_t frameNumber)
4026{
4027 int32_t bufIdx;
4028
4029 bufIdx = mYuvMemory->getBufferIndex(frameNumber);
4030
4031 if (bufIdx < 0) {
4032 LOGE("%s: Buffer not found for frame:%d", __func__, frameNumber);
4033 return -1;
4034 }
4035
4036 mStreams[0]->timeoutFrame(bufIdx);
4037
4038 return NO_ERROR;
4039}
4040
Chien-Yu Chene687bd02016-12-07 18:30:26 -08004041int32_t QCamera3PicChannel::getYuvBufferForRequest(mm_camera_buf_def_t *frame,
4042 uint32_t frameNumber)
4043{
4044 uint32_t bufIdx;
4045 status_t rc;
4046
4047 Mutex::Autolock lock(mFreeBuffersLock);
4048
4049 // Get an available YUV buffer.
4050 if (mFreeBufferList.empty()) {
4051 // Allocate a buffer if no one is available.
Chien-Yu Chen367f2cb2017-08-24 15:08:21 -07004052 rc = mYuvMemory->allocateOne(mFrameLen, /*isCached*/false);
Chien-Yu Chene687bd02016-12-07 18:30:26 -08004053 if (rc < 0) {
4054 LOGE("Failed to allocate heap buffer. Fatal");
4055 return rc;
4056 } else {
4057 bufIdx = (uint32_t)rc;
4058 }
4059 } else {
4060 List<uint32_t>::iterator it = mFreeBufferList.begin();
4061 bufIdx = *it;
4062 mFreeBufferList.erase(it);
4063 }
4064
4065 mYuvMemory->markFrameNumber(bufIdx, frameNumber);
4066
4067 cam_frame_len_offset_t offset = {};
4068 mStreams[0]->getFrameOffset(offset);
4069
4070 // Get a buffer from YUV memory.
Shuzhen Wang063deb52017-08-15 17:24:26 -07004071 rc = mYuvMemory->getBufDef(offset, *frame, bufIdx, mMapStreamBuffers);
Chien-Yu Chene687bd02016-12-07 18:30:26 -08004072 if (rc != 0) {
4073 ALOGE("%s: Getting a frame failed: %s (%d).", __FUNCTION__, strerror(-rc), rc);
4074 return rc;
4075 }
4076
4077 // Set the frame's stream ID because it's not set in getBufDef.
4078 frame->stream_id = mStreams[0]->getMyHandle();
4079 return 0;
4080}
4081
4082int32_t QCamera3PicChannel::returnYuvBuffer(mm_camera_buf_def_t *frame)
4083{
4084 Mutex::Autolock lock(mFreeBuffersLock);
4085 mFreeBufferList.push_back(frame->buf_idx);
4086 return 0;
4087}
4088
4089int32_t QCamera3PicChannel::returnYuvBufferAndEncode(mm_camera_buf_def_t *frame,
4090 buffer_handle_t *outBuffer, uint32_t frameNumber,
4091 std::shared_ptr<metadata_buffer_t> metadata)
4092{
4093 int32_t rc = OK;
4094
4095 // Picture stream must have been started before any request comes in.
4096 if (!m_bIsActive) {
4097 LOGE("Channel not started!!");
4098 return NO_INIT;
4099 }
4100
4101 // Set up reprocess configuration
4102 reprocess_config_t reproc_cfg = {};
4103 cam_dimension_t dim;
4104 dim.width = (int32_t)mYuvWidth;
4105 dim.height = (int32_t)mYuvHeight;
4106 setReprocConfig(reproc_cfg, nullptr, metadata.get(), mStreamFormat, dim);
4107
4108 // Override reprocess type to just JPEG encoding without reprocessing.
4109 reproc_cfg.reprocess_type = REPROCESS_TYPE_NONE;
4110
4111 // Get the index of the output jpeg buffer.
4112 int index = mMemory.getMatchBufIndex((void*)outBuffer);
4113 if(index < 0) {
4114 rc = registerBuffer(outBuffer, mIsType);
4115 if (OK != rc) {
4116 LOGE("On-the-fly buffer registration failed %d",
4117 rc);
4118 return rc;
4119 }
4120
4121 index = mMemory.getMatchBufIndex((void*)outBuffer);
4122 if (index < 0) {
4123 LOGE("Could not find object among registered buffers");
4124 return DEAD_OBJECT;
4125 }
4126 }
4127
4128 rc = mMemory.markFrameNumber((uint32_t)index, frameNumber);
4129 if (rc != OK) {
4130 ALOGE("%s: Marking frame number (%u) for jpeg buffer (%d) failed: %s (%d)", __FUNCTION__,
4131 frameNumber, index, strerror(-rc), rc);
4132 return rc;
4133 }
4134
4135 // Start postprocessor
4136 startPostProc(reproc_cfg);
4137
4138 // Queue jpeg settings
4139 rc = queueJpegSetting((uint32_t)index, metadata.get());
4140 if (rc != OK) {
4141 ALOGE("%s: Queueing Jpeg setting for frame number (%u) buffer index (%d) failed: %s (%d)",
4142 __FUNCTION__, frameNumber, index, strerror(-rc), rc);
4143 return rc;
4144 }
4145
4146 // Allocate a buffer for the YUV input. It will be freed in QCamera3PostProc.
4147 mm_camera_super_buf_t *src_frame =
4148 (mm_camera_super_buf_t *)calloc(1, sizeof(mm_camera_super_buf_t));
4149 if (src_frame == nullptr) {
4150 LOGE("%s: No memory for src frame", __FUNCTION__);
4151 return NO_MEMORY;
4152 }
4153 src_frame->camera_handle = m_camHandle;
4154 src_frame->ch_id = getMyHandle();
4155 src_frame->num_bufs = 1;
4156 src_frame->bufs[0] = frame;
4157
4158 // Start processing the YUV buffer.
4159 ALOGD("%s: %d: Post-process started", __FUNCTION__, __LINE__);
4160 rc = m_postprocessor.processData(src_frame);
4161 if (rc != OK) {
4162 ALOGE("%s: Post processing frame (frame number: %u, jpeg buffer: %d) failed: %s (%d)",
4163 __FUNCTION__, frameNumber, index, strerror(-rc), rc);
4164 return rc;
4165 }
4166
4167 // Allocate a buffer for the metadata. It will be freed in QCamera3PostProc.
4168 mm_camera_super_buf_t *metadataBuf =
4169 (mm_camera_super_buf_t *)calloc(1, sizeof(mm_camera_super_buf_t));
4170 if (metadata == nullptr) {
4171 LOGE("%s: No memory for metadata", __FUNCTION__);
4172 return NO_MEMORY;
4173 }
4174 metadataBuf->camera_handle = m_camHandle;
4175 metadataBuf->ch_id = getMyHandle();
4176 metadataBuf->num_bufs = 1;
4177 metadataBuf->bufs[0] = (mm_camera_buf_def_t *)calloc(1, sizeof(mm_camera_buf_def_t));
4178 metadataBuf->bufs[0]->buffer = metadata.get();
4179
4180 // Start processing the metadata
4181 rc = m_postprocessor.processPPMetadata(metadataBuf);
4182 if (rc != OK) {
4183 ALOGE("%s: Post processing metadata (frame number: %u, jpeg buffer: %d) failed: %s (%d)",
4184 __FUNCTION__, frameNumber, index, strerror(-rc), rc);
4185 return rc;
4186 }
4187
4188 // Queue the external metadata.
4189 {
4190 Mutex::Autolock lock(mPendingExternalMetadataLock);
4191 mPendingExternalMetadata.push_back(metadata);
4192 }
4193
4194 return OK;
4195}
4196
Thierry Strudelc2ee3302016-11-17 12:33:12 -08004197/*===========================================================================
Thierry Strudel3d639192016-09-09 11:52:26 -07004198 * FUNCTION : QCamera3ReprocessChannel
4199 *
4200 * DESCRIPTION: constructor of QCamera3ReprocessChannel
4201 *
4202 * PARAMETERS :
4203 * @cam_handle : camera handle
4204 * @cam_ops : ptr to camera ops table
4205 * @pp_mask : post-proccess feature mask
4206 *
4207 * RETURN : none
4208 *==========================================================================*/
4209QCamera3ReprocessChannel::QCamera3ReprocessChannel(uint32_t cam_handle,
4210 uint32_t channel_handle,
4211 mm_camera_ops_t *cam_ops,
4212 channel_cb_routine cb_routine,
Thierry Strudelc2ee3302016-11-17 12:33:12 -08004213 channel_cb_buffer_err cb_buf_err,
Thierry Strudel3d639192016-09-09 11:52:26 -07004214 cam_padding_info_t *paddingInfo,
4215 cam_feature_mask_t postprocess_mask,
4216 void *userData, void *ch_hdl) :
4217 /* In case of framework reprocessing, pproc and jpeg operations could be
4218 * parallelized by allowing 1 extra buffer for reprocessing output:
4219 * ch_hdl->getNumBuffers() + 1 */
Thierry Strudelc2ee3302016-11-17 12:33:12 -08004220 QCamera3Channel(cam_handle, channel_handle, cam_ops, cb_routine, cb_buf_err, paddingInfo,
Thierry Strudel3d639192016-09-09 11:52:26 -07004221 postprocess_mask, userData,
4222 ((QCamera3ProcessingChannel *)ch_hdl)->getNumBuffers()
4223 + (MAX_REPROCESS_PIPELINE_STAGES - 1)),
4224 inputChHandle(ch_hdl),
4225 mOfflineBuffersIndex(-1),
4226 mFrameLen(0),
4227 mReprocessType(REPROCESS_TYPE_NONE),
4228 m_pSrcChannel(NULL),
4229 m_pMetaChannel(NULL),
4230 mMemory(NULL),
4231 mGrallocMemory(0),
4232 mReprocessPerfMode(false)
4233{
4234 memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
4235 mOfflineBuffersIndex = mNumBuffers -1;
4236 mOfflineMetaIndex = (int32_t) (2*mNumBuffers -1);
4237}
4238
4239
4240/*===========================================================================
4241 * FUNCTION : QCamera3ReprocessChannel
4242 *
4243 * DESCRIPTION: constructor of QCamera3ReprocessChannel
4244 *
4245 * PARAMETERS :
4246 * @cam_handle : camera handle
4247 * @cam_ops : ptr to camera ops table
4248 * @pp_mask : post-proccess feature mask
4249 *
4250 * RETURN : none
4251 *==========================================================================*/
4252int32_t QCamera3ReprocessChannel::initialize(cam_is_type_t isType)
4253{
4254 int32_t rc = NO_ERROR;
4255 mm_camera_channel_attr_t attr;
4256
4257 memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
4258 attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS;
4259 attr.max_unmatched_frames = 1;
4260
4261 m_handle = m_camOps->add_channel(m_camHandle,
4262 &attr,
4263 NULL,
4264 this);
4265 if (m_handle == 0) {
4266 LOGE("Add channel failed");
4267 return UNKNOWN_ERROR;
4268 }
4269
4270 mIsType = isType;
4271 return rc;
4272}
4273
4274/*===========================================================================
4275 * FUNCTION : registerBuffer
4276 *
4277 * DESCRIPTION: register streaming buffer to the channel object
4278 *
4279 * PARAMETERS :
4280 * @buffer : buffer to be registered
4281 * @isType : the image stabilization type for the buffer
4282 *
4283 * RETURN : int32_t type of status
4284 * NO_ERROR -- success
4285 * none-zero failure code
4286 *==========================================================================*/
4287int32_t QCamera3ReprocessChannel::registerBuffer(buffer_handle_t *buffer,
4288 cam_is_type_t isType)
4289{
Thierry Strudele80ad7c2016-12-06 10:16:27 -08004290 ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_REPROC_CH_REG_BUF);
Thierry Strudel3d639192016-09-09 11:52:26 -07004291 int rc = 0;
4292 mIsType = isType;
4293 cam_stream_type_t streamType;
4294
4295 if (buffer == NULL) {
4296 LOGE("Error: Cannot register a NULL buffer");
4297 return BAD_VALUE;
4298 }
4299
4300 if ((uint32_t)mGrallocMemory.getCnt() > (mNumBuffers - 1)) {
4301 LOGE("Trying to register more buffers than initially requested");
4302 return BAD_VALUE;
4303 }
4304
4305 if (0 == m_numStreams) {
4306 rc = initialize(mIsType);
4307 if (rc != NO_ERROR) {
4308 LOGE("Couldn't initialize camera stream %d",
4309 rc);
4310 return rc;
4311 }
4312 }
4313
4314 streamType = mStreams[0]->getMyType();
4315 rc = mGrallocMemory.registerBuffer(buffer, streamType);
4316 if (ALREADY_EXISTS == rc) {
4317 return NO_ERROR;
4318 } else if (NO_ERROR != rc) {
4319 LOGE("Buffer %p couldn't be registered %d", buffer, rc);
4320 return rc;
4321 }
4322
4323 return rc;
4324}
4325
4326/*===========================================================================
4327 * FUNCTION : QCamera3ReprocessChannel
4328 *
4329 * DESCRIPTION: constructor of QCamera3ReprocessChannel
4330 *
4331 * PARAMETERS :
4332 * @cam_handle : camera handle
4333 * @cam_ops : ptr to camera ops table
4334 * @pp_mask : post-proccess feature mask
4335 *
4336 * RETURN : none
4337 *==========================================================================*/
4338void QCamera3ReprocessChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
4339 QCamera3Stream *stream)
4340{
4341 //Got the pproc data callback. Now send to jpeg encoding
4342 uint8_t frameIndex;
4343 uint32_t resultFrameNumber;
Shuzhen Wang26ea6ac2017-05-17 17:42:40 -07004344 ATRACE_CALL();
Thierry Strudel3d639192016-09-09 11:52:26 -07004345 mm_camera_super_buf_t* frame = NULL;
4346 QCamera3ProcessingChannel *obj = (QCamera3ProcessingChannel *)inputChHandle;
4347 cam_dimension_t dim;
4348 cam_frame_len_offset_t offset;
4349
4350 memset(&dim, 0, sizeof(dim));
4351 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
4352 if(!super_frame) {
4353 LOGE("Invalid Super buffer");
4354 return;
4355 }
4356
4357 if(super_frame->num_bufs != 1) {
4358 LOGE("Multiple streams are not supported");
4359 return;
4360 }
4361 if(super_frame->bufs[0] == NULL ) {
4362 LOGE("Error, Super buffer frame does not contain valid buffer");
4363 return;
4364 }
4365 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
4366
4367
4368 if (mReprocessType == REPROCESS_TYPE_JPEG) {
4369 resultFrameNumber = mMemory->getFrameNumber(frameIndex);
4370 frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
4371 if (frame == NULL) {
4372 LOGE("Error allocating memory to save received_frame structure.");
4373 if(stream) {
4374 stream->bufDone(frameIndex);
4375 }
4376 return;
4377 }
4378 LOGI("bufIndex: %u recvd from post proc",
4379 (uint32_t)frameIndex);
4380 *frame = *super_frame;
4381
4382 stream->getFrameDimension(dim);
4383 stream->getFrameOffset(offset);
Thierry Strudelcca4d9c2016-10-20 08:25:53 -07004384 dumpYUV(frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_INPUT_JPEG);
Eino-Ville Talvala8c0646d2017-06-22 14:38:21 -07004385 // Release offline buffers.
4386 int32_t rc = obj->releaseOfflineMemory(resultFrameNumber);
4387 if (NO_ERROR != rc) {
4388 LOGE("Error releasing offline memory %d", rc);
4389 }
Thierry Strudel3d639192016-09-09 11:52:26 -07004390 /* Since reprocessing is done, send the callback to release the input buffer */
4391 if (mChannelCB) {
4392 mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
4393 }
4394 obj->m_postprocessor.processPPData(frame);
4395 } else {
4396 buffer_handle_t *resultBuffer;
4397 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
4398 resultBuffer = (buffer_handle_t *)mGrallocMemory.getBufferHandle(frameIndex);
4399 resultFrameNumber = mGrallocMemory.getFrameNumber(frameIndex);
4400 int32_t rc = stream->bufRelease(frameIndex);
4401 if (NO_ERROR != rc) {
4402 LOGE("Error %d releasing stream buffer %d",
4403 rc, frameIndex);
4404 }
4405 rc = mGrallocMemory.unregisterBuffer(frameIndex);
4406 if (NO_ERROR != rc) {
4407 LOGE("Error %d unregistering stream buffer %d",
4408 rc, frameIndex);
4409 }
4410 obj->reprocessCbRoutine(resultBuffer, resultFrameNumber);
4411
4412 obj->m_postprocessor.releaseOfflineBuffers(false);
4413 qcamera_hal3_pp_data_t *pp_job = obj->m_postprocessor.dequeuePPJob(resultFrameNumber);
4414 if (pp_job != NULL) {
4415 obj->m_postprocessor.releasePPJobData(pp_job);
4416 }
4417 free(pp_job);
4418 resetToCamPerfNormal(resultFrameNumber);
4419 }
4420 free(super_frame);
4421 return;
4422}
4423
4424/*===========================================================================
4425 * FUNCTION : resetToCamPerfNormal
4426 *
4427 * DESCRIPTION: Set the perf mode to normal if all the priority frames
4428 * have been reprocessed
4429 *
4430 * PARAMETERS :
4431 * @frameNumber: Frame number of the reprocess completed frame
4432 *
4433 * RETURN : QCamera3StreamMem *
4434 *==========================================================================*/
4435int32_t QCamera3ReprocessChannel::resetToCamPerfNormal(uint32_t frameNumber)
4436{
4437 int32_t rc = NO_ERROR;
4438 bool resetToPerfNormal = false;
4439 {
4440 Mutex::Autolock lock(mPriorityFramesLock);
4441 /* remove the priority frame number from the list */
4442 for (size_t i = 0; i < mPriorityFrames.size(); i++) {
4443 if (mPriorityFrames[i] == frameNumber) {
4444 mPriorityFrames.removeAt(i);
4445 }
4446 }
4447 /* reset the perf mode if pending priority frame list is empty */
4448 if (mReprocessPerfMode && mPriorityFrames.empty()) {
4449 resetToPerfNormal = true;
4450 }
4451 }
4452 if (resetToPerfNormal) {
4453 QCamera3Stream *pStream = mStreams[0];
4454 cam_stream_parm_buffer_t param;
4455 memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
4456
4457 param.type = CAM_STREAM_PARAM_TYPE_REQUEST_OPS_MODE;
4458 param.perf_mode = CAM_PERF_NORMAL;
4459 rc = pStream->setParameter(param);
4460 {
4461 Mutex::Autolock lock(mPriorityFramesLock);
4462 mReprocessPerfMode = false;
4463 }
4464 }
4465 return rc;
4466}
4467
4468/*===========================================================================
4469 * FUNCTION : getStreamBufs
4470 *
4471 * DESCRIPTION: register the buffers of the reprocess channel
4472 *
4473 * PARAMETERS : none
4474 *
4475 * RETURN : QCamera3StreamMem *
4476 *==========================================================================*/
4477QCamera3StreamMem* QCamera3ReprocessChannel::getStreamBufs(uint32_t len)
4478{
4479 if (mReprocessType == REPROCESS_TYPE_JPEG) {
Shuzhen Wang3c077d72017-04-20 22:48:59 -07004480 mMemory = new QCamera3StreamMem(mNumBuffers);
Thierry Strudel3d639192016-09-09 11:52:26 -07004481 if (!mMemory) {
4482 LOGE("unable to create reproc memory");
4483 return NULL;
4484 }
4485 mFrameLen = len;
4486 return mMemory;
4487 }
4488 return &mGrallocMemory;
4489}
4490
4491/*===========================================================================
4492 * FUNCTION : putStreamBufs
4493 *
4494 * DESCRIPTION: release the reprocess channel buffers
4495 *
4496 * PARAMETERS : none
4497 *
4498 * RETURN :
4499 *==========================================================================*/
4500void QCamera3ReprocessChannel::putStreamBufs()
4501{
4502 if (mReprocessType == REPROCESS_TYPE_JPEG) {
4503 mMemory->deallocate();
4504 delete mMemory;
4505 mMemory = NULL;
4506 mFreeBufferList.clear();
4507 } else {
4508 mGrallocMemory.unregisterBuffers();
4509 }
4510}
4511
4512/*===========================================================================
4513 * FUNCTION : ~QCamera3ReprocessChannel
4514 *
4515 * DESCRIPTION: destructor of QCamera3ReprocessChannel
4516 *
4517 * PARAMETERS : none
4518 *
4519 * RETURN : none
4520 *==========================================================================*/
4521QCamera3ReprocessChannel::~QCamera3ReprocessChannel()
4522{
4523 destroy();
4524
4525 if (m_handle) {
4526 m_camOps->delete_channel(m_camHandle, m_handle);
4527 LOGD("deleting channel %d", m_handle);
4528 m_handle = 0;
4529 }
4530}
4531
4532/*===========================================================================
4533 * FUNCTION : start
4534 *
4535 * DESCRIPTION: start reprocess channel.
4536 *
4537 * PARAMETERS :
4538 *
4539 * RETURN : int32_t type of status
4540 * NO_ERROR -- success
4541 * none-zero failure code
4542 *==========================================================================*/
4543int32_t QCamera3ReprocessChannel::start()
4544{
Thierry Strudele80ad7c2016-12-06 10:16:27 -08004545 ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_REPROC_CH_START);
Thierry Strudel3d639192016-09-09 11:52:26 -07004546 int32_t rc = NO_ERROR;
4547
4548 rc = QCamera3Channel::start();
4549
4550 if (rc == NO_ERROR) {
Chien-Yu Chence5b8662017-05-09 17:17:17 -07004551 rc = m_camOps->start_channel(m_camHandle, m_handle, /*start_sensor_streaming*/true);
Thierry Strudel3d639192016-09-09 11:52:26 -07004552
4553 // Check failure
4554 if (rc != NO_ERROR) {
4555 LOGE("start_channel failed %d", rc);
4556 QCamera3Channel::stop();
4557 }
4558 }
4559 return rc;
4560}
4561
4562/*===========================================================================
4563 * FUNCTION : stop
4564 *
4565 * DESCRIPTION: stop reprocess channel.
4566 *
4567 * PARAMETERS : none
4568 *
4569 * RETURN : int32_t type of status
4570 * NO_ERROR -- success
4571 * none-zero failure code
4572 *==========================================================================*/
4573int32_t QCamera3ReprocessChannel::stop()
4574{
Thierry Strudele80ad7c2016-12-06 10:16:27 -08004575 ATRACE_CAMSCOPE_CALL(CAMSCOPE_HAL3_REPROC_CH_STOP);
Thierry Strudel3d639192016-09-09 11:52:26 -07004576 int32_t rc = NO_ERROR;
4577
4578 rc = QCamera3Channel::stop();
Chien-Yu Chen09cb28e2017-07-21 13:15:52 -07004579 rc |= m_camOps->stop_channel(m_camHandle, m_handle, /*stop_channel_immediately*/false);
Thierry Strudel3d639192016-09-09 11:52:26 -07004580 // Unmapping the buffers
4581 unmapOfflineBuffers(true);
4582 return rc;
4583}
4584
4585/*===========================================================================
4586 * FUNCTION : getStreamBySrcHandle
4587 *
4588 * DESCRIPTION: find reprocess stream by its source stream handle
4589 *
4590 * PARAMETERS :
4591 * @srcHandle : source stream handle
4592 *
4593 * RETURN : ptr to reprocess stream if found. NULL if not found
4594 *==========================================================================*/
4595QCamera3Stream * QCamera3ReprocessChannel::getStreamBySrcHandle(uint32_t srcHandle)
4596{
4597 QCamera3Stream *pStream = NULL;
4598
4599 for (uint32_t i = 0; i < m_numStreams; i++) {
4600 if (mSrcStreamHandles[i] == srcHandle) {
4601 pStream = mStreams[i];
4602 break;
4603 }
4604 }
4605 return pStream;
4606}
4607
4608/*===========================================================================
4609 * FUNCTION : getSrcStreamBySrcHandle
4610 *
4611 * DESCRIPTION: find source stream by source stream handle
4612 *
4613 * PARAMETERS :
4614 * @srcHandle : source stream handle
4615 *
4616 * RETURN : ptr to reprocess stream if found. NULL if not found
4617 *==========================================================================*/
4618QCamera3Stream * QCamera3ReprocessChannel::getSrcStreamBySrcHandle(uint32_t srcHandle)
4619{
4620 QCamera3Stream *pStream = NULL;
4621
4622 if (NULL == m_pSrcChannel) {
4623 return NULL;
4624 }
4625
4626 for (uint32_t i = 0; i < m_numStreams; i++) {
4627 if (mSrcStreamHandles[i] == srcHandle) {
4628 pStream = m_pSrcChannel->getStreamByIndex(i);
4629 break;
4630 }
4631 }
4632 return pStream;
4633}
4634
4635/*===========================================================================
4636 * FUNCTION : unmapOfflineBuffers
4637 *
4638 * DESCRIPTION: Unmaps offline buffers
4639 *
4640 * PARAMETERS : none
4641 *
4642 * RETURN : int32_t type of status
4643 * NO_ERROR -- success
4644 * none-zero failure code
4645 *==========================================================================*/
4646int32_t QCamera3ReprocessChannel::unmapOfflineBuffers(bool all)
4647{
4648 int rc = NO_ERROR;
Emilian Peev5c4e9f52017-07-27 18:57:26 +01004649 Mutex::Autolock l(mOfflineBuffersLock);
Thierry Strudel3d639192016-09-09 11:52:26 -07004650 if (!mOfflineBuffers.empty()) {
4651 QCamera3Stream *stream = NULL;
4652 List<OfflineBuffer>::iterator it = mOfflineBuffers.begin();
4653 for (; it != mOfflineBuffers.end(); it++) {
4654 stream = (*it).stream;
4655 if (NULL != stream) {
4656 rc = stream->unmapBuf((*it).type,
4657 (*it).index,
4658 -1);
4659 if (NO_ERROR != rc) {
4660 LOGE("Error during offline buffer unmap %d",
4661 rc);
4662 }
4663 LOGD("Unmapped buffer with index %d", (*it).index);
4664 }
4665 if (!all) {
4666 mOfflineBuffers.erase(it);
4667 break;
4668 }
4669 }
4670 if (all) {
4671 mOfflineBuffers.clear();
4672 }
4673 }
4674
4675 if (!mOfflineMetaBuffers.empty()) {
4676 QCamera3Stream *stream = NULL;
4677 List<OfflineBuffer>::iterator it = mOfflineMetaBuffers.begin();
4678 for (; it != mOfflineMetaBuffers.end(); it++) {
4679 stream = (*it).stream;
4680 if (NULL != stream) {
4681 rc = stream->unmapBuf((*it).type,
4682 (*it).index,
4683 -1);
4684 if (NO_ERROR != rc) {
4685 LOGE("Error during offline buffer unmap %d",
4686 rc);
4687 }
4688 LOGD("Unmapped meta buffer with index %d", (*it).index);
4689 }
4690 if (!all) {
4691 mOfflineMetaBuffers.erase(it);
4692 break;
4693 }
4694 }
4695 if (all) {
4696 mOfflineMetaBuffers.clear();
4697 }
4698 }
4699 return rc;
4700}
4701
4702/*===========================================================================
4703 * FUNCTION : bufDone
4704 *
4705 * DESCRIPTION: Return reprocess stream buffer to free buffer list.
4706 * Note that this function doesn't queue buffer back to kernel.
4707 * It's up to doReprocessOffline to do that instead.
4708 * PARAMETERS :
4709 * @recvd_frame : stream buf frame to be returned
4710 *
4711 * RETURN : int32_t type of status
4712 * NO_ERROR -- success
4713 * none-zero failure code
4714 *==========================================================================*/
4715int32_t QCamera3ReprocessChannel::bufDone(mm_camera_super_buf_t *recvd_frame)
4716{
4717 int rc = NO_ERROR;
4718 if (recvd_frame && recvd_frame->num_bufs == 1) {
4719 Mutex::Autolock lock(mFreeBuffersLock);
4720 uint32_t buf_idx = recvd_frame->bufs[0]->buf_idx;
4721 mFreeBufferList.push_back(buf_idx);
4722
4723 } else {
4724 LOGE("Fatal. Not supposed to be here");
4725 rc = BAD_VALUE;
4726 }
4727
4728 return rc;
4729}
4730
4731/*===========================================================================
4732 * FUNCTION : overrideMetadata
4733 *
4734 * DESCRIPTION: Override metadata entry such as rotation, crop, and CDS info.
4735 *
4736 * PARAMETERS :
4737 * @frame : input frame from source stream
4738 * meta_buffer: metadata buffer
4739 * @metadata : corresponding metadata
4740 * @fwk_frame :
4741 *
4742 * RETURN : int32_t type of status
4743 * NO_ERROR -- success
4744 * none-zero failure code
4745 *==========================================================================*/
4746int32_t QCamera3ReprocessChannel::overrideMetadata(qcamera_hal3_pp_buffer_t *pp_buffer,
4747 mm_camera_buf_def_t *meta_buffer, jpeg_settings_t *jpeg_settings,
4748 qcamera_fwk_input_pp_data_t &fwk_frame)
4749{
4750 int32_t rc = NO_ERROR;
4751 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
4752 if ((NULL == meta_buffer) || (NULL == pp_buffer) || (NULL == pp_buffer->input) ||
4753 (NULL == hal_obj)) {
4754 return BAD_VALUE;
4755 }
4756
4757 metadata_buffer_t *meta = (metadata_buffer_t *)meta_buffer->buffer;
4758 mm_camera_super_buf_t *frame = pp_buffer->input;
4759 if (NULL == meta) {
4760 return BAD_VALUE;
4761 }
4762
4763 for (uint32_t i = 0; i < frame->num_bufs; i++) {
4764 QCamera3Stream *pStream = getStreamBySrcHandle(frame->bufs[i]->stream_id);
4765 QCamera3Stream *pSrcStream = getSrcStreamBySrcHandle(frame->bufs[i]->stream_id);
4766
4767 if (pStream != NULL && pSrcStream != NULL) {
4768 if (jpeg_settings) {
4769 // Find rotation info for reprocess stream
4770 cam_rotation_info_t rotation_info;
4771 memset(&rotation_info, 0, sizeof(rotation_info));
4772 if (jpeg_settings->jpeg_orientation == 0) {
4773 rotation_info.rotation = ROTATE_0;
4774 } else if (jpeg_settings->jpeg_orientation == 90) {
4775 rotation_info.rotation = ROTATE_90;
4776 } else if (jpeg_settings->jpeg_orientation == 180) {
4777 rotation_info.rotation = ROTATE_180;
4778 } else if (jpeg_settings->jpeg_orientation == 270) {
4779 rotation_info.rotation = ROTATE_270;
4780 }
Shuzhen Wang6ec8eac2016-07-28 23:09:23 -07004781
4782 rotation_info.device_rotation = ROTATE_0;
Thierry Strudel3d639192016-09-09 11:52:26 -07004783 rotation_info.streamId = mStreams[0]->getMyServerID();
4784 ADD_SET_PARAM_ENTRY_TO_BATCH(meta, CAM_INTF_PARM_ROTATION, rotation_info);
4785 }
4786
4787 // Find and insert crop info for reprocess stream
4788 IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) {
4789 if (MAX_NUM_STREAMS > crop_data->num_of_streams) {
4790 for (int j = 0; j < crop_data->num_of_streams; j++) {
4791 if (crop_data->crop_info[j].stream_id ==
4792 pSrcStream->getMyServerID()) {
4793
4794 // Store crop/roi information for offline reprocess
4795 // in the reprocess stream slot
4796 crop_data->crop_info[crop_data->num_of_streams].crop =
4797 crop_data->crop_info[j].crop;
4798 crop_data->crop_info[crop_data->num_of_streams].roi_map =
4799 crop_data->crop_info[j].roi_map;
4800 crop_data->crop_info[crop_data->num_of_streams].stream_id =
4801 mStreams[0]->getMyServerID();
4802 crop_data->num_of_streams++;
4803
4804 LOGD("Reprocess stream server id: %d",
4805 mStreams[0]->getMyServerID());
4806 LOGD("Found offline reprocess crop %dx%d %dx%d",
4807 crop_data->crop_info[j].crop.left,
4808 crop_data->crop_info[j].crop.top,
4809 crop_data->crop_info[j].crop.width,
4810 crop_data->crop_info[j].crop.height);
4811 LOGD("Found offline reprocess roimap %dx%d %dx%d",
4812 crop_data->crop_info[j].roi_map.left,
4813 crop_data->crop_info[j].roi_map.top,
4814 crop_data->crop_info[j].roi_map.width,
4815 crop_data->crop_info[j].roi_map.height);
4816
4817 break;
4818 }
4819 }
4820 } else {
4821 LOGE("No space to add reprocess stream crop/roi information");
4822 }
4823 }
4824
4825 IF_META_AVAILABLE(cam_cds_data_t, cdsInfo, CAM_INTF_META_CDS_DATA, meta) {
4826 uint8_t cnt = cdsInfo->num_of_streams;
4827 if (cnt <= MAX_NUM_STREAMS) {
4828 cam_stream_cds_info_t repro_cds_info;
4829 memset(&repro_cds_info, 0, sizeof(repro_cds_info));
4830 repro_cds_info.stream_id = mStreams[0]->getMyServerID();
4831 for (size_t i = 0; i < cnt; i++) {
4832 if (cdsInfo->cds_info[i].stream_id ==
4833 pSrcStream->getMyServerID()) {
4834 repro_cds_info.cds_enable =
4835 cdsInfo->cds_info[i].cds_enable;
4836 break;
4837 }
4838 }
4839 cdsInfo->num_of_streams = 1;
4840 cdsInfo->cds_info[0] = repro_cds_info;
4841 } else {
4842 LOGE("No space to add reprocess stream cds information");
4843 }
4844 }
4845
4846 fwk_frame.input_buffer = *frame->bufs[i];
4847 fwk_frame.metadata_buffer = *meta_buffer;
4848 fwk_frame.output_buffer = pp_buffer->output;
4849 break;
4850 } else {
4851 LOGE("Source/Re-process streams are invalid");
4852 rc |= BAD_VALUE;
4853 }
4854 }
4855
4856 return rc;
4857}
4858
4859/*===========================================================================
4860* FUNCTION : overrideFwkMetadata
4861*
4862* DESCRIPTION: Override frameworks metadata such as rotation, crop, and CDS data.
4863*
4864* PARAMETERS :
4865* @frame : input frame for reprocessing
4866*
4867* RETURN : int32_t type of status
4868* NO_ERROR -- success
4869* none-zero failure code
4870*==========================================================================*/
4871int32_t QCamera3ReprocessChannel::overrideFwkMetadata(
4872 qcamera_fwk_input_pp_data_t *frame)
4873{
4874 if (NULL == frame) {
4875 LOGE("Incorrect input frame");
4876 return BAD_VALUE;
4877 }
4878
4879 if (NULL == frame->metadata_buffer.buffer) {
4880 LOGE("No metadata available");
4881 return BAD_VALUE;
4882 }
4883 metadata_buffer_t *meta = (metadata_buffer_t *) frame->metadata_buffer.buffer;
4884
4885 // Not doing rotation at all for YUV to YUV reprocess
4886 if (mReprocessType != REPROCESS_TYPE_JPEG) {
4887 LOGD("Override rotation to 0 for channel reprocess type %d",
4888 mReprocessType);
4889 cam_rotation_info_t rotation_info;
4890 memset(&rotation_info, 0, sizeof(rotation_info));
4891 rotation_info.rotation = ROTATE_0;
4892 rotation_info.streamId = mStreams[0]->getMyServerID();
4893 ADD_SET_PARAM_ENTRY_TO_BATCH(meta, CAM_INTF_PARM_ROTATION, rotation_info);
4894 }
4895
4896 // Find and insert crop info for reprocess stream
4897 IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) {
4898 if (1 == crop_data->num_of_streams) {
4899 // Store crop/roi information for offline reprocess
4900 // in the reprocess stream slot
4901 crop_data->crop_info[crop_data->num_of_streams].crop =
4902 crop_data->crop_info[0].crop;
4903 crop_data->crop_info[crop_data->num_of_streams].roi_map =
4904 crop_data->crop_info[0].roi_map;
4905 crop_data->crop_info[crop_data->num_of_streams].stream_id =
4906 mStreams[0]->getMyServerID();
4907 crop_data->num_of_streams++;
4908
4909 LOGD("Reprocess stream server id: %d",
4910 mStreams[0]->getMyServerID());
4911 LOGD("Found offline reprocess crop %dx%d %dx%d",
4912 crop_data->crop_info[0].crop.left,
4913 crop_data->crop_info[0].crop.top,
4914 crop_data->crop_info[0].crop.width,
4915 crop_data->crop_info[0].crop.height);
4916 LOGD("Found offline reprocess roi map %dx%d %dx%d",
4917 crop_data->crop_info[0].roi_map.left,
4918 crop_data->crop_info[0].roi_map.top,
4919 crop_data->crop_info[0].roi_map.width,
4920 crop_data->crop_info[0].roi_map.height);
4921 } else {
4922 LOGE("Incorrect number of offline crop data entries %d",
4923 crop_data->num_of_streams);
4924 return BAD_VALUE;
4925 }
4926 } else {
4927 LOGW("Crop data not present");
4928 }
4929
4930 IF_META_AVAILABLE(cam_cds_data_t, cdsInfo, CAM_INTF_META_CDS_DATA, meta) {
4931 if (1 == cdsInfo->num_of_streams) {
4932 cdsInfo->cds_info[0].stream_id = mStreams[0]->getMyServerID();
4933 } else {
4934 LOGE("Incorrect number of offline cds info entries %d",
4935 cdsInfo->num_of_streams);
4936 return BAD_VALUE;
4937 }
4938 }
4939
4940 return NO_ERROR;
4941}
4942
4943/*===========================================================================
4944 * FUNCTION : doReprocessOffline
4945 *
4946 * DESCRIPTION: request to do a reprocess on the frame
4947 *
4948 * PARAMETERS :
4949 * @frame : input frame for reprocessing
4950 * @isPriorityFrame: Hint that this frame is of priority, equivalent to
4951 * real time, even though it is processed in offline mechanism
4952 *
4953 * RETURN : int32_t type of status
4954 * NO_ERROR -- success
4955 * none-zero failure code
4956 *==========================================================================*/
4957 int32_t QCamera3ReprocessChannel::doReprocessOffline(
4958 qcamera_fwk_input_pp_data_t *frame, bool isPriorityFrame)
4959{
4960 int32_t rc = 0;
4961 int index;
4962 OfflineBuffer mappedBuffer;
Shuzhen Wang26ea6ac2017-05-17 17:42:40 -07004963 ATRACE_CALL();
Thierry Strudel3d639192016-09-09 11:52:26 -07004964
4965 if (m_numStreams < 1) {
4966 LOGE("No reprocess stream is created");
4967 return -1;
4968 }
4969
4970 if (NULL == frame) {
4971 LOGE("Incorrect input frame");
4972 return BAD_VALUE;
4973 }
4974
4975 if (NULL == frame->metadata_buffer.buffer) {
4976 LOGE("No metadata available");
4977 return BAD_VALUE;
4978 }
4979
Shuzhen Wang063deb52017-08-15 17:24:26 -07004980 if (0 > frame->input_buffer.fd) {
Thierry Strudel3d639192016-09-09 11:52:26 -07004981 LOGE("No input buffer available");
4982 return BAD_VALUE;
4983 }
4984
4985 if ((0 == m_numStreams) || (NULL == mStreams[0])) {
4986 LOGE("Reprocess stream not initialized!");
4987 return NO_INIT;
4988 }
4989
4990 QCamera3Stream *pStream = mStreams[0];
4991
4992 //qbuf the output buffer if it was allocated by the framework
4993 if (mReprocessType != REPROCESS_TYPE_JPEG && frame->output_buffer != NULL) {
Thierry Strudel3d639192016-09-09 11:52:26 -07004994 index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer);
4995 if(index < 0) {
4996 rc = registerBuffer(frame->output_buffer, mIsType);
4997 if (NO_ERROR != rc) {
4998 LOGE("On-the-fly buffer registration failed %d",
4999 rc);
5000 return rc;
5001 }
5002
5003 index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer);
5004 if (index < 0) {
5005 LOGE("Could not find object among registered buffers");
5006 return DEAD_OBJECT;
5007 }
5008 }
Thierry Strudelc2ee3302016-11-17 12:33:12 -08005009 rc = mGrallocMemory.markFrameNumber(index, frame->frameNumber);
5010 if(rc != NO_ERROR) {
5011 LOGE("Failed to mark frame#:%d, index:%d",frame->frameNumber,index);
5012 return rc;
5013 }
Shuzhen Wang3c077d72017-04-20 22:48:59 -07005014 if(!m_bIsActive) {
5015 rc = start();
5016 if (NO_ERROR != rc) {
5017 return rc;
5018 }
5019 } else {
5020 rc = pStream->bufDone(index);
5021 if(rc != NO_ERROR) {
5022 LOGE("Failed to Q new buffer to stream %d", rc);
5023 mGrallocMemory.markFrameNumber(index, -1);
5024 return rc;
5025 }
Thierry Strudel3d639192016-09-09 11:52:26 -07005026 }
Thierry Strudel3d639192016-09-09 11:52:26 -07005027
5028 } else if (mReprocessType == REPROCESS_TYPE_JPEG) {
5029 Mutex::Autolock lock(mFreeBuffersLock);
5030 uint32_t bufIdx;
5031 if (mFreeBufferList.empty()) {
5032 rc = mMemory->allocateOne(mFrameLen);
5033 if (rc < 0) {
5034 LOGE("Failed allocating heap buffer. Fatal");
5035 return BAD_VALUE;
5036 } else {
5037 bufIdx = (uint32_t)rc;
5038 }
5039 } else {
5040 bufIdx = *(mFreeBufferList.begin());
5041 mFreeBufferList.erase(mFreeBufferList.begin());
5042 }
5043
5044 mMemory->markFrameNumber(bufIdx, frame->frameNumber);
5045 rc = pStream->bufDone(bufIdx);
5046 if (rc != NO_ERROR) {
5047 LOGE("Failed to queue new buffer to stream");
5048 return rc;
5049 }
5050 }
5051
5052 int32_t max_idx = (int32_t) (mNumBuffers - 1);
5053 //loop back the indices if max burst count reached
5054 if (mOfflineBuffersIndex == max_idx) {
5055 mOfflineBuffersIndex = -1;
5056 }
5057 uint32_t buf_idx = (uint32_t)(mOfflineBuffersIndex + 1);
Thierry Strudel295a0ca2016-11-03 18:38:47 -07005058
5059 //Do cache ops before sending for reprocess
5060 if (mMemory != NULL) {
5061 mMemory->cleanInvalidateCache(buf_idx);
5062 }
5063
Thierry Strudel3d639192016-09-09 11:52:26 -07005064 rc = pStream->mapBuf(
5065 CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
5066 buf_idx, -1,
5067 frame->input_buffer.fd, frame->input_buffer.buffer,
5068 frame->input_buffer.frame_len);
5069 if (NO_ERROR == rc) {
Emilian Peev5c4e9f52017-07-27 18:57:26 +01005070 Mutex::Autolock l(mOfflineBuffersLock);
Thierry Strudel3d639192016-09-09 11:52:26 -07005071 mappedBuffer.index = buf_idx;
5072 mappedBuffer.stream = pStream;
5073 mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF;
5074 mOfflineBuffers.push_back(mappedBuffer);
5075 mOfflineBuffersIndex = (int32_t)buf_idx;
5076 LOGD("Mapped buffer with index %d", mOfflineBuffersIndex);
5077 }
5078
5079 max_idx = (int32_t) ((mNumBuffers * 2) - 1);
5080 //loop back the indices if max burst count reached
5081 if (mOfflineMetaIndex == max_idx) {
5082 mOfflineMetaIndex = (int32_t) (mNumBuffers - 1);
5083 }
5084 uint32_t meta_buf_idx = (uint32_t)(mOfflineMetaIndex + 1);
5085 rc |= pStream->mapBuf(
5086 CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF,
5087 meta_buf_idx, -1,
5088 frame->metadata_buffer.fd, frame->metadata_buffer.buffer,
5089 frame->metadata_buffer.frame_len);
5090 if (NO_ERROR == rc) {
Emilian Peev5c4e9f52017-07-27 18:57:26 +01005091 Mutex::Autolock l(mOfflineBuffersLock);
Thierry Strudel3d639192016-09-09 11:52:26 -07005092 mappedBuffer.index = meta_buf_idx;
5093 mappedBuffer.stream = pStream;
5094 mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF;
5095 mOfflineMetaBuffers.push_back(mappedBuffer);
5096 mOfflineMetaIndex = (int32_t)meta_buf_idx;
5097 LOGD("Mapped meta buffer with index %d", mOfflineMetaIndex);
5098 }
5099
5100 if (rc == NO_ERROR) {
5101 cam_stream_parm_buffer_t param;
5102 uint32_t numPendingPriorityFrames = 0;
5103
5104 if(isPriorityFrame && (mReprocessType != REPROCESS_TYPE_JPEG)) {
5105 Mutex::Autolock lock(mPriorityFramesLock);
5106 /* read the length before pushing the frame number to check if
5107 * vector is empty */
5108 numPendingPriorityFrames = mPriorityFrames.size();
5109 mPriorityFrames.push(frame->frameNumber);
5110 }
5111
5112 if(isPriorityFrame && !numPendingPriorityFrames &&
5113 (mReprocessType != REPROCESS_TYPE_JPEG)) {
5114 memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
5115 param.type = CAM_STREAM_PARAM_TYPE_REQUEST_OPS_MODE;
5116 param.perf_mode = CAM_PERF_HIGH_PERFORMANCE;
5117 rc = pStream->setParameter(param);
5118 if (rc != NO_ERROR) {
Thierry Strudelc2ee3302016-11-17 12:33:12 -08005119 LOGE("%s: setParameter for CAM_PERF_HIGH_PERFORMANCE failed",
Thierry Strudel3d639192016-09-09 11:52:26 -07005120 __func__);
5121 }
5122 {
5123 Mutex::Autolock lock(mPriorityFramesLock);
5124 mReprocessPerfMode = true;
5125 }
5126 }
5127
5128 memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
5129 param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
5130 param.reprocess.buf_index = buf_idx;
5131 param.reprocess.frame_idx = frame->input_buffer.frame_idx;
5132 param.reprocess.meta_present = 1;
5133 param.reprocess.meta_buf_index = meta_buf_idx;
5134
5135 LOGI("Offline reprocessing id = %d buf Id = %d meta index = %d",
5136 param.reprocess.frame_idx, param.reprocess.buf_index,
5137 param.reprocess.meta_buf_index);
5138 rc = pStream->setParameter(param);
5139 if (rc != NO_ERROR) {
5140 LOGE("stream setParameter for reprocess failed");
5141 resetToCamPerfNormal(frame->frameNumber);
5142 }
5143 } else {
5144 LOGE("Input buffer memory map failed: %d", rc);
5145 }
5146
5147 return rc;
5148}
5149
5150/*===========================================================================
5151 * FUNCTION : doReprocess
5152 *
5153 * DESCRIPTION: request to do a reprocess on the frame
5154 *
5155 * PARAMETERS :
5156 * @buf_fd : fd to the input buffer that needs reprocess
5157 * @buffer : Buffer ptr
5158 * @buf_lenght : length of the input buffer
5159 * @ret_val : result of reprocess.
5160 * Example: Could be faceID in case of register face image.
5161 * @meta_frame : metadata frame.
5162 *
5163 * RETURN : int32_t type of status
5164 * NO_ERROR -- success
5165 * none-zero failure code
5166 *==========================================================================*/
5167int32_t QCamera3ReprocessChannel::doReprocess(int buf_fd, void *buffer, size_t buf_length,
5168 int32_t &ret_val, mm_camera_super_buf_t *meta_frame)
5169{
5170 int32_t rc = 0;
5171 if (m_numStreams < 1) {
5172 LOGE("No reprocess stream is created");
5173 return -1;
5174 }
5175 if (meta_frame == NULL) {
5176 LOGE("Did not get corresponding metadata in time");
5177 return -1;
5178 }
5179
5180 uint8_t buf_idx = 0;
5181 for (uint32_t i = 0; i < m_numStreams; i++) {
5182 rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
5183 buf_idx, -1,
5184 buf_fd, buffer, buf_length);
5185
Thierry Strudel295a0ca2016-11-03 18:38:47 -07005186 //Do cache ops before sending for reprocess
5187 if (mMemory != NULL) {
5188 mMemory->cleanInvalidateCache(buf_idx);
5189 }
5190
Thierry Strudel3d639192016-09-09 11:52:26 -07005191 if (rc == NO_ERROR) {
5192 cam_stream_parm_buffer_t param;
5193 memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
5194 param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
5195 param.reprocess.buf_index = buf_idx;
5196 param.reprocess.meta_present = 1;
5197 param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID();
5198 param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx;
5199
5200 LOGI("Online reprocessing id = %d buf Id = %d meta index = %d",
5201 param.reprocess.frame_idx, param.reprocess.buf_index,
5202 param.reprocess.meta_buf_index);
5203 rc = mStreams[i]->setParameter(param);
5204 if (rc == NO_ERROR) {
5205 ret_val = param.reprocess.ret_val;
5206 }
5207 mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
5208 buf_idx, -1);
5209 }
5210 }
5211 return rc;
5212}
5213
5214/*===========================================================================
5215 * FUNCTION : addReprocStreamsFromSource
5216 *
5217 * DESCRIPTION: add reprocess streams from input source channel
5218 *
5219 * PARAMETERS :
5220 * @config : pp feature configuration
5221 * @src_config : source reprocess configuration
5222 * @isType : type of image stabilization required on this stream
5223 * @pMetaChannel : ptr to metadata channel to get corresp. metadata
5224 *
5225 *
5226 * RETURN : int32_t type of status
5227 * NO_ERROR -- success
5228 * none-zero failure code
5229 *==========================================================================*/
5230int32_t QCamera3ReprocessChannel::addReprocStreamsFromSource(cam_pp_feature_config_t &pp_config,
5231 const reprocess_config_t &src_config , cam_is_type_t is_type,
5232 QCamera3Channel *pMetaChannel)
5233{
5234 int32_t rc = 0;
5235 cam_stream_reproc_config_t reprocess_config;
5236 cam_stream_type_t streamType;
5237
5238 cam_dimension_t streamDim = src_config.output_stream_dim;
5239
5240 if (NULL != src_config.src_channel) {
5241 QCamera3Stream *pSrcStream = src_config.src_channel->getStreamByIndex(0);
5242 if (pSrcStream == NULL) {
5243 LOGE("source channel doesn't have a stream");
5244 return BAD_VALUE;
5245 }
5246 mSrcStreamHandles[m_numStreams] = pSrcStream->getMyHandle();
5247 }
5248
5249 streamType = CAM_STREAM_TYPE_OFFLINE_PROC;
5250 reprocess_config.pp_type = CAM_OFFLINE_REPROCESS_TYPE;
5251
5252 reprocess_config.offline.input_fmt = src_config.stream_format;
5253 reprocess_config.offline.input_dim = src_config.input_stream_dim;
5254 reprocess_config.offline.input_buf_planes.plane_info =
5255 src_config.input_stream_plane_info.plane_info;
5256 reprocess_config.offline.num_of_bufs = (uint8_t)mNumBuffers;
5257 reprocess_config.offline.input_type = src_config.stream_type;
5258
5259 reprocess_config.pp_feature_config = pp_config;
5260 QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
5261 m_handle,
5262 m_camOps,
5263 &mPaddingInfo,
Shuzhen Wang063deb52017-08-15 17:24:26 -07005264 (QCamera3Channel*)this,
5265 false/*mapStreamBuffers*/);
Thierry Strudel3d639192016-09-09 11:52:26 -07005266 if (pStream == NULL) {
5267 LOGE("No mem for Stream");
5268 return NO_MEMORY;
5269 }
5270
5271 rc = pStream->init(streamType, src_config.stream_format,
5272 streamDim, ROTATE_0, &reprocess_config,
5273 (uint8_t)mNumBuffers,
5274 reprocess_config.pp_feature_config.feature_mask,
5275 is_type,
5276 0,/* batchSize */
5277 QCamera3Channel::streamCbRoutine, this);
5278
5279 if (rc == 0) {
5280 mStreams[m_numStreams] = pStream;
5281 m_numStreams++;
5282 } else {
5283 LOGE("failed to create reprocess stream");
5284 delete pStream;
5285 }
5286
5287 if (rc == NO_ERROR) {
5288 m_pSrcChannel = src_config.src_channel;
5289 m_pMetaChannel = pMetaChannel;
5290 mReprocessType = src_config.reprocess_type;
5291 LOGD("mReprocessType is %d", mReprocessType);
5292 }
5293 mm_camera_req_buf_t buf;
5294 memset(&buf, 0x0, sizeof(buf));
5295 buf.type = MM_CAMERA_REQ_SUPER_BUF;
5296 buf.num_buf_requested = 1;
5297 if(m_camOps->request_super_buf(m_camHandle,m_handle, &buf) < 0) {
5298 LOGE("Request for super buffer failed");
5299 }
5300 return rc;
5301}
5302
5303/* QCamera3SupportChannel methods */
5304
5305cam_dimension_t QCamera3SupportChannel::kDim = {640, 480};
5306
5307QCamera3SupportChannel::QCamera3SupportChannel(uint32_t cam_handle,
5308 uint32_t channel_handle,
5309 mm_camera_ops_t *cam_ops,
5310 cam_padding_info_t *paddingInfo,
5311 cam_feature_mask_t postprocess_mask,
5312 cam_stream_type_t streamType,
5313 cam_dimension_t *dim,
5314 cam_format_t streamFormat,
5315 uint8_t hw_analysis_supported,
5316 cam_color_filter_arrangement_t color_arrangement,
5317 void *userData, uint32_t numBuffers) :
5318 QCamera3Channel(cam_handle, channel_handle, cam_ops,
Thierry Strudelc2ee3302016-11-17 12:33:12 -08005319 NULL, NULL, paddingInfo, postprocess_mask,
Thierry Strudel3d639192016-09-09 11:52:26 -07005320 userData, numBuffers),
Jason Leec4cf5032017-05-24 18:31:41 -07005321 mMemory(NULL),
5322 mHwAnalysisSupported(hw_analysis_supported),
5323 mColorArrangement(color_arrangement)
Thierry Strudel3d639192016-09-09 11:52:26 -07005324{
5325 memcpy(&mDim, dim, sizeof(cam_dimension_t));
5326 mStreamType = streamType;
5327 mStreamFormat = streamFormat;
Thierry Strudel3d639192016-09-09 11:52:26 -07005328}
5329
5330QCamera3SupportChannel::~QCamera3SupportChannel()
5331{
5332 destroy();
5333
5334 if (mMemory) {
5335 mMemory->deallocate();
5336 delete mMemory;
5337 mMemory = NULL;
5338 }
5339}
5340
5341int32_t QCamera3SupportChannel::initialize(cam_is_type_t isType)
5342{
5343 int32_t rc;
5344
5345 if (mMemory || m_numStreams > 0) {
5346 LOGE("metadata channel already initialized");
5347 return -EINVAL;
5348 }
5349
5350 mIsType = isType;
Jason Leec4cf5032017-05-24 18:31:41 -07005351 // Make Analysis same as Preview format
5352 if (!mHwAnalysisSupported && mStreamType == CAM_STREAM_TYPE_ANALYSIS &&
5353 mColorArrangement != CAM_FILTER_ARRANGEMENT_Y) {
5354 mStreamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_PREVIEW,
5355 mDim.width, mDim.height, m_bUBWCenable, mIsType);
5356 }
5357
Thierry Strudel3d639192016-09-09 11:52:26 -07005358 rc = QCamera3Channel::addStream(mStreamType,
5359 mStreamFormat, mDim, ROTATE_0, MIN_STREAMING_BUFFER_NUM,
5360 mPostProcMask, mIsType);
5361 if (rc < 0) {
5362 LOGE("addStream failed");
5363 }
5364 return rc;
5365}
5366
5367int32_t QCamera3SupportChannel::request(buffer_handle_t * /*buffer*/,
Thierry Strudelc2ee3302016-11-17 12:33:12 -08005368 uint32_t /*frameNumber*/,
5369 int & /*indexUsed*/)
Thierry Strudel3d639192016-09-09 11:52:26 -07005370{
5371 return NO_ERROR;
5372}
5373
5374void QCamera3SupportChannel::streamCbRoutine(
5375 mm_camera_super_buf_t *super_frame,
5376 QCamera3Stream * /*stream*/)
5377{
5378 if (super_frame == NULL || super_frame->num_bufs != 1) {
5379 LOGE("super_frame is not valid");
5380 return;
5381 }
5382 bufDone(super_frame);
5383 free(super_frame);
5384}
5385
5386QCamera3StreamMem* QCamera3SupportChannel::getStreamBufs(uint32_t len)
5387{
5388 int rc;
5389 mMemory = new QCamera3StreamMem(mNumBuffers);
5390 if (!mMemory) {
5391 LOGE("unable to create heap memory");
5392 return NULL;
5393 }
5394 rc = mMemory->allocateAll(len);
5395 if (rc < 0) {
5396 LOGE("unable to allocate heap memory");
5397 delete mMemory;
5398 mMemory = NULL;
5399 return NULL;
5400 }
5401 return mMemory;
5402}
5403
5404void QCamera3SupportChannel::putStreamBufs()
5405{
5406 mMemory->deallocate();
5407 delete mMemory;
5408 mMemory = NULL;
5409}
5410
Emilian Peev7650c122017-01-19 08:24:33 -08005411QCamera3DepthChannel::~QCamera3DepthChannel() {
5412 unmapAllBuffers();
5413}
5414
5415/*===========================================================================
5416 * FUNCTION : mapBuffer
5417 *
5418 * DESCRIPTION: Maps stream depth buffer
5419 *
5420 * PARAMETERS :
5421 * @buffer : Depth buffer
5422 * @frameNumber : Frame number
5423 *
5424 *
5425 * RETURN : int32_t type of status
5426 * NO_ERROR -- success
5427 * none-zero failure code
5428 *==========================================================================*/
5429int32_t QCamera3DepthChannel::mapBuffer(buffer_handle_t *buffer,
5430 uint32_t frameNumber) {
5431 int32_t rc = NO_ERROR;
5432
5433 int32_t index = mGrallocMem.getMatchBufIndex((void*)buffer);
5434 if (0 > index) {
5435 rc = mGrallocMem.registerBuffer(buffer, CAM_STREAM_TYPE_DEFAULT);
5436 if (NO_ERROR != rc) {
5437 LOGE("Buffer registration failed %d", rc);
5438 return rc;
5439 }
5440
5441 index = mGrallocMem.getMatchBufIndex((void*)buffer);
5442 if (index < 0) {
5443 LOGE("Could not find object among registered buffers");
5444 return DEAD_OBJECT;
5445 }
5446 } else {
5447 LOGE("Buffer: %p is already present at index: %d!", buffer, index);
5448 return ALREADY_EXISTS;
5449 }
5450
5451 rc = mGrallocMem.markFrameNumber((uint32_t)index, frameNumber);
5452
5453 return rc;
5454}
5455
5456/*===========================================================================
5457 * FUNCTION : populateDepthData
5458 *
5459 * DESCRIPTION: Copies the incoming depth data in the respective depth buffer
5460 *
5461 * PARAMETERS :
5462 * @data : Incoming Depth data
5463 * @frameNumber : Frame number of incoming depth data
5464 *
5465 *
5466 * RETURN : int32_t type of status
5467 * NO_ERROR -- success
5468 * none-zero failure code
5469 *==========================================================================*/
5470int32_t QCamera3DepthChannel::populateDepthData(const cam_depth_data_t &data,
5471 uint32_t frameNumber) {
5472 if (nullptr == mStream) {
5473 LOGE("Invalid depth stream!");
5474 return BAD_VALUE;
5475 }
Emilian Peev7650c122017-01-19 08:24:33 -08005476
5477 ssize_t length = data.length;
5478 int32_t index = mGrallocMem.getBufferIndex(frameNumber);
5479 if (0 > index) {
5480 LOGE("Frame number: %u not present!");
5481 return BAD_VALUE;
5482 }
5483
5484 void *dst = mGrallocMem.getPtr(index);
5485 if (nullptr == dst) {
5486 LOGE("Invalid mapped buffer");
5487 return BAD_VALUE;
5488 }
5489
5490 camera3_jpeg_blob_t jpegHeader;
5491 ssize_t headerSize = sizeof jpegHeader;
5492 buffer_handle_t *blobBufferHandle = static_cast<buffer_handle_t *>
5493 (mGrallocMem.getBufferHandle(index));
5494 ssize_t maxBlobSize;
5495 if (nullptr != blobBufferHandle) {
5496 maxBlobSize = ((private_handle_t*)(*blobBufferHandle))->width;
5497 } else {
5498 LOGE("Couldn't query buffer handle!");
5499 return BAD_VALUE;
5500 }
5501
5502 if ((length + headerSize) > maxBlobSize) {
5503 LOGE("Depth buffer size mismatch expected: %d actual: %d",
5504 (length + headerSize), maxBlobSize);
5505 return BAD_VALUE;
5506 }
Emilian Peev656e4fa2017-06-02 16:47:04 +01005507
5508 if (0 < length) {
5509 memcpy(dst, data.depth_data, length);
5510 }
Emilian Peev7650c122017-01-19 08:24:33 -08005511
5512 memset(&jpegHeader, 0, headerSize);
5513 jpegHeader.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
5514 jpegHeader.jpeg_size = length;
5515 size_t jpeg_eof_offset = static_cast<size_t> (maxBlobSize - headerSize);
5516 uint8_t *jpegBuffer = static_cast<uint8_t *> (dst);
5517 uint8_t *jpegEOF = &jpegBuffer[jpeg_eof_offset];
5518 memcpy(jpegEOF, &jpegHeader, headerSize);
5519
5520 return NO_ERROR;
5521}
5522
5523/*===========================================================================
5524 * FUNCTION : getOldestFrame
5525 *
5526 * DESCRIPTION: Return oldest mapped buffer
5527 *
5528 * PARAMETERS :
5529 * @frameNumber : Sets oldest frame number if present
5530 *
5531 *
5532 * RETURN : buffer_handle_t pointer
5533 * NULL in case of error
5534 *==========================================================================*/
5535buffer_handle_t *QCamera3DepthChannel::getOldestFrame(uint32_t &frameNumber) {
5536 uint32_t oldestIndex = UINT32_MAX;
5537 int32_t frameNumberResult = mGrallocMem.getOldestFrameNumber(oldestIndex);
5538 if (0 > frameNumberResult) {
5539 LOGD("Invalid frame number!");
5540 return nullptr;
5541 }
5542 frameNumber = static_cast<uint32_t> (frameNumberResult);
5543
5544 buffer_handle_t *ret = static_cast<buffer_handle_t *>
5545 (mGrallocMem.getBufferHandle(oldestIndex));
5546 if (nullptr == ret) {
5547 LOGE("Invalid buffer handle!");
5548 return nullptr;
5549 }
5550
5551 return ret;
5552}
5553
5554/*===========================================================================
5555 * FUNCTION : unmapBuffer
5556 *
5557 * DESCRIPTION: Unmap a single buffer
5558 *
5559 * PARAMETERS :
5560 * @frameNumber : Frame number of buffer that should get unmapped
5561 *
5562 *
5563 * RETURN : int32_t type of status
5564 * NO_ERROR -- success
5565 * none-zero failure code
5566 *==========================================================================*/
5567int32_t QCamera3DepthChannel::unmapBuffer(uint32_t frameNumber) {
5568 int32_t index = mGrallocMem.getBufferIndex(frameNumber);
5569 if (0 > index) {
5570 LOGE("Frame number: %u not present!", frameNumber);
5571 return BAD_VALUE;
5572 }
5573
5574 return mGrallocMem.unregisterBuffer(index);
5575}
5576
5577/*===========================================================================
5578 * FUNCTION : unmapAllBuffers
5579 *
5580 * DESCRIPTION: This will unmap all buffers
5581 *
5582 * PARAMETERS :
5583 *
5584 * RETURN : int32_t type of status
5585 * NO_ERROR -- success
5586 * none-zero failure code
5587 *==========================================================================*/
5588int32_t QCamera3DepthChannel::unmapAllBuffers() {
5589 mGrallocMem.unregisterBuffers();
5590
5591 return NO_ERROR;
5592}
5593
Thierry Strudel3d639192016-09-09 11:52:26 -07005594}; // namespace qcamera