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