1 /* 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
30 #define LOG_TAG "QCamera3Channel"
31
32 // To remove
33 #include <cutils/properties.h>
34
35 // System dependencies
36 #include <fcntl.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include "gralloc.h"
40
41 // Camera dependencies
42 #include "QCamera3Channel.h"
43 #include "QCamera3HWI.h"
44 #include "QCameraTrace.h"
45
46 extern "C" {
47 #include "mm_camera_dbg.h"
48 }
49
50 using namespace android;
51
52 namespace qcamera {
53 #define IS_BUFFER_ERROR(x) (((x) & V4L2_BUF_FLAG_ERROR) == V4L2_BUF_FLAG_ERROR)
54
55 /*===========================================================================
56 * FUNCTION : QCamera3Channel
57 *
58 * DESCRIPTION: constrcutor of QCamera3Channel
59 *
60 * PARAMETERS :
61 * @cam_handle : camera handle
62 * @cam_ops : ptr to camera ops table
63 *
64 * RETURN : none
65 *==========================================================================*/
QCamera3Channel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,channel_cb_routine cb_routine,cam_padding_info_t * paddingInfo,uint32_t postprocess_mask,void * userData,uint32_t numBuffers)66 QCamera3Channel::QCamera3Channel(uint32_t cam_handle,
67 uint32_t channel_handle,
68 mm_camera_ops_t *cam_ops,
69 channel_cb_routine cb_routine,
70 cam_padding_info_t *paddingInfo,
71 uint32_t postprocess_mask,
72 void *userData, uint32_t numBuffers)
73 {
74 m_camHandle = cam_handle;
75 m_handle = channel_handle;
76 m_camOps = cam_ops;
77 m_bIsActive = false;
78
79 m_numStreams = 0;
80 memset(mStreams, 0, sizeof(mStreams));
81 mUserData = userData;
82
83 mStreamInfoBuf = NULL;
84 mChannelCB = cb_routine;
85 mPaddingInfo = *paddingInfo;
86 mPaddingInfo.offset_info.offset_x = 0;
87 mPaddingInfo.offset_info.offset_y = 0;
88
89 mPostProcMask = postprocess_mask;
90
91 mIsType = IS_TYPE_NONE;
92 mNumBuffers = numBuffers;
93 mPerFrameMapUnmapEnable = true;
94 dumpFrmCnt = 0;
95 }
96
97 /*===========================================================================
98 * FUNCTION : ~QCamera3Channel
99 *
100 * DESCRIPTION: destructor of QCamera3Channel
101 *
102 * PARAMETERS : none
103 *
104 * RETURN : none
105 *==========================================================================*/
~QCamera3Channel()106 QCamera3Channel::~QCamera3Channel()
107 {
108 }
109
110 /*===========================================================================
111 * FUNCTION : destroy
112 *
113 * DESCRIPTION: internal destructor of QCamera3Channel called by the subclasses
114 * this destructor will call pure virtual functions. stop will eventuall call
115 * QCamera3Stream::putBufs. The putBufs function will
116 * call QCamera3Channel::putStreamBufs which is pure virtual
117 *
118 * PARAMETERS : none
119 *
120 * RETURN : none
121 *==========================================================================*/
destroy()122 void QCamera3Channel::destroy()
123 {
124 if (m_bIsActive)
125 stop();
126
127 for (uint32_t i = 0; i < m_numStreams; i++) {
128 if (mStreams[i] != NULL) {
129 delete mStreams[i];
130 mStreams[i] = 0;
131 }
132 }
133 m_numStreams = 0;
134 }
135
136 /*===========================================================================
137 * FUNCTION : addStream
138 *
139 * DESCRIPTION: add a stream into channel
140 *
141 * PARAMETERS :
142 * @streamType : stream type
143 * @streamFormat : stream format
144 * @streamDim : stream dimension
145 * @streamRotation : rotation of the stream
146 * @minStreamBufNum : minimal buffer count for particular stream type
147 * @postprocessMask : post-proccess feature mask
148 * @isType : type of image stabilization required on the stream
149 *
150 * RETURN : int32_t type of status
151 * NO_ERROR -- success
152 * none-zero failure code
153 *==========================================================================*/
addStream(cam_stream_type_t streamType,cam_format_t streamFormat,cam_dimension_t streamDim,cam_rotation_t streamRotation,uint8_t minStreamBufNum,uint32_t postprocessMask,cam_is_type_t isType,uint32_t batchSize)154 int32_t QCamera3Channel::addStream(cam_stream_type_t streamType,
155 cam_format_t streamFormat,
156 cam_dimension_t streamDim,
157 cam_rotation_t streamRotation,
158 uint8_t minStreamBufNum,
159 uint32_t postprocessMask,
160 cam_is_type_t isType,
161 uint32_t batchSize)
162 {
163 int32_t rc = NO_ERROR;
164
165 if (m_numStreams >= 1) {
166 LOGE("Only one stream per channel supported in v3 Hal");
167 return BAD_VALUE;
168 }
169
170 if (m_numStreams >= MAX_STREAM_NUM_IN_BUNDLE) {
171 LOGE("stream number (%d) exceeds max limit (%d)",
172 m_numStreams, MAX_STREAM_NUM_IN_BUNDLE);
173 return BAD_VALUE;
174 }
175 QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
176 m_handle,
177 m_camOps,
178 &mPaddingInfo,
179 this);
180 if (pStream == NULL) {
181 LOGE("No mem for Stream");
182 return NO_MEMORY;
183 }
184 LOGD("batch size is %d", batchSize);
185
186 rc = pStream->init(streamType, streamFormat, streamDim, streamRotation,
187 NULL, minStreamBufNum, postprocessMask, isType, batchSize,
188 streamCbRoutine, this);
189 if (rc == 0) {
190 mStreams[m_numStreams] = pStream;
191 m_numStreams++;
192 } else {
193 delete pStream;
194 }
195 return rc;
196 }
197
198 /*===========================================================================
199 * FUNCTION : start
200 *
201 * DESCRIPTION: start channel, which will start all streams belong to this channel
202 *
203 * PARAMETERS :
204 *
205 * RETURN : int32_t type of status
206 * NO_ERROR -- success
207 * none-zero failure code
208 *==========================================================================*/
start()209 int32_t QCamera3Channel::start()
210 {
211 ATRACE_CALL();
212 int32_t rc = NO_ERROR;
213
214 if (m_numStreams > 1) {
215 LOGW("bundle not supported");
216 } else if (m_numStreams == 0) {
217 return NO_INIT;
218 }
219
220 if(m_bIsActive) {
221 LOGW("Attempt to start active channel");
222 return rc;
223 }
224
225 for (uint32_t i = 0; i < m_numStreams; i++) {
226 if (mStreams[i] != NULL) {
227 mStreams[i]->start();
228 }
229 }
230
231 m_bIsActive = true;
232
233 return rc;
234 }
235
236 /*===========================================================================
237 * FUNCTION : stop
238 *
239 * DESCRIPTION: stop a channel, which will stop all streams belong to this channel
240 *
241 * PARAMETERS : none
242 *
243 * RETURN : int32_t type of status
244 * NO_ERROR -- success
245 * none-zero failure code
246 *==========================================================================*/
stop()247 int32_t QCamera3Channel::stop()
248 {
249 ATRACE_CALL();
250 int32_t rc = NO_ERROR;
251 if(!m_bIsActive) {
252 LOGE("Attempt to stop inactive channel");
253 return rc;
254 }
255
256 for (uint32_t i = 0; i < m_numStreams; i++) {
257 if (mStreams[i] != NULL) {
258 mStreams[i]->stop();
259 }
260 }
261
262 m_bIsActive = false;
263 return rc;
264 }
265
266 /*===========================================================================
267 * FUNCTION : setBatchSize
268 *
269 * DESCRIPTION: Set batch size for the channel. This is a dummy implementation
270 * for the base class
271 *
272 * PARAMETERS :
273 * @batchSize : Number of image buffers in a batch
274 *
275 * RETURN : int32_t type of status
276 * NO_ERROR -- success always
277 * none-zero failure code
278 *==========================================================================*/
setBatchSize(uint32_t batchSize)279 int32_t QCamera3Channel::setBatchSize(uint32_t batchSize)
280 {
281 LOGD("Dummy method. batchSize: %d unused ", batchSize);
282 return NO_ERROR;
283 }
284
285 /*===========================================================================
286 * FUNCTION : queueBatchBuf
287 *
288 * DESCRIPTION: This is a dummy implementation for the base class
289 *
290 * PARAMETERS :
291 *
292 * RETURN : int32_t type of status
293 * NO_ERROR -- success always
294 * none-zero failure code
295 *==========================================================================*/
queueBatchBuf()296 int32_t QCamera3Channel::queueBatchBuf()
297 {
298 LOGD("Dummy method. Unused ");
299 return NO_ERROR;
300 }
301
302 /*===========================================================================
303 * FUNCTION : setPerFrameMapUnmap
304 *
305 * DESCRIPTION: Sets internal enable flag
306 *
307 * PARAMETERS :
308 * @enable : Bool value for the enable flag
309 *
310 * RETURN : int32_t type of status
311 * NO_ERROR -- success always
312 * none-zero failure code
313 *==========================================================================*/
setPerFrameMapUnmap(bool enable)314 int32_t QCamera3Channel::setPerFrameMapUnmap(bool enable)
315 {
316 mPerFrameMapUnmapEnable = enable;
317 return NO_ERROR;
318 }
319
320 /*===========================================================================
321 * FUNCTION : flush
322 *
323 * DESCRIPTION: flush a channel
324 *
325 * PARAMETERS : none
326 *
327 * RETURN : int32_t type of status
328 * NO_ERROR -- success
329 * none-zero failure code
330 *==========================================================================*/
flush()331 int32_t QCamera3Channel::flush()
332 {
333 ATRACE_CALL();
334 return NO_ERROR;
335 }
336
337 /*===========================================================================
338 * FUNCTION : bufDone
339 *
340 * DESCRIPTION: return a stream buf back to kernel
341 *
342 * PARAMETERS :
343 * @recvd_frame : stream buf frame to be returned
344 *
345 * RETURN : int32_t type of status
346 * NO_ERROR -- success
347 * none-zero failure code
348 *==========================================================================*/
bufDone(mm_camera_super_buf_t * recvd_frame)349 int32_t QCamera3Channel::bufDone(mm_camera_super_buf_t *recvd_frame)
350 {
351 int32_t rc = NO_ERROR;
352 for (uint32_t i = 0; i < recvd_frame->num_bufs; i++) {
353 if (recvd_frame->bufs[i] != NULL) {
354 for (uint32_t j = 0; j < m_numStreams; j++) {
355 if (mStreams[j] != NULL &&
356 mStreams[j]->getMyHandle() == recvd_frame->bufs[i]->stream_id) {
357 rc = mStreams[j]->bufDone(recvd_frame->bufs[i]->buf_idx);
358 break; // break loop j
359 }
360 }
361 }
362 }
363
364 return rc;
365 }
366
setBundleInfo(const cam_bundle_config_t & bundleInfo)367 int32_t QCamera3Channel::setBundleInfo(const cam_bundle_config_t &bundleInfo)
368 {
369 int32_t rc = NO_ERROR;
370 cam_stream_parm_buffer_t param;
371 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t));
372 param.type = CAM_STREAM_PARAM_TYPE_SET_BUNDLE_INFO;
373 param.bundleInfo = bundleInfo;
374 rc = mStreams[0]->setParameter(param);
375 if (rc != NO_ERROR) {
376 LOGE("stream setParameter for set bundle failed");
377 }
378
379 return rc;
380 }
381
382 /*===========================================================================
383 * FUNCTION : getStreamTypeMask
384 *
385 * DESCRIPTION: Get bit mask of all stream types in this channel
386 *
387 * PARAMETERS : None
388 *
389 * RETURN : Bit mask of all stream types in this channel
390 *==========================================================================*/
getStreamTypeMask()391 uint32_t QCamera3Channel::getStreamTypeMask()
392 {
393 uint32_t mask = 0;
394 for (uint32_t i = 0; i < m_numStreams; i++) {
395 mask |= (1U << mStreams[i]->getMyType());
396 }
397 return mask;
398 }
399
400 /*===========================================================================
401 * FUNCTION : getStreamID
402 *
403 * DESCRIPTION: Get StreamID of requested stream type
404 *
405 * PARAMETERS : streamMask
406 *
407 * RETURN : Stream ID
408 *==========================================================================*/
getStreamID(uint32_t streamMask)409 uint32_t QCamera3Channel::getStreamID(uint32_t streamMask)
410 {
411 uint32_t streamID = 0;
412 for (uint32_t i = 0; i < m_numStreams; i++) {
413 if (streamMask == (uint32_t )(0x1 << mStreams[i]->getMyType())) {
414 streamID = mStreams[i]->getMyServerID();
415 break;
416 }
417 }
418 return streamID;
419 }
420
421 /*===========================================================================
422 * FUNCTION : getStreamByHandle
423 *
424 * DESCRIPTION: return stream object by stream handle
425 *
426 * PARAMETERS :
427 * @streamHandle : stream handle
428 *
429 * RETURN : stream object. NULL if not found
430 *==========================================================================*/
getStreamByHandle(uint32_t streamHandle)431 QCamera3Stream *QCamera3Channel::getStreamByHandle(uint32_t streamHandle)
432 {
433 for (uint32_t i = 0; i < m_numStreams; i++) {
434 if (mStreams[i] != NULL && mStreams[i]->getMyHandle() == streamHandle) {
435 return mStreams[i];
436 }
437 }
438 return NULL;
439 }
440
441 /*===========================================================================
442 * FUNCTION : getStreamByIndex
443 *
444 * DESCRIPTION: return stream object by index
445 *
446 * PARAMETERS :
447 * @streamHandle : stream handle
448 *
449 * RETURN : stream object. NULL if not found
450 *==========================================================================*/
getStreamByIndex(uint32_t index)451 QCamera3Stream *QCamera3Channel::getStreamByIndex(uint32_t index)
452 {
453 if (index < m_numStreams) {
454 return mStreams[index];
455 }
456 return NULL;
457 }
458
459 /*===========================================================================
460 * FUNCTION : streamCbRoutine
461 *
462 * DESCRIPTION: callback routine for stream
463 *
464 * PARAMETERS :
465 * @streamHandle : stream handle
466 *
467 * RETURN : stream object. NULL if not found
468 *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream,void * userdata)469 void QCamera3Channel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
470 QCamera3Stream *stream, void *userdata)
471 {
472 QCamera3Channel *channel = (QCamera3Channel *)userdata;
473 if (channel == NULL) {
474 LOGE("invalid channel pointer");
475 return;
476 }
477 channel->streamCbRoutine(super_frame, stream);
478 }
479
480 /*===========================================================================
481 * FUNCTION : dumpYUV
482 *
483 * DESCRIPTION: function to dump the YUV data from ISP/pproc
484 *
485 * PARAMETERS :
486 * @frame : frame to be dumped
487 * @dim : dimension of the stream
488 * @offset : offset of the data
489 * @name : 1 if it is ISP output/pproc input, 2 if it is pproc output
490 *
491 * RETURN :
492 *==========================================================================*/
dumpYUV(mm_camera_buf_def_t * frame,cam_dimension_t dim,cam_frame_len_offset_t offset,uint8_t dump_type)493 void QCamera3Channel::dumpYUV(mm_camera_buf_def_t *frame, cam_dimension_t dim,
494 cam_frame_len_offset_t offset, uint8_t dump_type)
495 {
496 char buf[FILENAME_MAX];
497 memset(buf, 0, sizeof(buf));
498 static int counter = 0;
499 char prop[PROPERTY_VALUE_MAX];
500 property_get("persist.camera.dumpimg", prop, "0");
501 mYUVDump = (uint8_t) atoi(prop);
502 if (mYUVDump & dump_type) {
503 frm_num = ((mYUVDump & 0xffff0000) >> 16);
504 if (frm_num == 0) {
505 frm_num = 10;
506 }
507 if (frm_num > 256) {
508 frm_num = 256;
509 }
510 skip_mode = ((mYUVDump & 0x0000ff00) >> 8);
511 if (skip_mode == 0) {
512 skip_mode = 1;
513 }
514 if (mDumpSkipCnt == 0) {
515 mDumpSkipCnt = 1;
516 }
517 if (mDumpSkipCnt % skip_mode == 0) {
518 if (dumpFrmCnt <= frm_num) {
519 /* Note that the image dimension will be the unrotated stream dimension.
520 * If you feel that the image would have been rotated during reprocess
521 * then swap the dimensions while opening the file
522 * */
523 switch (dump_type) {
524 case QCAMERA_DUMP_FRM_PREVIEW:
525 snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"p_%d_%d_%dx%d.yuv",
526 counter, frame->frame_idx, dim.width, dim.height);
527 break;
528 case QCAMERA_DUMP_FRM_VIDEO:
529 snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"v_%d_%d_%dx%d.yuv",
530 counter, frame->frame_idx, dim.width, dim.height);
531 break;
532 case QCAMERA_DUMP_FRM_SNAPSHOT:
533 snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"s_%d_%d_%dx%d.yuv",
534 counter, frame->frame_idx, dim.width, dim.height);
535 break;
536 case QCAMERA_DUMP_FRM_INPUT_REPROCESS:
537 snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"ir_%d_%d_%dx%d.yuv",
538 counter, frame->frame_idx, dim.width, dim.height);
539 break;
540 case QCAMERA_DUMP_FRM_CALLBACK:
541 snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"c_%d_%d_%dx%d.yuv",
542 counter, frame->frame_idx, dim.width, dim.height);
543 break;
544 default :
545 LOGE("dumping not enabled for stream type %d",dump_type);
546 break;
547 }
548 counter++;
549 int file_fd = open(buf, O_RDWR | O_CREAT, 0777);
550 ssize_t written_len = 0;
551 if (file_fd >= 0) {
552 void *data = NULL;
553 fchmod(file_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
554 for (uint32_t i = 0; i < offset.num_planes; i++) {
555 uint32_t index = offset.mp[i].offset;
556 if (i > 0) {
557 index += offset.mp[i-1].len;
558 }
559 for (int j = 0; j < offset.mp[i].height; j++) {
560 data = (void *)((uint8_t *)frame->buffer + index);
561 written_len += write(file_fd, data,
562 (size_t)offset.mp[i].width);
563 index += (uint32_t)offset.mp[i].stride;
564 }
565 }
566 LOGH("written number of bytes %ld\n", written_len);
567 dumpFrmCnt++;
568 close(file_fd);
569 } else {
570 LOGE("failed to open file to dump image");
571 }
572 }
573 } else {
574 mDumpSkipCnt++;
575 }
576 }
577 }
578
579 /*===========================================================================
580 * FUNCTION : isUBWCEnabled
581 *
582 * DESCRIPTION: Function to get UBWC hardware support.
583 *
584 * PARAMETERS : None
585 *
586 * RETURN : TRUE -- UBWC format supported
587 * FALSE -- UBWC is not supported.
588 *==========================================================================*/
isUBWCEnabled()589 bool QCamera3Channel::isUBWCEnabled()
590 {
591 #ifdef UBWC_PRESENT
592 char value[PROPERTY_VALUE_MAX];
593 int prop_value = 0;
594 memset(value, 0, sizeof(value));
595 property_get("debug.gralloc.gfx_ubwc_disable", value, "0");
596 prop_value = atoi(value);
597 if (prop_value) {
598 return FALSE;
599 }
600
601 //Disable UBWC if Eztune is enabled
602 //EzTune process CPP output frame and cannot understand UBWC.
603 memset(value, 0, sizeof(value));
604 property_get("persist.camera.eztune.enable", value, "0");
605 prop_value = atoi(value);
606 if (prop_value) {
607 return FALSE;
608 }
609 return TRUE;
610 #else
611 return FALSE;
612 #endif
613 }
614
615 /*===========================================================================
616 * FUNCTION : getStreamDefaultFormat
617 *
618 * DESCRIPTION: return default buffer format for the stream
619 *
620 * PARAMETERS : type : Stream type
621 *
622 ** RETURN : format for stream type
623 *
624 *==========================================================================*/
getStreamDefaultFormat(cam_stream_type_t type)625 cam_format_t QCamera3Channel::getStreamDefaultFormat(cam_stream_type_t type)
626 {
627 cam_format_t streamFormat;
628
629 switch (type) {
630 case CAM_STREAM_TYPE_PREVIEW:
631 if (isUBWCEnabled()) {
632 char prop[PROPERTY_VALUE_MAX];
633 int pFormat;
634 memset(prop, 0, sizeof(prop));
635 property_get("persist.camera.preview.ubwc", prop, "1");
636 pFormat = atoi(prop);
637 if (pFormat == 1) {
638 streamFormat = CAM_FORMAT_YUV_420_NV12_UBWC;
639 } else {
640 streamFormat = CAM_FORMAT_YUV_420_NV12_VENUS;
641 }
642 } else {
643 streamFormat = CAM_FORMAT_YUV_420_NV12_VENUS;
644 }
645 break;
646 case CAM_STREAM_TYPE_VIDEO:
647 if (isUBWCEnabled()) {
648 char prop[PROPERTY_VALUE_MAX];
649 int pFormat;
650 memset(prop, 0, sizeof(prop));
651 property_get("persist.camera.video.ubwc", prop, "1");
652 pFormat = atoi(prop);
653 if (pFormat == 1) {
654 streamFormat = CAM_FORMAT_YUV_420_NV12_UBWC;
655 } else {
656 streamFormat = CAM_FORMAT_YUV_420_NV12_VENUS;
657 }
658 } else {
659 #if VENUS_PRESENT
660 streamFormat = CAM_FORMAT_YUV_420_NV12_VENUS;
661 #else
662 streamFormat = CAM_FORMAT_YUV_420_NV12;
663 #endif
664 }
665 break;
666 case CAM_STREAM_TYPE_SNAPSHOT:
667 streamFormat = CAM_FORMAT_YUV_420_NV21;
668 break;
669 case CAM_STREAM_TYPE_CALLBACK:
670 streamFormat = CAM_FORMAT_YUV_420_NV21;
671 break;
672 case CAM_STREAM_TYPE_RAW:
673 streamFormat = CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG;
674 break;
675 default:
676 streamFormat = CAM_FORMAT_YUV_420_NV21;
677 break;
678 }
679 return streamFormat;
680 }
681
682
683 /* QCamera3ProcessingChannel methods */
684
685 /*===========================================================================
686 * FUNCTION : QCamera3ProcessingChannel
687 *
688 * DESCRIPTION: constructor of QCamera3ProcessingChannel
689 *
690 * PARAMETERS :
691 * @cam_handle : camera handle
692 * @cam_ops : ptr to camera ops table
693 * @cb_routine : callback routine to frame aggregator
694 * @paddingInfo: stream padding info
695 * @userData : HWI handle
696 * @stream : camera3_stream_t structure
697 * @stream_type: Channel stream type
698 * @postprocess_mask: the postprocess mask for streams of this channel
699 * @metadataChannel: handle to the metadataChannel
700 * @numBuffers : number of max dequeued buffers
701 * RETURN : none
702 *==========================================================================*/
QCamera3ProcessingChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,channel_cb_routine cb_routine,cam_padding_info_t * paddingInfo,void * userData,camera3_stream_t * stream,cam_stream_type_t stream_type,uint32_t postprocess_mask,QCamera3Channel * metadataChannel,uint32_t numBuffers)703 QCamera3ProcessingChannel::QCamera3ProcessingChannel(uint32_t cam_handle,
704 uint32_t channel_handle,
705 mm_camera_ops_t *cam_ops,
706 channel_cb_routine cb_routine,
707 cam_padding_info_t *paddingInfo,
708 void *userData,
709 camera3_stream_t *stream,
710 cam_stream_type_t stream_type,
711 uint32_t postprocess_mask,
712 QCamera3Channel *metadataChannel,
713 uint32_t numBuffers) :
714 QCamera3Channel(cam_handle, channel_handle, cam_ops, cb_routine,
715 paddingInfo, postprocess_mask, userData, numBuffers),
716 m_postprocessor(this),
717 mFrameCount(0),
718 mLastFrameCount(0),
719 mLastFpsTime(0),
720 mMemory(numBuffers),
721 mCamera3Stream(stream),
722 mNumBufs(CAM_MAX_NUM_BUFS_PER_STREAM),
723 mStreamType(stream_type),
724 mPostProcStarted(false),
725 mInputBufferConfig(false),
726 m_pMetaChannel(metadataChannel),
727 mMetaFrame(NULL),
728 mOfflineMemory(0),
729 mOfflineMetaMemory(numBuffers + (MAX_REPROCESS_PIPELINE_STAGES - 1),
730 false)
731 {
732 char prop[PROPERTY_VALUE_MAX];
733 property_get("persist.debug.sf.showfps", prop, "0");
734 mDebugFPS = (uint8_t) atoi(prop);
735
736 int32_t rc = m_postprocessor.init(&mMemory, mPostProcMask);
737 if (rc != 0) {
738 LOGE("Init Postprocessor failed");
739 }
740 }
741
742 /*===========================================================================
743 * FUNCTION : ~QCamera3ProcessingChannel
744 *
745 * DESCRIPTION: destructor of QCamera3ProcessingChannel
746 *
747 * PARAMETERS : none
748 *
749 * RETURN : none
750 *==========================================================================*/
~QCamera3ProcessingChannel()751 QCamera3ProcessingChannel::~QCamera3ProcessingChannel()
752 {
753 destroy();
754
755 int32_t rc = m_postprocessor.deinit();
756 if (rc != 0) {
757 LOGE("De-init Postprocessor failed");
758 }
759
760 if (0 < mOfflineMetaMemory.getCnt()) {
761 mOfflineMetaMemory.deallocate();
762 }
763 if (0 < mOfflineMemory.getCnt()) {
764 mOfflineMemory.unregisterBuffers();
765 }
766
767 }
768
769 /*===========================================================================
770 * FUNCTION : streamCbRoutine
771 *
772 * DESCRIPTION:
773 *
774 * PARAMETERS :
775 * @super_frame : the super frame with filled buffer
776 * @stream : stream on which the buffer was requested and filled
777 *
778 * RETURN : none
779 *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)780 void QCamera3ProcessingChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
781 QCamera3Stream *stream)
782 {
783 ATRACE_CALL();
784 //FIXME Q Buf back in case of error?
785 uint8_t frameIndex;
786 buffer_handle_t *resultBuffer;
787 int32_t resultFrameNumber;
788 camera3_stream_buffer_t result;
789 cam_dimension_t dim;
790 cam_frame_len_offset_t offset;
791
792 memset(&dim, 0, sizeof(dim));
793 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
794 if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
795 LOGE("Error with the stream callback");
796 return;
797 }
798
799 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
800 if(frameIndex >= mNumBufs) {
801 LOGE("Error, Invalid index for buffer");
802 stream->bufDone(frameIndex);
803 return;
804 }
805
806 if (mDebugFPS) {
807 showDebugFPS(stream->getMyType());
808 }
809 stream->getFrameDimension(dim);
810 stream->getFrameOffset(offset);
811 if (stream->getMyType() == CAM_STREAM_TYPE_PREVIEW) {
812 dumpYUV(super_frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_PREVIEW);
813 } else if (stream->getMyType() == CAM_STREAM_TYPE_VIDEO) {
814 dumpYUV(super_frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_VIDEO);
815 } else if (stream->getMyType() == CAM_STREAM_TYPE_CALLBACK) {
816 dumpYUV(super_frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_CALLBACK);
817 }
818 ////Use below data to issue framework callback
819 resultBuffer = (buffer_handle_t *)mMemory.getBufferHandle(frameIndex);
820 resultFrameNumber = mMemory.getFrameNumber(frameIndex);
821
822 result.stream = mCamera3Stream;
823 result.buffer = resultBuffer;
824 if (IS_BUFFER_ERROR(super_frame->bufs[0]->flags)) {
825 result.status = CAMERA3_BUFFER_STATUS_ERROR;
826 LOGW("CAMERA3_BUFFER_STATUS_ERROR for stream_type: %d",
827 mStreams[0]->getMyType());
828 } else {
829 result.status = CAMERA3_BUFFER_STATUS_OK;
830 }
831 result.acquire_fence = -1;
832 result.release_fence = -1;
833 if(mPerFrameMapUnmapEnable) {
834 int32_t rc = stream->bufRelease(frameIndex);
835 if (NO_ERROR != rc) {
836 LOGE("Error %d releasing stream buffer %d",
837 rc, frameIndex);
838 }
839
840 rc = mMemory.unregisterBuffer(frameIndex);
841 if (NO_ERROR != rc) {
842 LOGE("Error %d unregistering stream buffer %d",
843 rc, frameIndex);
844 }
845 }
846
847 if (0 <= resultFrameNumber) {
848 if (mChannelCB) {
849 mChannelCB(NULL, &result, (uint32_t)resultFrameNumber, false, mUserData);
850 }
851 } else {
852 LOGE("Bad frame number");
853 }
854 free(super_frame);
855 return;
856 }
857
858 /*===========================================================================
859 * FUNCTION : putStreamBufs
860 *
861 * DESCRIPTION: release the buffers allocated to the stream
862 *
863 * PARAMETERS : NONE
864 *
865 * RETURN : NONE
866 *==========================================================================*/
putStreamBufs()867 void QCamera3YUVChannel::putStreamBufs()
868 {
869 QCamera3ProcessingChannel::putStreamBufs();
870
871 // Free allocated heap buffer.
872 mMemory.deallocate();
873 // Clear free heap buffer list.
874 mFreeHeapBufferList.clear();
875 // Clear offlinePpInfoList
876 mOfflinePpInfoList.clear();
877 }
878
879 /*===========================================================================
880 * FUNCTION : request
881 *
882 * DESCRIPTION: handle the request - either with an input buffer or a direct
883 * output request
884 *
885 * PARAMETERS :
886 * @buffer : pointer to the output buffer
887 * @frameNumber : frame number of the request
888 * @pInputBuffer : pointer to input buffer if an input request
889 * @metadata : parameters associated with the request
890 *
891 * RETURN : 0 on a success start of capture
892 * -EINVAL on invalid input
893 * -ENODEV on serious error
894 *==========================================================================*/
request(buffer_handle_t * buffer,uint32_t frameNumber,camera3_stream_buffer_t * pInputBuffer,metadata_buffer_t * metadata)895 int32_t QCamera3ProcessingChannel::request(buffer_handle_t *buffer,
896 uint32_t frameNumber,
897 camera3_stream_buffer_t* pInputBuffer,
898 metadata_buffer_t* metadata)
899 {
900 int32_t rc = NO_ERROR;
901 int index;
902
903 if (NULL == buffer || NULL == metadata) {
904 LOGE("Invalid buffer/metadata in channel request");
905 return BAD_VALUE;
906 }
907
908 if (pInputBuffer) {
909 //need to send to reprocessing
910 LOGD("Got a request with input buffer, output streamType = %d", mStreamType);
911 reprocess_config_t reproc_cfg;
912 cam_dimension_t dim;
913 memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
914 memset(&dim, 0, sizeof(dim));
915 setReprocConfig(reproc_cfg, pInputBuffer, metadata, mStreamFormat, dim);
916 startPostProc(reproc_cfg);
917
918 qcamera_fwk_input_pp_data_t *src_frame = NULL;
919 src_frame = (qcamera_fwk_input_pp_data_t *)calloc(1,
920 sizeof(qcamera_fwk_input_pp_data_t));
921 if (src_frame == NULL) {
922 LOGE("No memory for src frame");
923 return NO_MEMORY;
924 }
925 rc = setFwkInputPPData(src_frame, pInputBuffer, &reproc_cfg, metadata, buffer, frameNumber);
926 if (NO_ERROR != rc) {
927 LOGE("Error %d while setting framework input PP data", rc);
928 free(src_frame);
929 return rc;
930 }
931 LOGH("Post-process started");
932 m_postprocessor.processData(src_frame);
933 } else {
934 //need to fill output buffer with new data and return
935 if(!m_bIsActive) {
936 rc = registerBuffer(buffer, mIsType);
937 if (NO_ERROR != rc) {
938 LOGE("On-the-fly buffer registration failed %d",
939 rc);
940 return rc;
941 }
942
943 rc = start();
944 if (NO_ERROR != rc)
945 return rc;
946 } else {
947 LOGD("Request on an existing stream");
948 }
949
950 index = mMemory.getMatchBufIndex((void*)buffer);
951 if(index < 0) {
952 rc = registerBuffer(buffer, mIsType);
953 if (NO_ERROR != rc) {
954 LOGE("On-the-fly buffer registration failed %d",
955 rc);
956 return rc;
957 }
958
959 index = mMemory.getMatchBufIndex((void*)buffer);
960 if (index < 0) {
961 LOGE("Could not find object among registered buffers");
962 return DEAD_OBJECT;
963 }
964 }
965 rc = mStreams[0]->bufDone(index);
966 if(rc != NO_ERROR) {
967 LOGE("Failed to Q new buffer to stream");
968 return rc;
969 }
970 rc = mMemory.markFrameNumber(index, frameNumber);
971 }
972 return rc;
973 }
974
975 /*===========================================================================
976 * FUNCTION : initialize
977 *
978 * DESCRIPTION:
979 *
980 * PARAMETERS : isType : type of image stabilization on the buffer
981 *
982 * RETURN : int32_t type of status
983 * NO_ERROR -- success
984 * none-zero failure code
985 *==========================================================================*/
initialize(__unused cam_is_type_t isType)986 int32_t QCamera3ProcessingChannel::initialize(__unused cam_is_type_t isType)
987 {
988 int32_t rc = NO_ERROR;
989 rc = mOfflineMetaMemory.allocateAll(sizeof(metadata_buffer_t));
990 if (rc == NO_ERROR) {
991 Mutex::Autolock lock(mFreeOfflineMetaBuffersLock);
992 mFreeOfflineMetaBuffersList.clear();
993 for (uint32_t i = 0; i < mNumBuffers + (MAX_REPROCESS_PIPELINE_STAGES - 1);
994 i++) {
995 mFreeOfflineMetaBuffersList.push_back(i);
996 }
997 } else {
998 LOGE("Could not allocate offline meta buffers for input reprocess");
999 }
1000 return rc;
1001 }
1002
1003 /*===========================================================================
1004 * FUNCTION : registerBuffer
1005 *
1006 * DESCRIPTION: register streaming buffer to the channel object
1007 *
1008 * PARAMETERS :
1009 * @buffer : buffer to be registered
1010 * @isType : image stabilization type on the stream
1011 *
1012 * RETURN : int32_t type of status
1013 * NO_ERROR -- success
1014 * none-zero failure code
1015 *==========================================================================*/
registerBuffer(buffer_handle_t * buffer,cam_is_type_t isType)1016 int32_t QCamera3ProcessingChannel::registerBuffer(buffer_handle_t *buffer,
1017 cam_is_type_t isType)
1018 {
1019 ATRACE_CALL();
1020 int rc = 0;
1021 mIsType = isType;
1022 cam_stream_type_t streamType;
1023
1024 if ((uint32_t)mMemory.getCnt() > (mNumBufs - 1)) {
1025 LOGE("Trying to register more buffers than initially requested");
1026 return BAD_VALUE;
1027 }
1028
1029 if (0 == m_numStreams) {
1030 rc = initialize(mIsType);
1031 if (rc != NO_ERROR) {
1032 LOGE("Couldn't initialize camera stream %d", rc);
1033 return rc;
1034 }
1035 }
1036
1037 streamType = mStreams[0]->getMyType();
1038 rc = mMemory.registerBuffer(buffer, streamType);
1039 if (ALREADY_EXISTS == rc) {
1040 return NO_ERROR;
1041 } else if (NO_ERROR != rc) {
1042 LOGE("Buffer %p couldn't be registered %d", buffer, rc);
1043 return rc;
1044 }
1045
1046 return rc;
1047 }
1048
1049 /*===========================================================================
1050 * FUNCTION : setFwkInputPPData
1051 *
1052 * DESCRIPTION: fill out the framework src frame information for reprocessing
1053 *
1054 * PARAMETERS :
1055 * @src_frame : input pp data to be filled out
1056 * @pInputBuffer : input buffer for reprocessing
1057 * @reproc_cfg : pointer to the reprocess config
1058 * @metadata : pointer to the metadata buffer
1059 * @output_buffer : output buffer for reprocessing; could be NULL if not
1060 * framework allocated
1061 * @frameNumber : frame number of the request
1062 *
1063 * RETURN : int32_t type of status
1064 * NO_ERROR -- success
1065 * none-zero failure code
1066 *==========================================================================*/
setFwkInputPPData(qcamera_fwk_input_pp_data_t * src_frame,camera3_stream_buffer_t * pInputBuffer,reprocess_config_t * reproc_cfg,metadata_buffer_t * metadata,buffer_handle_t * output_buffer,uint32_t frameNumber)1067 int32_t QCamera3ProcessingChannel::setFwkInputPPData(qcamera_fwk_input_pp_data_t *src_frame,
1068 camera3_stream_buffer_t *pInputBuffer, reprocess_config_t *reproc_cfg,
1069 metadata_buffer_t *metadata, buffer_handle_t *output_buffer,
1070 uint32_t frameNumber)
1071 {
1072 int32_t rc = NO_ERROR;
1073 int input_index = mOfflineMemory.getMatchBufIndex((void*)pInputBuffer->buffer);
1074 if(input_index < 0) {
1075 rc = mOfflineMemory.registerBuffer(pInputBuffer->buffer, mStreamType);
1076 if (NO_ERROR != rc) {
1077 LOGE("On-the-fly input buffer registration failed %d",
1078 rc);
1079 return rc;
1080 }
1081 input_index = mOfflineMemory.getMatchBufIndex((void*)pInputBuffer->buffer);
1082 if (input_index < 0) {
1083 LOGE("Could not find object among registered buffers");
1084 return DEAD_OBJECT;
1085 }
1086 }
1087 mOfflineMemory.markFrameNumber(input_index, frameNumber);
1088
1089 src_frame->src_frame = *pInputBuffer;
1090 rc = mOfflineMemory.getBufDef(reproc_cfg->input_stream_plane_info.plane_info,
1091 src_frame->input_buffer, input_index);
1092 if (rc != 0) {
1093 return rc;
1094 }
1095 dumpYUV(&src_frame->input_buffer, reproc_cfg->input_stream_dim,
1096 reproc_cfg->input_stream_plane_info.plane_info, QCAMERA_DUMP_FRM_INPUT_REPROCESS);
1097 cam_dimension_t dim = {sizeof(metadata_buffer_t), 1};
1098 cam_stream_buf_plane_info_t meta_planes;
1099 rc = mm_stream_calc_offset_metadata(&dim, &mPaddingInfo, &meta_planes);
1100 if (rc != 0) {
1101 LOGE("Metadata stream plane info calculation failed!");
1102 return rc;
1103 }
1104 uint32_t metaBufIdx;
1105 {
1106 Mutex::Autolock lock(mFreeOfflineMetaBuffersLock);
1107 if (mFreeOfflineMetaBuffersList.empty()) {
1108 LOGE("mFreeOfflineMetaBuffersList is null. Fatal");
1109 return BAD_VALUE;
1110 }
1111
1112 metaBufIdx = *(mFreeOfflineMetaBuffersList.begin());
1113 mFreeOfflineMetaBuffersList.erase(mFreeOfflineMetaBuffersList.begin());
1114 LOGD("erasing %d, mFreeOfflineMetaBuffersList.size %d", metaBufIdx,
1115 mFreeOfflineMetaBuffersList.size());
1116 }
1117
1118 mOfflineMetaMemory.markFrameNumber(metaBufIdx, frameNumber);
1119
1120 mm_camera_buf_def_t meta_buf;
1121 cam_frame_len_offset_t offset = meta_planes.plane_info;
1122 rc = mOfflineMetaMemory.getBufDef(offset, meta_buf, metaBufIdx);
1123 if (NO_ERROR != rc) {
1124 return rc;
1125 }
1126 memcpy(meta_buf.buffer, metadata, sizeof(metadata_buffer_t));
1127 src_frame->metadata_buffer = meta_buf;
1128 src_frame->reproc_config = *reproc_cfg;
1129 src_frame->output_buffer = output_buffer;
1130 src_frame->frameNumber = frameNumber;
1131 return rc;
1132 }
1133
1134 /*===========================================================================
1135 * FUNCTION : checkStreamCbErrors
1136 *
1137 * DESCRIPTION: check the stream callback for errors
1138 *
1139 * PARAMETERS :
1140 * @super_frame : the super frame with filled buffer
1141 * @stream : stream on which the buffer was requested and filled
1142 *
1143 * RETURN : int32_t type of status
1144 * NO_ERROR -- success
1145 * none-zero failure code
1146 *==========================================================================*/
checkStreamCbErrors(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)1147 int32_t QCamera3ProcessingChannel::checkStreamCbErrors(mm_camera_super_buf_t *super_frame,
1148 QCamera3Stream *stream)
1149 {
1150 if (NULL == stream) {
1151 LOGE("Invalid stream");
1152 return BAD_VALUE;
1153 }
1154
1155 if(NULL == super_frame) {
1156 LOGE("Invalid Super buffer");
1157 return BAD_VALUE;
1158 }
1159
1160 if(super_frame->num_bufs != 1) {
1161 LOGE("Multiple streams are not supported");
1162 return BAD_VALUE;
1163 }
1164 if(NULL == super_frame->bufs[0]) {
1165 LOGE("Error, Super buffer frame does not contain valid buffer");
1166 return BAD_VALUE;
1167 }
1168 return NO_ERROR;
1169 }
1170
1171 /*===========================================================================
1172 * FUNCTION : getStreamSize
1173 *
1174 * DESCRIPTION: get the size from the camera3_stream_t for the channel
1175 *
1176 * PARAMETERS :
1177 * @dim : Return the size of the stream
1178 *
1179 * RETURN : int32_t type of status
1180 * NO_ERROR -- success
1181 * none-zero failure code
1182 *==========================================================================*/
getStreamSize(cam_dimension_t & dim)1183 int32_t QCamera3ProcessingChannel::getStreamSize(cam_dimension_t &dim)
1184 {
1185 if (mCamera3Stream) {
1186 dim.width = mCamera3Stream->width;
1187 dim.height = mCamera3Stream->height;
1188 return NO_ERROR;
1189 } else {
1190 return BAD_VALUE;
1191 }
1192 }
1193
1194 /*===========================================================================
1195 * FUNCTION : getStreamBufs
1196 *
1197 * DESCRIPTION: get the buffers allocated to the stream
1198 *
1199 * PARAMETERS :
1200 * @len : buffer length
1201 *
1202 * RETURN : int32_t type of status
1203 * NO_ERROR -- success
1204 * none-zero failure code
1205 *==========================================================================*/
getStreamBufs(uint32_t)1206 QCamera3StreamMem* QCamera3ProcessingChannel::getStreamBufs(uint32_t /*len*/)
1207 {
1208 KPI_ATRACE_CALL();
1209 return &mMemory;
1210 }
1211
1212 /*===========================================================================
1213 * FUNCTION : putStreamBufs
1214 *
1215 * DESCRIPTION: release the buffers allocated to the stream
1216 *
1217 * PARAMETERS : NONE
1218 *
1219 * RETURN : NONE
1220 *==========================================================================*/
putStreamBufs()1221 void QCamera3ProcessingChannel::putStreamBufs()
1222 {
1223 mMemory.unregisterBuffers();
1224
1225 /* Reclaim all the offline metabuffers and push them to free list */
1226 {
1227 Mutex::Autolock lock(mFreeOfflineMetaBuffersLock);
1228 mFreeOfflineMetaBuffersList.clear();
1229 for (uint32_t i = 0; i < mOfflineMetaMemory.getCnt(); i++) {
1230 mFreeOfflineMetaBuffersList.push_back(i);
1231 }
1232 }
1233 }
1234
1235
1236 /*===========================================================================
1237 * FUNCTION : stop
1238 *
1239 * DESCRIPTION: stop processing channel, which will stop all streams within,
1240 * including the reprocessing channel in postprocessor.
1241 *
1242 * PARAMETERS : none
1243 *
1244 * RETURN : int32_t type of status
1245 * NO_ERROR -- success
1246 * none-zero failure code
1247 *==========================================================================*/
stop()1248 int32_t QCamera3ProcessingChannel::stop()
1249 {
1250 int32_t rc = NO_ERROR;
1251 if(!m_bIsActive) {
1252 LOGE("Attempt to stop inactive channel");
1253 return rc;
1254 }
1255
1256 m_postprocessor.stop();
1257 mPostProcStarted = false;
1258 rc |= QCamera3Channel::stop();
1259 return rc;
1260 }
1261
1262 /*===========================================================================
1263 * FUNCTION : startPostProc
1264 *
1265 * DESCRIPTION: figure out if the postprocessor needs to be restarted and if yes
1266 * start it
1267 *
1268 * PARAMETERS :
1269 * @inputBufExists : whether there is an input buffer for post processing
1270 * @config : reprocessing configuration
1271 * @metadata : metadata associated with the reprocessing request
1272 *
1273 * RETURN : NONE
1274 *==========================================================================*/
startPostProc(const reprocess_config_t & config)1275 void QCamera3ProcessingChannel::startPostProc(const reprocess_config_t &config)
1276 {
1277 if(!mPostProcStarted) {
1278 m_postprocessor.start(config);
1279 mPostProcStarted = true;
1280 }
1281 }
1282
1283 /*===========================================================================
1284 * FUNCTION : queueReprocMetadata
1285 *
1286 * DESCRIPTION: queue the reprocess metadata to the postprocessor
1287 *
1288 * PARAMETERS : metadata : the metadata corresponding to the pp frame
1289 *
1290 * RETURN : int32_t type of status
1291 * NO_ERROR -- success
1292 * none-zero failure code
1293 *==========================================================================*/
queueReprocMetadata(mm_camera_super_buf_t * metadata)1294 int32_t QCamera3ProcessingChannel::queueReprocMetadata(mm_camera_super_buf_t *metadata)
1295 {
1296 return m_postprocessor.processPPMetadata(metadata);
1297 }
1298
1299 /*===========================================================================
1300 * FUNCTION : metadataBufDone
1301 *
1302 * DESCRIPTION: Buffer done method for a metadata buffer
1303 *
1304 * PARAMETERS :
1305 * @recvd_frame : received metadata frame
1306 *
1307 * RETURN : int32_t type of status
1308 * NO_ERROR -- success
1309 * none-zero failure code
1310 *==========================================================================*/
metadataBufDone(mm_camera_super_buf_t * recvd_frame)1311 int32_t QCamera3ProcessingChannel::metadataBufDone(mm_camera_super_buf_t *recvd_frame)
1312 {
1313 int32_t rc = NO_ERROR;;
1314 if ((NULL == m_pMetaChannel) || (NULL == recvd_frame)) {
1315 LOGE("Metadata channel or metadata buffer invalid");
1316 return BAD_VALUE;
1317 }
1318
1319 rc = ((QCamera3MetadataChannel*)m_pMetaChannel)->bufDone(recvd_frame);
1320
1321 return rc;
1322 }
1323
1324 /*===========================================================================
1325 * FUNCTION : translateStreamTypeAndFormat
1326 *
1327 * DESCRIPTION: translates the framework stream format into HAL stream type
1328 * and format
1329 *
1330 * PARAMETERS :
1331 * @streamType : translated stream type
1332 * @streamFormat : translated stream format
1333 * @stream : fwk stream
1334 *
1335 * RETURN : int32_t type of status
1336 * NO_ERROR -- success
1337 * none-zero failure code
1338 *==========================================================================*/
translateStreamTypeAndFormat(camera3_stream_t * stream,cam_stream_type_t & streamType,cam_format_t & streamFormat)1339 int32_t QCamera3ProcessingChannel::translateStreamTypeAndFormat(camera3_stream_t *stream,
1340 cam_stream_type_t &streamType, cam_format_t &streamFormat)
1341 {
1342 switch (stream->format) {
1343 case HAL_PIXEL_FORMAT_YCbCr_420_888:
1344 if(stream->stream_type == CAMERA3_STREAM_INPUT){
1345 streamType = CAM_STREAM_TYPE_SNAPSHOT;
1346 streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_SNAPSHOT);
1347 } else {
1348 streamType = CAM_STREAM_TYPE_CALLBACK;
1349 streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_CALLBACK);
1350 }
1351 break;
1352 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
1353 if (stream->usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) {
1354 streamType = CAM_STREAM_TYPE_VIDEO;
1355 streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_VIDEO);
1356 } else if(stream->stream_type == CAMERA3_STREAM_INPUT ||
1357 stream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL ||
1358 IS_USAGE_ZSL(stream->usage)){
1359 streamType = CAM_STREAM_TYPE_SNAPSHOT;
1360 streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_SNAPSHOT);
1361 } else {
1362 streamType = CAM_STREAM_TYPE_PREVIEW;
1363 streamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_PREVIEW);
1364 }
1365 break;
1366 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
1367 case HAL_PIXEL_FORMAT_RAW16:
1368 case HAL_PIXEL_FORMAT_RAW10:
1369 streamType = CAM_STREAM_TYPE_RAW;
1370 streamFormat = CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG;
1371 break;
1372 default:
1373 return -EINVAL;
1374 }
1375 LOGD("fwk_format = %d, streamType = %d, streamFormat = %d",
1376 stream->format, streamType, streamFormat);
1377 return NO_ERROR;
1378 }
1379
1380 /*===========================================================================
1381 * FUNCTION : setReprocConfig
1382 *
1383 * DESCRIPTION: sets the reprocessing parameters for the input buffer
1384 *
1385 * PARAMETERS :
1386 * @reproc_cfg : the configuration to be set
1387 * @pInputBuffer : pointer to the input buffer
1388 * @metadata : pointer to the reprocessing metadata buffer
1389 * @streamFormat : format of the input stream
1390 *
1391 * RETURN : int32_t type of status
1392 * NO_ERROR -- success
1393 * none-zero failure code
1394 *==========================================================================*/
setReprocConfig(reprocess_config_t & reproc_cfg,camera3_stream_buffer_t * pInputBuffer,__unused metadata_buffer_t * metadata,cam_format_t streamFormat,cam_dimension_t dim)1395 int32_t QCamera3ProcessingChannel::setReprocConfig(reprocess_config_t &reproc_cfg,
1396 camera3_stream_buffer_t *pInputBuffer,
1397 __unused metadata_buffer_t *metadata,
1398 cam_format_t streamFormat, cam_dimension_t dim)
1399 {
1400 int32_t rc = 0;
1401 reproc_cfg.padding = &mPaddingInfo;
1402 //to ensure a big enough buffer size set the height and width
1403 //padding to max(height padding, width padding)
1404 if (reproc_cfg.padding->height_padding > reproc_cfg.padding->width_padding) {
1405 reproc_cfg.padding->width_padding = reproc_cfg.padding->height_padding;
1406 } else {
1407 reproc_cfg.padding->height_padding = reproc_cfg.padding->width_padding;
1408 }
1409 if (NULL != pInputBuffer) {
1410 reproc_cfg.input_stream_dim.width = (int32_t)pInputBuffer->stream->width;
1411 reproc_cfg.input_stream_dim.height = (int32_t)pInputBuffer->stream->height;
1412 } else {
1413 reproc_cfg.input_stream_dim.width = (int32_t)dim.width;
1414 reproc_cfg.input_stream_dim.height = (int32_t)dim.height;
1415 }
1416 reproc_cfg.src_channel = this;
1417 reproc_cfg.output_stream_dim.width = mCamera3Stream->width;
1418 reproc_cfg.output_stream_dim.height = mCamera3Stream->height;
1419 reproc_cfg.reprocess_type = getReprocessType();
1420
1421 //offset calculation
1422 if (NULL != pInputBuffer) {
1423 rc = translateStreamTypeAndFormat(pInputBuffer->stream,
1424 reproc_cfg.stream_type, reproc_cfg.stream_format);
1425 if (rc != NO_ERROR) {
1426 LOGE("Stream format %d is not supported",
1427 pInputBuffer->stream->format);
1428 return rc;
1429 }
1430 } else {
1431 reproc_cfg.stream_type = mStreamType;
1432 reproc_cfg.stream_format = streamFormat;
1433 }
1434
1435 switch (reproc_cfg.stream_type) {
1436 case CAM_STREAM_TYPE_PREVIEW:
1437 if (getStreamByIndex(0) == NULL) {
1438 LOGE("Could not find stream");
1439 rc = -1;
1440 break;
1441 }
1442 rc = mm_stream_calc_offset_preview(
1443 getStreamByIndex(0)->getStreamInfo(),
1444 &reproc_cfg.input_stream_dim,
1445 reproc_cfg.padding,
1446 &reproc_cfg.input_stream_plane_info);
1447 break;
1448 case CAM_STREAM_TYPE_VIDEO:
1449 rc = mm_stream_calc_offset_video(reproc_cfg.stream_format,
1450 &reproc_cfg.input_stream_dim,
1451 &reproc_cfg.input_stream_plane_info);
1452 break;
1453 case CAM_STREAM_TYPE_RAW:
1454 rc = mm_stream_calc_offset_raw(reproc_cfg.stream_format,
1455 &reproc_cfg.input_stream_dim,
1456 reproc_cfg.padding, &reproc_cfg.input_stream_plane_info);
1457 break;
1458 case CAM_STREAM_TYPE_SNAPSHOT:
1459 case CAM_STREAM_TYPE_CALLBACK:
1460 default:
1461 rc = mm_stream_calc_offset_snapshot(streamFormat, &reproc_cfg.input_stream_dim,
1462 reproc_cfg.padding, &reproc_cfg.input_stream_plane_info);
1463 break;
1464 }
1465 if (rc != 0) {
1466 LOGE("Stream %d plane info calculation failed!", mStreamType);
1467 return rc;
1468 }
1469 return rc;
1470 }
1471
1472 /*===========================================================================
1473 * FUNCTION : reprocessCbRoutine
1474 *
1475 * DESCRIPTION: callback function for the reprocessed frame. This frame now
1476 * should be returned to the framework
1477 *
1478 * PARAMETERS :
1479 * @resultBuffer : buffer containing the reprocessed data
1480 * @resultFrameNumber : frame number on which the buffer was requested
1481 *
1482 * RETURN : NONE
1483 *
1484 *==========================================================================*/
reprocessCbRoutine(buffer_handle_t * resultBuffer,uint32_t resultFrameNumber)1485 void QCamera3ProcessingChannel::reprocessCbRoutine(buffer_handle_t *resultBuffer,
1486 uint32_t resultFrameNumber)
1487 {
1488 ATRACE_CALL();
1489 int rc = NO_ERROR;
1490
1491 rc = releaseOfflineMemory(resultFrameNumber);
1492 if (NO_ERROR != rc) {
1493 LOGE("Error releasing offline memory %d", rc);
1494 }
1495 /* Since reprocessing is done, send the callback to release the input buffer */
1496 if (mChannelCB) {
1497 mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
1498 }
1499 issueChannelCb(resultBuffer, resultFrameNumber);
1500
1501 return;
1502 }
1503
1504 /*===========================================================================
1505 * FUNCTION : issueChannelCb
1506 *
1507 * DESCRIPTION: function to set the result and issue channel callback
1508 *
1509 * PARAMETERS :
1510 * @resultBuffer : buffer containing the data
1511 * @resultFrameNumber : frame number on which the buffer was requested
1512 *
1513 * RETURN : NONE
1514 *
1515 *
1516 *==========================================================================*/
issueChannelCb(buffer_handle_t * resultBuffer,uint32_t resultFrameNumber)1517 void QCamera3ProcessingChannel::issueChannelCb(buffer_handle_t *resultBuffer,
1518 uint32_t resultFrameNumber)
1519 {
1520 camera3_stream_buffer_t result;
1521 //Use below data to issue framework callback
1522 result.stream = mCamera3Stream;
1523 result.buffer = resultBuffer;
1524 result.status = CAMERA3_BUFFER_STATUS_OK;
1525 result.acquire_fence = -1;
1526 result.release_fence = -1;
1527
1528 if (mChannelCB) {
1529 mChannelCB(NULL, &result, resultFrameNumber, false, mUserData);
1530 }
1531 }
1532
1533 /*===========================================================================
1534 * FUNCTION : showDebugFPS
1535 *
1536 * DESCRIPTION: Function to log the fps for preview, video, callback and raw
1537 * streams
1538 *
1539 * PARAMETERS : Stream type
1540 *
1541 * RETURN : None
1542 *==========================================================================*/
showDebugFPS(int32_t streamType)1543 void QCamera3ProcessingChannel::showDebugFPS(int32_t streamType)
1544 {
1545 double fps = 0;
1546 mFrameCount++;
1547 nsecs_t now = systemTime();
1548 nsecs_t diff = now - mLastFpsTime;
1549 if (diff > ms2ns(250)) {
1550 fps = (((double)(mFrameCount - mLastFrameCount)) *
1551 (double)(s2ns(1))) / (double)diff;
1552 switch(streamType) {
1553 case CAM_STREAM_TYPE_PREVIEW:
1554 LOGH("PROFILE_PREVIEW_FRAMES_PER_SECOND : %.4f",
1555 fps);
1556 break;
1557 case CAM_STREAM_TYPE_VIDEO:
1558 LOGH("PROFILE_VIDEO_FRAMES_PER_SECOND : %.4f",
1559 fps);
1560 break;
1561 case CAM_STREAM_TYPE_CALLBACK:
1562 LOGH("PROFILE_CALLBACK_FRAMES_PER_SECOND : %.4f",
1563 fps);
1564 break;
1565 case CAM_STREAM_TYPE_RAW:
1566 LOGH("PROFILE_RAW_FRAMES_PER_SECOND : %.4f",
1567 fps);
1568 break;
1569 default:
1570 LOGH("logging not supported for the stream");
1571 break;
1572 }
1573 mLastFpsTime = now;
1574 mLastFrameCount = mFrameCount;
1575 }
1576 }
1577
1578 /*===========================================================================
1579 * FUNCTION : releaseOfflineMemory
1580 *
1581 * DESCRIPTION: function to clean up the offline memory used for input reprocess
1582 *
1583 * PARAMETERS :
1584 * @resultFrameNumber : frame number on which the buffer was requested
1585 *
1586 * RETURN : int32_t type of status
1587 * NO_ERROR -- success
1588 * non-zero failure code
1589 *
1590 *
1591 *==========================================================================*/
releaseOfflineMemory(uint32_t resultFrameNumber)1592 int32_t QCamera3ProcessingChannel::releaseOfflineMemory(uint32_t resultFrameNumber)
1593 {
1594 int32_t rc = NO_ERROR;
1595 int32_t inputBufIndex =
1596 mOfflineMemory.getGrallocBufferIndex(resultFrameNumber);
1597 if (0 <= inputBufIndex) {
1598 rc = mOfflineMemory.unregisterBuffer(inputBufIndex);
1599 } else {
1600 LOGW("Could not find offline input buffer, resultFrameNumber %d",
1601 resultFrameNumber);
1602 }
1603 if (rc != NO_ERROR) {
1604 LOGE("Failed to unregister offline input buffer");
1605 }
1606
1607 int32_t metaBufIndex =
1608 mOfflineMetaMemory.getHeapBufferIndex(resultFrameNumber);
1609 if (0 <= metaBufIndex) {
1610 Mutex::Autolock lock(mFreeOfflineMetaBuffersLock);
1611 mFreeOfflineMetaBuffersList.push_back((uint32_t)metaBufIndex);
1612 } else {
1613 LOGW("Could not find offline meta buffer, resultFrameNumber %d",
1614 resultFrameNumber);
1615 }
1616
1617 return rc;
1618 }
1619
1620 /* Regular Channel methods */
1621 /*===========================================================================
1622 * FUNCTION : QCamera3RegularChannel
1623 *
1624 * DESCRIPTION: constructor of QCamera3RegularChannel
1625 *
1626 * PARAMETERS :
1627 * @cam_handle : camera handle
1628 * @cam_ops : ptr to camera ops table
1629 * @cb_routine : callback routine to frame aggregator
1630 * @stream : camera3_stream_t structure
1631 * @stream_type: Channel stream type
1632 * @postprocess_mask: feature mask for postprocessing
1633 * @metadataChannel : metadata channel for the session
1634 * @numBuffers : number of max dequeued buffers
1635 *
1636 * RETURN : none
1637 *==========================================================================*/
QCamera3RegularChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,channel_cb_routine cb_routine,cam_padding_info_t * paddingInfo,void * userData,camera3_stream_t * stream,cam_stream_type_t stream_type,uint32_t postprocess_mask,QCamera3Channel * metadataChannel,uint32_t numBuffers)1638 QCamera3RegularChannel::QCamera3RegularChannel(uint32_t cam_handle,
1639 uint32_t channel_handle,
1640 mm_camera_ops_t *cam_ops,
1641 channel_cb_routine cb_routine,
1642 cam_padding_info_t *paddingInfo,
1643 void *userData,
1644 camera3_stream_t *stream,
1645 cam_stream_type_t stream_type,
1646 uint32_t postprocess_mask,
1647 QCamera3Channel *metadataChannel,
1648 uint32_t numBuffers) :
1649 QCamera3ProcessingChannel(cam_handle, channel_handle, cam_ops,
1650 cb_routine, paddingInfo, userData, stream, stream_type,
1651 postprocess_mask, metadataChannel, numBuffers),
1652 mBatchSize(0),
1653 mRotation(ROTATE_0)
1654 {
1655 }
1656
1657 /*===========================================================================
1658 * FUNCTION : ~QCamera3RegularChannel
1659 *
1660 * DESCRIPTION: destructor of QCamera3RegularChannel
1661 *
1662 * PARAMETERS : none
1663 *
1664 * RETURN : none
1665 *==========================================================================*/
~QCamera3RegularChannel()1666 QCamera3RegularChannel::~QCamera3RegularChannel()
1667 {
1668 destroy();
1669 }
1670
1671 /*===========================================================================
1672 * FUNCTION : initialize
1673 *
1674 * DESCRIPTION: Initialize and add camera channel & stream
1675 *
1676 * PARAMETERS :
1677 * @isType : type of image stabilization required on this stream
1678 *
1679 * RETURN : int32_t type of status
1680 * NO_ERROR -- success
1681 * none-zero failure code
1682 *==========================================================================*/
1683
initialize(cam_is_type_t isType)1684 int32_t QCamera3RegularChannel::initialize(cam_is_type_t isType)
1685 {
1686 ATRACE_CALL();
1687 int32_t rc = NO_ERROR;
1688
1689 cam_dimension_t streamDim;
1690
1691 if (NULL == mCamera3Stream) {
1692 LOGE("Camera stream uninitialized");
1693 return NO_INIT;
1694 }
1695
1696 if (1 <= m_numStreams) {
1697 // Only one stream per channel supported in v3 Hal
1698 return NO_ERROR;
1699 }
1700
1701 mIsType = isType;
1702
1703 rc = translateStreamTypeAndFormat(mCamera3Stream, mStreamType,
1704 mStreamFormat);
1705 if (rc != NO_ERROR) {
1706 return -EINVAL;
1707 }
1708
1709
1710 if ((mStreamType == CAM_STREAM_TYPE_VIDEO) ||
1711 (mStreamType == CAM_STREAM_TYPE_PREVIEW)) {
1712 if ((mCamera3Stream->rotation != CAMERA3_STREAM_ROTATION_0) &&
1713 ((mPostProcMask & CAM_QCOM_FEATURE_ROTATION) == 0)) {
1714 LOGE("attempting rotation %d when rotation is disabled",
1715 mCamera3Stream->rotation);
1716 return -EINVAL;
1717 }
1718
1719 switch (mCamera3Stream->rotation) {
1720 case CAMERA3_STREAM_ROTATION_0:
1721 mRotation = ROTATE_0;
1722 break;
1723 case CAMERA3_STREAM_ROTATION_90: {
1724 mRotation = ROTATE_90;
1725 break;
1726 }
1727 case CAMERA3_STREAM_ROTATION_180:
1728 mRotation = ROTATE_180;
1729 break;
1730 case CAMERA3_STREAM_ROTATION_270: {
1731 mRotation = ROTATE_270;
1732 break;
1733 }
1734 default:
1735 LOGE("Unknown rotation: %d",
1736 mCamera3Stream->rotation);
1737 return -EINVAL;
1738 }
1739 } else if (mCamera3Stream->rotation != CAMERA3_STREAM_ROTATION_0) {
1740 LOGE("Rotation %d is not supported by stream type %d",
1741 mCamera3Stream->rotation,
1742 mStreamType);
1743 return -EINVAL;
1744 }
1745
1746 streamDim.width = mCamera3Stream->width;
1747 streamDim.height = mCamera3Stream->height;
1748
1749 LOGD("batch size is %d", mBatchSize);
1750 rc = QCamera3Channel::addStream(mStreamType,
1751 mStreamFormat,
1752 streamDim,
1753 mRotation,
1754 mNumBufs,
1755 mPostProcMask,
1756 mIsType,
1757 mBatchSize);
1758
1759 return rc;
1760 }
1761
1762 /*===========================================================================
1763 * FUNCTION : setBatchSize
1764 *
1765 * DESCRIPTION: Set batch size for the channel.
1766 *
1767 * PARAMETERS :
1768 * @batchSize : Number of image buffers in a batch
1769 *
1770 * RETURN : int32_t type of status
1771 * NO_ERROR -- success always
1772 * none-zero failure code
1773 *==========================================================================*/
setBatchSize(uint32_t batchSize)1774 int32_t QCamera3RegularChannel::setBatchSize(uint32_t batchSize)
1775 {
1776 int32_t rc = NO_ERROR;
1777
1778 mBatchSize = batchSize;
1779 LOGD("Batch size set: %d", mBatchSize);
1780 return rc;
1781 }
1782
1783 /*===========================================================================
1784 * FUNCTION : getStreamTypeMask
1785 *
1786 * DESCRIPTION: Get bit mask of all stream types in this channel.
1787 * If stream is not initialized, then generate mask based on
1788 * local streamType
1789 *
1790 * PARAMETERS : None
1791 *
1792 * RETURN : Bit mask of all stream types in this channel
1793 *==========================================================================*/
getStreamTypeMask()1794 uint32_t QCamera3RegularChannel::getStreamTypeMask()
1795 {
1796 if (mStreams[0]) {
1797 return QCamera3Channel::getStreamTypeMask();
1798 } else {
1799 return (1U << mStreamType);
1800 }
1801 }
1802
1803 /*===========================================================================
1804 * FUNCTION : queueBatchBuf
1805 *
1806 * DESCRIPTION: queue batch container to downstream
1807 *
1808 * PARAMETERS :
1809 *
1810 * RETURN : int32_t type of status
1811 * NO_ERROR -- success always
1812 * none-zero failure code
1813 *==========================================================================*/
queueBatchBuf()1814 int32_t QCamera3RegularChannel::queueBatchBuf()
1815 {
1816 int32_t rc = NO_ERROR;
1817
1818 if (mStreams[0]) {
1819 rc = mStreams[0]->queueBatchBuf();
1820 }
1821 if (rc != NO_ERROR) {
1822 LOGE("stream->queueBatchContainer failed");
1823 }
1824 return rc;
1825 }
1826
1827 /*===========================================================================
1828 * FUNCTION : request
1829 *
1830 * DESCRIPTION: process a request from camera service. Stream on if ncessary.
1831 *
1832 * PARAMETERS :
1833 * @buffer : buffer to be filled for this request
1834 *
1835 * RETURN : 0 on a success start of capture
1836 * -EINVAL on invalid input
1837 * -ENODEV on serious error
1838 *==========================================================================*/
request(buffer_handle_t * buffer,uint32_t frameNumber)1839 int32_t QCamera3RegularChannel::request(buffer_handle_t *buffer, uint32_t frameNumber)
1840 {
1841 ATRACE_CALL();
1842 //FIX ME: Return buffer back in case of failures below.
1843
1844 int32_t rc = NO_ERROR;
1845 int index;
1846
1847 if (NULL == buffer) {
1848 LOGE("Invalid buffer in channel request");
1849 return BAD_VALUE;
1850 }
1851
1852 if(!m_bIsActive) {
1853 rc = registerBuffer(buffer, mIsType);
1854 if (NO_ERROR != rc) {
1855 LOGE("On-the-fly buffer registration failed %d",
1856 rc);
1857 return rc;
1858 }
1859
1860 rc = start();
1861 if (NO_ERROR != rc) {
1862 return rc;
1863 }
1864 } else {
1865 LOGD("Request on an existing stream");
1866 }
1867
1868 index = mMemory.getMatchBufIndex((void*)buffer);
1869 if(index < 0) {
1870 rc = registerBuffer(buffer, mIsType);
1871 if (NO_ERROR != rc) {
1872 LOGE("On-the-fly buffer registration failed %d",
1873 rc);
1874 return rc;
1875 }
1876
1877 index = mMemory.getMatchBufIndex((void*)buffer);
1878 if (index < 0) {
1879 LOGE("Could not find object among registered buffers");
1880 return DEAD_OBJECT;
1881 }
1882 }
1883
1884 rc = mStreams[0]->bufDone((uint32_t)index);
1885 if(rc != NO_ERROR) {
1886 LOGE("Failed to Q new buffer to stream");
1887 return rc;
1888 }
1889
1890 rc = mMemory.markFrameNumber((uint32_t)index, frameNumber);
1891 return rc;
1892 }
1893
1894 /*===========================================================================
1895 * FUNCTION : getReprocessType
1896 *
1897 * DESCRIPTION: get the type of reprocess output supported by this channel
1898 *
1899 * PARAMETERS : NONE
1900 *
1901 * RETURN : reprocess_type_t : type of reprocess
1902 *==========================================================================*/
getReprocessType()1903 reprocess_type_t QCamera3RegularChannel::getReprocessType()
1904 {
1905 return REPROCESS_TYPE_PRIVATE;
1906 }
1907
1908
QCamera3MetadataChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,channel_cb_routine cb_routine,cam_padding_info_t * paddingInfo,uint32_t postprocess_mask,void * userData,uint32_t numBuffers)1909 QCamera3MetadataChannel::QCamera3MetadataChannel(uint32_t cam_handle,
1910 uint32_t channel_handle,
1911 mm_camera_ops_t *cam_ops,
1912 channel_cb_routine cb_routine,
1913 cam_padding_info_t *paddingInfo,
1914 uint32_t postprocess_mask,
1915 void *userData, uint32_t numBuffers) :
1916 QCamera3Channel(cam_handle, channel_handle, cam_ops,
1917 cb_routine, paddingInfo, postprocess_mask,
1918 userData, numBuffers),
1919 mMemory(NULL)
1920 {
1921 }
1922
~QCamera3MetadataChannel()1923 QCamera3MetadataChannel::~QCamera3MetadataChannel()
1924 {
1925 destroy();
1926
1927 if (mMemory) {
1928 mMemory->deallocate();
1929 delete mMemory;
1930 mMemory = NULL;
1931 }
1932 }
1933
initialize(cam_is_type_t isType)1934 int32_t QCamera3MetadataChannel::initialize(cam_is_type_t isType)
1935 {
1936 ATRACE_CALL();
1937 int32_t rc;
1938 cam_dimension_t streamDim;
1939
1940 if (mMemory || m_numStreams > 0) {
1941 LOGE("metadata channel already initialized");
1942 return -EINVAL;
1943 }
1944
1945 streamDim.width = (int32_t)sizeof(metadata_buffer_t),
1946 streamDim.height = 1;
1947
1948 mIsType = isType;
1949 rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_METADATA, CAM_FORMAT_MAX,
1950 streamDim, ROTATE_0, (uint8_t)mNumBuffers, mPostProcMask, mIsType);
1951 if (rc < 0) {
1952 LOGE("addStream failed");
1953 }
1954 return rc;
1955 }
1956
request(buffer_handle_t *,uint32_t)1957 int32_t QCamera3MetadataChannel::request(buffer_handle_t * /*buffer*/,
1958 uint32_t /*frameNumber*/)
1959 {
1960 if (!m_bIsActive) {
1961 return start();
1962 }
1963 else
1964 return 0;
1965 }
1966
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream *)1967 void QCamera3MetadataChannel::streamCbRoutine(
1968 mm_camera_super_buf_t *super_frame,
1969 QCamera3Stream * /*stream*/)
1970 {
1971 ATRACE_NAME("metadata_stream_cb_routine");
1972 uint32_t requestNumber = 0;
1973 if (super_frame == NULL || super_frame->num_bufs != 1) {
1974 LOGE("super_frame is not valid");
1975 return;
1976 }
1977 if (mChannelCB) {
1978 mChannelCB(super_frame, NULL, requestNumber, false, mUserData);
1979 }
1980 }
1981
getStreamBufs(uint32_t len)1982 QCamera3StreamMem* QCamera3MetadataChannel::getStreamBufs(uint32_t len)
1983 {
1984 int rc;
1985 if (len < sizeof(metadata_buffer_t)) {
1986 LOGE("Metadata buffer size less than structure %d vs %d",
1987 len,
1988 sizeof(metadata_buffer_t));
1989 return NULL;
1990 }
1991 mMemory = new QCamera3StreamMem(MIN_STREAMING_BUFFER_NUM);
1992 if (!mMemory) {
1993 LOGE("unable to create metadata memory");
1994 return NULL;
1995 }
1996 rc = mMemory->allocateAll(len);
1997 if (rc < 0) {
1998 LOGE("unable to allocate metadata memory");
1999 delete mMemory;
2000 mMemory = NULL;
2001 return NULL;
2002 }
2003 clear_metadata_buffer((metadata_buffer_t*)mMemory->getPtr(0));
2004 return mMemory;
2005 }
2006
putStreamBufs()2007 void QCamera3MetadataChannel::putStreamBufs()
2008 {
2009 mMemory->deallocate();
2010 delete mMemory;
2011 mMemory = NULL;
2012 }
2013 /*************************************************************************************/
2014 // RAW Channel related functions
QCamera3RawChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,channel_cb_routine cb_routine,cam_padding_info_t * paddingInfo,void * userData,camera3_stream_t * stream,uint32_t postprocess_mask,QCamera3Channel * metadataChannel,bool raw_16,uint32_t numBuffers)2015 QCamera3RawChannel::QCamera3RawChannel(uint32_t cam_handle,
2016 uint32_t channel_handle,
2017 mm_camera_ops_t *cam_ops,
2018 channel_cb_routine cb_routine,
2019 cam_padding_info_t *paddingInfo,
2020 void *userData,
2021 camera3_stream_t *stream,
2022 uint32_t postprocess_mask,
2023 QCamera3Channel *metadataChannel,
2024 bool raw_16, uint32_t numBuffers) :
2025 QCamera3RegularChannel(cam_handle, channel_handle, cam_ops,
2026 cb_routine, paddingInfo, userData, stream,
2027 CAM_STREAM_TYPE_RAW, postprocess_mask,
2028 metadataChannel, numBuffers),
2029 mIsRaw16(raw_16)
2030 {
2031 char prop[PROPERTY_VALUE_MAX];
2032 property_get("persist.camera.raw.debug.dump", prop, "0");
2033 mRawDump = atoi(prop);
2034 }
2035
~QCamera3RawChannel()2036 QCamera3RawChannel::~QCamera3RawChannel()
2037 {
2038 }
2039
2040 /*===========================================================================
2041 * FUNCTION : initialize
2042 *
2043 * DESCRIPTION: Initialize and add camera channel & stream
2044 *
2045 * PARAMETERS :
2046 * @isType : image stabilization type on the stream
2047 *
2048 * RETURN : int32_t type of status
2049 * NO_ERROR -- success
2050 * none-zero failure code
2051 *==========================================================================*/
2052
initialize(cam_is_type_t isType)2053 int32_t QCamera3RawChannel::initialize(cam_is_type_t isType)
2054 {
2055 return QCamera3RegularChannel::initialize(isType);
2056 }
2057
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)2058 void QCamera3RawChannel::streamCbRoutine(
2059 mm_camera_super_buf_t *super_frame,
2060 QCamera3Stream * stream)
2061 {
2062 ATRACE_CALL();
2063 /* Move this back down once verified */
2064 if (mRawDump)
2065 dumpRawSnapshot(super_frame->bufs[0]);
2066
2067 if (mIsRaw16) {
2068 if (getStreamDefaultFormat(CAM_STREAM_TYPE_RAW) ==
2069 CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG)
2070 convertMipiToRaw16(super_frame->bufs[0]);
2071 else
2072 convertLegacyToRaw16(super_frame->bufs[0]);
2073 }
2074
2075 //Make sure cache coherence because extra processing is done
2076 mMemory.cleanInvalidateCache(super_frame->bufs[0]->buf_idx);
2077
2078 QCamera3RegularChannel::streamCbRoutine(super_frame, stream);
2079 return;
2080 }
2081
dumpRawSnapshot(mm_camera_buf_def_t * frame)2082 void QCamera3RawChannel::dumpRawSnapshot(mm_camera_buf_def_t *frame)
2083 {
2084 QCamera3Stream *stream = getStreamByIndex(0);
2085 if (stream != NULL) {
2086 char buf[FILENAME_MAX];
2087 memset(buf, 0, sizeof(buf));
2088 cam_dimension_t dim;
2089 memset(&dim, 0, sizeof(dim));
2090 stream->getFrameDimension(dim);
2091
2092 cam_frame_len_offset_t offset;
2093 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2094 stream->getFrameOffset(offset);
2095 snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"r_%d_%dx%d.raw",
2096 frame->frame_idx, offset.mp[0].stride, offset.mp[0].scanline);
2097
2098 int file_fd = open(buf, O_RDWR| O_CREAT, 0644);
2099 if (file_fd >= 0) {
2100 ssize_t written_len = write(file_fd, frame->buffer, frame->frame_len);
2101 LOGD("written number of bytes %zd", written_len);
2102 close(file_fd);
2103 } else {
2104 LOGE("failed to open file to dump image");
2105 }
2106 } else {
2107 LOGE("Could not find stream");
2108 }
2109
2110 }
2111
convertLegacyToRaw16(mm_camera_buf_def_t * frame)2112 void QCamera3RawChannel::convertLegacyToRaw16(mm_camera_buf_def_t *frame)
2113 {
2114 // Convert image buffer from Opaque raw format to RAW16 format
2115 // 10bit Opaque raw is stored in the format of:
2116 // 0000 - p5 - p4 - p3 - p2 - p1 - p0
2117 // where p0 to p5 are 6 pixels (each is 10bit)_and most significant
2118 // 4 bits are 0s. Each 64bit word contains 6 pixels.
2119
2120 QCamera3Stream *stream = getStreamByIndex(0);
2121 if (stream != NULL) {
2122 cam_dimension_t dim;
2123 memset(&dim, 0, sizeof(dim));
2124 stream->getFrameDimension(dim);
2125
2126 cam_frame_len_offset_t offset;
2127 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2128 stream->getFrameOffset(offset);
2129
2130 uint32_t raw16_stride = ((uint32_t)dim.width + 15U) & ~15U;
2131 uint16_t* raw16_buffer = (uint16_t *)frame->buffer;
2132
2133 // In-place format conversion.
2134 // Raw16 format always occupy more memory than opaque raw10.
2135 // Convert to Raw16 by iterating through all pixels from bottom-right
2136 // to top-left of the image.
2137 // One special notes:
2138 // 1. Cross-platform raw16's stride is 16 pixels.
2139 // 2. Opaque raw10's stride is 6 pixels, and aligned to 16 bytes.
2140 for (int32_t ys = dim.height - 1; ys >= 0; ys--) {
2141 uint32_t y = (uint32_t)ys;
2142 uint64_t* row_start = (uint64_t *)frame->buffer +
2143 y * (uint32_t)offset.mp[0].stride_in_bytes / 8;
2144 for (int32_t xs = dim.width - 1; xs >= 0; xs--) {
2145 uint32_t x = (uint32_t)xs;
2146 uint16_t raw16_pixel = 0x3FF & (row_start[x/6] >> (10*(x%6)));
2147 raw16_buffer[y*raw16_stride+x] = raw16_pixel;
2148 }
2149 }
2150 } else {
2151 LOGE("Could not find stream");
2152 }
2153
2154 }
2155
convertMipiToRaw16(mm_camera_buf_def_t * frame)2156 void QCamera3RawChannel::convertMipiToRaw16(mm_camera_buf_def_t *frame)
2157 {
2158 // Convert image buffer from mipi10 raw format to RAW16 format
2159 // mipi10 opaque raw is stored in the format of:
2160 // P3(1:0) P2(1:0) P1(1:0) P0(1:0) P3(9:2) P2(9:2) P1(9:2) P0(9:2)
2161 // 4 pixels occupy 5 bytes, no padding needed
2162
2163 QCamera3Stream *stream = getStreamByIndex(0);
2164 if (stream != NULL) {
2165 cam_dimension_t dim;
2166 memset(&dim, 0, sizeof(dim));
2167 stream->getFrameDimension(dim);
2168
2169 cam_frame_len_offset_t offset;
2170 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2171 stream->getFrameOffset(offset);
2172
2173 uint32_t raw16_stride = ((uint32_t)dim.width + 15U) & ~15U;
2174 uint16_t* raw16_buffer = (uint16_t *)frame->buffer;
2175
2176 // In-place format conversion.
2177 // Raw16 format always occupy more memory than opaque raw10.
2178 // Convert to Raw16 by iterating through all pixels from bottom-right
2179 // to top-left of the image.
2180 // One special notes:
2181 // 1. Cross-platform raw16's stride is 16 pixels.
2182 // 2. mipi raw10's stride is 4 pixels, and aligned to 16 bytes.
2183 for (int32_t ys = dim.height - 1; ys >= 0; ys--) {
2184 uint32_t y = (uint32_t)ys;
2185 uint8_t* row_start = (uint8_t *)frame->buffer +
2186 y * (uint32_t)offset.mp[0].stride_in_bytes;
2187 for (int32_t xs = dim.width - 1; xs >= 0; xs--) {
2188 uint32_t x = (uint32_t)xs;
2189 uint8_t upper_8bit = row_start[5*(x/4)+x%4];
2190 uint8_t lower_2bit = ((row_start[5*(x/4)+4] >> (x%4)) & 0x3);
2191 uint16_t raw16_pixel =
2192 (uint16_t)(((uint16_t)upper_8bit)<<2 |
2193 (uint16_t)lower_2bit);
2194 raw16_buffer[y*raw16_stride+x] = raw16_pixel;
2195 }
2196 }
2197 } else {
2198 LOGE("Could not find stream");
2199 }
2200
2201 }
2202
2203 /*===========================================================================
2204 * FUNCTION : getReprocessType
2205 *
2206 * DESCRIPTION: get the type of reprocess output supported by this channel
2207 *
2208 * PARAMETERS : NONE
2209 *
2210 * RETURN : reprocess_type_t : type of reprocess
2211 *==========================================================================*/
getReprocessType()2212 reprocess_type_t QCamera3RawChannel::getReprocessType()
2213 {
2214 return REPROCESS_TYPE_RAW;
2215 }
2216
2217
2218 /*************************************************************************************/
2219 // RAW Dump Channel related functions
2220
2221 /*===========================================================================
2222 * FUNCTION : QCamera3RawDumpChannel
2223 *
2224 * DESCRIPTION: Constructor for RawDumpChannel
2225 *
2226 * PARAMETERS :
2227 * @cam_handle : Handle for Camera
2228 * @cam_ops : Function pointer table
2229 * @rawDumpSize : Dimensions for the Raw stream
2230 * @paddinginfo : Padding information for stream
2231 * @userData : Cookie for parent
2232 * @pp mask : PP feature mask for this stream
2233 * @numBuffers : number of max dequeued buffers
2234 *
2235 * RETURN : NA
2236 *==========================================================================*/
QCamera3RawDumpChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,cam_dimension_t rawDumpSize,cam_padding_info_t * paddingInfo,void * userData,uint32_t postprocess_mask,uint32_t numBuffers)2237 QCamera3RawDumpChannel::QCamera3RawDumpChannel(uint32_t cam_handle,
2238 uint32_t channel_handle,
2239 mm_camera_ops_t *cam_ops,
2240 cam_dimension_t rawDumpSize,
2241 cam_padding_info_t *paddingInfo,
2242 void *userData,
2243 uint32_t postprocess_mask, uint32_t numBuffers) :
2244 QCamera3Channel(cam_handle, channel_handle, cam_ops, NULL,
2245 paddingInfo, postprocess_mask,
2246 userData, numBuffers),
2247 mDim(rawDumpSize),
2248 mMemory(NULL)
2249 {
2250 char prop[PROPERTY_VALUE_MAX];
2251 property_get("persist.camera.raw.dump", prop, "0");
2252 mRawDump = atoi(prop);
2253 }
2254
2255 /*===========================================================================
2256 * FUNCTION : QCamera3RawDumpChannel
2257 *
2258 * DESCRIPTION: Destructor for RawDumpChannel
2259 *
2260 * PARAMETERS :
2261 *
2262 * RETURN : NA
2263 *==========================================================================*/
2264
~QCamera3RawDumpChannel()2265 QCamera3RawDumpChannel::~QCamera3RawDumpChannel()
2266 {
2267 destroy();
2268 }
2269
2270 /*===========================================================================
2271 * FUNCTION : dumpRawSnapshot
2272 *
2273 * DESCRIPTION: Helper function to dump Raw frames
2274 *
2275 * PARAMETERS :
2276 * @frame : stream buf frame to be dumped
2277 *
2278 * RETURN : NA
2279 *==========================================================================*/
dumpRawSnapshot(mm_camera_buf_def_t * frame)2280 void QCamera3RawDumpChannel::dumpRawSnapshot(mm_camera_buf_def_t *frame)
2281 {
2282 QCamera3Stream *stream = getStreamByIndex(0);
2283 if (stream != NULL) {
2284 char buf[FILENAME_MAX];
2285 struct timeval tv;
2286 struct tm timeinfo_data;
2287 struct tm *timeinfo;
2288
2289 cam_dimension_t dim;
2290 memset(&dim, 0, sizeof(dim));
2291 stream->getFrameDimension(dim);
2292
2293 cam_frame_len_offset_t offset;
2294 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2295 stream->getFrameOffset(offset);
2296
2297 gettimeofday(&tv, NULL);
2298 timeinfo = localtime_r(&tv.tv_sec, &timeinfo_data);
2299
2300 if (NULL != timeinfo) {
2301 memset(buf, 0, sizeof(buf));
2302 snprintf(buf, sizeof(buf),
2303 QCAMERA_DUMP_FRM_LOCATION
2304 "%04d-%02d-%02d-%02d-%02d-%02d-%06ld_%d_%dx%d.raw",
2305 timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
2306 timeinfo->tm_mday, timeinfo->tm_hour,
2307 timeinfo->tm_min, timeinfo->tm_sec,tv.tv_usec,
2308 frame->frame_idx, dim.width, dim.height);
2309
2310 int file_fd = open(buf, O_RDWR| O_CREAT, 0777);
2311 if (file_fd >= 0) {
2312 ssize_t written_len =
2313 write(file_fd, frame->buffer, offset.frame_len);
2314 LOGD("written number of bytes %zd", written_len);
2315 close(file_fd);
2316 } else {
2317 LOGE("failed to open file to dump image");
2318 }
2319 } else {
2320 LOGE("localtime_r() error");
2321 }
2322 } else {
2323 LOGE("Could not find stream");
2324 }
2325
2326 }
2327
2328 /*===========================================================================
2329 * FUNCTION : streamCbRoutine
2330 *
2331 * DESCRIPTION: Callback routine invoked for each frame generated for
2332 * Rawdump channel
2333 *
2334 * PARAMETERS :
2335 * @super_frame : stream buf frame generated
2336 * @stream : Underlying Stream object cookie
2337 *
2338 * RETURN : NA
2339 *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,__unused QCamera3Stream * stream)2340 void QCamera3RawDumpChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
2341 __unused QCamera3Stream *stream)
2342 {
2343 LOGD("E");
2344 if (super_frame == NULL || super_frame->num_bufs != 1) {
2345 LOGE("super_frame is not valid");
2346 return;
2347 }
2348
2349 if (mRawDump)
2350 dumpRawSnapshot(super_frame->bufs[0]);
2351
2352 bufDone(super_frame);
2353 free(super_frame);
2354 }
2355
2356 /*===========================================================================
2357 * FUNCTION : getStreamBufs
2358 *
2359 * DESCRIPTION: Callback function provided to interface to get buffers.
2360 *
2361 * PARAMETERS :
2362 * @len : Length of each buffer to be allocated
2363 *
2364 * RETURN : NULL on buffer allocation failure
2365 * QCamera3StreamMem object on sucess
2366 *==========================================================================*/
getStreamBufs(uint32_t len)2367 QCamera3StreamMem* QCamera3RawDumpChannel::getStreamBufs(uint32_t len)
2368 {
2369 int rc;
2370 mMemory = new QCamera3StreamMem(mNumBuffers);
2371
2372 if (!mMemory) {
2373 LOGE("unable to create heap memory");
2374 return NULL;
2375 }
2376 rc = mMemory->allocateAll((size_t)len);
2377 if (rc < 0) {
2378 LOGE("unable to allocate heap memory");
2379 delete mMemory;
2380 mMemory = NULL;
2381 return NULL;
2382 }
2383 return mMemory;
2384 }
2385
2386 /*===========================================================================
2387 * FUNCTION : putStreamBufs
2388 *
2389 * DESCRIPTION: Callback function provided to interface to return buffers.
2390 * Although no handles are actually returned, implicitl assumption
2391 * that interface will no longer use buffers and channel can
2392 * deallocated if necessary.
2393 *
2394 * PARAMETERS : NA
2395 *
2396 * RETURN : NA
2397 *==========================================================================*/
putStreamBufs()2398 void QCamera3RawDumpChannel::putStreamBufs()
2399 {
2400 mMemory->deallocate();
2401 delete mMemory;
2402 mMemory = NULL;
2403 }
2404
2405 /*===========================================================================
2406 * FUNCTION : request
2407 *
2408 * DESCRIPTION: Request function used as trigger
2409 *
2410 * PARAMETERS :
2411 * @recvd_frame : buffer- this will be NULL since this is internal channel
2412 * @frameNumber : Undefined again since this is internal stream
2413 *
2414 * RETURN : int32_t type of status
2415 * NO_ERROR -- success
2416 * none-zero failure code
2417 *==========================================================================*/
request(buffer_handle_t *,uint32_t)2418 int32_t QCamera3RawDumpChannel::request(buffer_handle_t * /*buffer*/,
2419 uint32_t /*frameNumber*/)
2420 {
2421 if (!m_bIsActive) {
2422 return QCamera3Channel::start();
2423 }
2424 else
2425 return 0;
2426 }
2427
2428 /*===========================================================================
2429 * FUNCTION : intialize
2430 *
2431 * DESCRIPTION: Initializes channel params and creates underlying stream
2432 *
2433 * PARAMETERS :
2434 * @isType : type of image stabilization required on this stream
2435 *
2436 * RETURN : int32_t type of status
2437 * NO_ERROR -- success
2438 * none-zero failure code
2439 *==========================================================================*/
initialize(cam_is_type_t isType)2440 int32_t QCamera3RawDumpChannel::initialize(cam_is_type_t isType)
2441 {
2442 int32_t rc;
2443
2444 mIsType = isType;
2445 rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_RAW,
2446 CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG, mDim, ROTATE_0, (uint8_t)mNumBuffers,
2447 mPostProcMask, mIsType);
2448 if (rc < 0) {
2449 LOGE("addStream failed");
2450 }
2451 return rc;
2452 }
2453 /*************************************************************************************/
2454
2455 /* QCamera3YUVChannel methods */
2456
2457 /*===========================================================================
2458 * FUNCTION : QCamera3YUVChannel
2459 *
2460 * DESCRIPTION: constructor of QCamera3YUVChannel
2461 *
2462 * PARAMETERS :
2463 * @cam_handle : camera handle
2464 * @cam_ops : ptr to camera ops table
2465 * @cb_routine : callback routine to frame aggregator
2466 * @paddingInfo : padding information for the stream
2467 * @stream : camera3_stream_t structure
2468 * @stream_type: Channel stream type
2469 * @postprocess_mask: the postprocess mask for streams of this channel
2470 * @metadataChannel: handle to the metadataChannel
2471 * RETURN : none
2472 *==========================================================================*/
QCamera3YUVChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,channel_cb_routine cb_routine,cam_padding_info_t * paddingInfo,void * userData,camera3_stream_t * stream,cam_stream_type_t stream_type,uint32_t postprocess_mask,QCamera3Channel * metadataChannel)2473 QCamera3YUVChannel::QCamera3YUVChannel(uint32_t cam_handle,
2474 uint32_t channel_handle,
2475 mm_camera_ops_t *cam_ops,
2476 channel_cb_routine cb_routine,
2477 cam_padding_info_t *paddingInfo,
2478 void *userData,
2479 camera3_stream_t *stream,
2480 cam_stream_type_t stream_type,
2481 uint32_t postprocess_mask,
2482 QCamera3Channel *metadataChannel) :
2483 QCamera3ProcessingChannel(cam_handle, channel_handle, cam_ops,
2484 cb_routine, paddingInfo, userData, stream, stream_type,
2485 postprocess_mask, metadataChannel)
2486 {
2487
2488 mBypass = (postprocess_mask == CAM_QCOM_FEATURE_NONE);
2489 mFrameLen = 0;
2490 mEdgeMode.edge_mode = CAM_EDGE_MODE_OFF;
2491 mEdgeMode.sharpness = 0;
2492 mNoiseRedMode = CAM_NOISE_REDUCTION_MODE_OFF;
2493 memset(&mCropRegion, 0, sizeof(mCropRegion));
2494 }
2495
2496 /*===========================================================================
2497 * FUNCTION : ~QCamera3YUVChannel
2498 *
2499 * DESCRIPTION: destructor of QCamera3YUVChannel
2500 *
2501 * PARAMETERS : none
2502 *
2503 *
2504 * RETURN : none
2505 *==========================================================================*/
~QCamera3YUVChannel()2506 QCamera3YUVChannel::~QCamera3YUVChannel()
2507 {
2508 // Deallocation of heap buffers allocated in mMemory is freed
2509 // automatically by its destructor
2510 }
2511
2512 /*===========================================================================
2513 * FUNCTION : initialize
2514 *
2515 * DESCRIPTION: Initialize and add camera channel & stream
2516 *
2517 * PARAMETERS :
2518 * @isType : the image stabilization type
2519 *
2520 * RETURN : int32_t type of status
2521 * NO_ERROR -- success
2522 * none-zero failure code
2523 *==========================================================================*/
initialize(cam_is_type_t isType)2524 int32_t QCamera3YUVChannel::initialize(cam_is_type_t isType)
2525 {
2526 ATRACE_CALL();
2527 int32_t rc = NO_ERROR;
2528 cam_dimension_t streamDim;
2529
2530 if (NULL == mCamera3Stream) {
2531 LOGE("Camera stream uninitialized");
2532 return NO_INIT;
2533 }
2534
2535 if (1 <= m_numStreams) {
2536 // Only one stream per channel supported in v3 Hal
2537 return NO_ERROR;
2538 }
2539
2540 mIsType = isType;
2541 mStreamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_CALLBACK);
2542 streamDim.width = mCamera3Stream->width;
2543 streamDim.height = mCamera3Stream->height;
2544
2545 rc = QCamera3Channel::addStream(mStreamType,
2546 mStreamFormat,
2547 streamDim,
2548 ROTATE_0,
2549 mNumBufs,
2550 mPostProcMask,
2551 mIsType);
2552 if (rc < 0) {
2553 LOGE("addStream failed");
2554 return rc;
2555 }
2556
2557 cam_stream_buf_plane_info_t buf_planes;
2558 cam_padding_info_t paddingInfo = mPaddingInfo;
2559
2560 memset(&buf_planes, 0, sizeof(buf_planes));
2561 //to ensure a big enough buffer size set the height and width
2562 //padding to max(height padding, width padding)
2563 paddingInfo.width_padding = MAX(paddingInfo.width_padding, paddingInfo.height_padding);
2564 paddingInfo.height_padding = paddingInfo.width_padding;
2565
2566 rc = mm_stream_calc_offset_snapshot(mStreamFormat, &streamDim, &paddingInfo,
2567 &buf_planes);
2568 if (rc < 0) {
2569 LOGE("mm_stream_calc_offset_preview failed");
2570 return rc;
2571 }
2572
2573 mFrameLen = buf_planes.plane_info.frame_len;
2574
2575 if (NO_ERROR != rc) {
2576 LOGE("Initialize failed, rc = %d", rc);
2577 return rc;
2578 }
2579
2580 /* initialize offline meta memory for input reprocess */
2581 rc = QCamera3ProcessingChannel::initialize(isType);
2582 if (NO_ERROR != rc) {
2583 LOGE("Processing Channel initialize failed, rc = %d",
2584 rc);
2585 }
2586
2587 return rc;
2588 }
2589
2590 /*===========================================================================
2591 * FUNCTION : request
2592 *
2593 * DESCRIPTION: entry function for a request on a YUV stream. This function
2594 * has the logic to service a request based on its type
2595 *
2596 * PARAMETERS :
2597 * @buffer : pointer to the output buffer
2598 * @frameNumber : frame number of the request
2599 * @pInputBuffer : pointer to input buffer if an input request
2600 * @metadata : parameters associated with the request
2601 *
2602 * RETURN : 0 on a success start of capture
2603 * -EINVAL on invalid input
2604 * -ENODEV on serious error
2605 *==========================================================================*/
request(buffer_handle_t * buffer,uint32_t frameNumber,camera3_stream_buffer_t * pInputBuffer,metadata_buffer_t * metadata,bool & needMetadata)2606 int32_t QCamera3YUVChannel::request(buffer_handle_t *buffer,
2607 uint32_t frameNumber,
2608 camera3_stream_buffer_t* pInputBuffer,
2609 metadata_buffer_t* metadata, bool &needMetadata)
2610 {
2611 int32_t rc = NO_ERROR;
2612 Mutex::Autolock lock(mOfflinePpLock);
2613
2614 LOGD("pInputBuffer is %p frame number %d", pInputBuffer, frameNumber);
2615 if (NULL == buffer || NULL == metadata) {
2616 LOGE("Invalid buffer/metadata in channel request");
2617 return BAD_VALUE;
2618 }
2619
2620 PpInfo ppInfo;
2621 memset(&ppInfo, 0, sizeof(ppInfo));
2622 ppInfo.frameNumber = frameNumber;
2623 ppInfo.offlinePpFlag = false;
2624 if (mBypass && !pInputBuffer ) {
2625 ppInfo.offlinePpFlag = needsFramePostprocessing(metadata);
2626 ppInfo.output = buffer;
2627 mOfflinePpInfoList.push_back(ppInfo);
2628 }
2629
2630 LOGD("offlinePpFlag is %d", ppInfo.offlinePpFlag);
2631 needMetadata = ppInfo.offlinePpFlag;
2632 if (!ppInfo.offlinePpFlag) {
2633 // regular request
2634 return QCamera3ProcessingChannel::request(buffer, frameNumber,
2635 pInputBuffer, metadata);
2636 } else {
2637 if(!m_bIsActive) {
2638 rc = start();
2639 if (NO_ERROR != rc)
2640 return rc;
2641 } else {
2642 LOGD("Request on an existing stream");
2643 }
2644
2645 //we need to send this frame through the CPP
2646 //Allocate heap memory, then buf done on the buffer
2647 uint32_t bufIdx;
2648 if (mFreeHeapBufferList.empty()) {
2649 rc = mMemory.allocateOne(mFrameLen);
2650 if (rc < 0) {
2651 LOGE("Failed allocating heap buffer. Fatal");
2652 return BAD_VALUE;
2653 } else {
2654 bufIdx = (uint32_t)rc;
2655 }
2656 } else {
2657 bufIdx = *(mFreeHeapBufferList.begin());
2658 mFreeHeapBufferList.erase(mFreeHeapBufferList.begin());
2659 }
2660
2661 /* Configure and start postproc if necessary */
2662 reprocess_config_t reproc_cfg;
2663 cam_dimension_t dim;
2664 memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
2665 memset(&dim, 0, sizeof(dim));
2666 mStreams[0]->getFrameDimension(dim);
2667 setReprocConfig(reproc_cfg, NULL, metadata, mStreamFormat, dim);
2668
2669 // Start postprocessor without input buffer
2670 startPostProc(reproc_cfg);
2671
2672 LOGD("erasing %d", bufIdx);
2673
2674 mMemory.markFrameNumber(bufIdx, frameNumber);
2675 mStreams[0]->bufDone(bufIdx);
2676
2677 }
2678 return rc;
2679 }
2680
2681 /*===========================================================================
2682 * FUNCTION : streamCbRoutine
2683 *
2684 * DESCRIPTION:
2685 *
2686 * PARAMETERS :
2687 * @super_frame : the super frame with filled buffer
2688 * @stream : stream on which the buffer was requested and filled
2689 *
2690 * RETURN : none
2691 *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)2692 void QCamera3YUVChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
2693 QCamera3Stream *stream)
2694 {
2695 ATRACE_CALL();
2696 uint8_t frameIndex;
2697 int32_t resultFrameNumber;
2698
2699 if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
2700 LOGE("Error with the stream callback");
2701 return;
2702 }
2703
2704 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
2705 if(frameIndex >= mNumBufs) {
2706 LOGE("Error, Invalid index for buffer");
2707 stream->bufDone(frameIndex);
2708 return;
2709 }
2710
2711 if (mBypass) {
2712 List<PpInfo>::iterator ppInfo;
2713
2714 Mutex::Autolock lock(mOfflinePpLock);
2715 resultFrameNumber = mMemory.getFrameNumber(frameIndex);
2716 for (ppInfo = mOfflinePpInfoList.begin();
2717 ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
2718 if (ppInfo->frameNumber == (uint32_t)resultFrameNumber) {
2719 break;
2720 }
2721 }
2722 LOGD("frame index %d, frame number %d", frameIndex, resultFrameNumber);
2723 //check the reprocessing required flag against the frame number
2724 if (ppInfo == mOfflinePpInfoList.end()) {
2725 LOGE("Error, request for frame number is a reprocess.");
2726 stream->bufDone(frameIndex);
2727 return;
2728 }
2729
2730 if (ppInfo->offlinePpFlag) {
2731 mm_camera_super_buf_t *frame =
2732 (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
2733 if (frame == NULL) {
2734 LOGE("Error allocating memory to save received_frame structure.");
2735 if(stream) {
2736 stream->bufDone(frameIndex);
2737 }
2738 return;
2739 }
2740
2741 *frame = *super_frame;
2742 m_postprocessor.processData(frame, ppInfo->output, resultFrameNumber);
2743 free(super_frame);
2744 return;
2745 } else {
2746 if (ppInfo != mOfflinePpInfoList.begin()) {
2747 // There is pending reprocess buffer, cache current buffer
2748 if (ppInfo->callback_buffer != NULL) {
2749 LOGE("Fatal: cached callback_buffer is already present");
2750 }
2751 ppInfo->callback_buffer = super_frame;
2752 return;
2753 } else {
2754 mOfflinePpInfoList.erase(ppInfo);
2755 }
2756 }
2757 }
2758
2759 QCamera3ProcessingChannel::streamCbRoutine(super_frame, stream);
2760 return;
2761 }
2762
2763 /*===========================================================================
2764 * FUNCTION : reprocessCbRoutine
2765 *
2766 * DESCRIPTION: callback function for the reprocessed frame. This frame now
2767 * should be returned to the framework. This same callback is
2768 * used during input reprocessing or offline postprocessing
2769 *
2770 * PARAMETERS :
2771 * @resultBuffer : buffer containing the reprocessed data
2772 * @resultFrameNumber : frame number on which the buffer was requested
2773 *
2774 * RETURN : NONE
2775 *
2776 *==========================================================================*/
reprocessCbRoutine(buffer_handle_t * resultBuffer,uint32_t resultFrameNumber)2777 void QCamera3YUVChannel::reprocessCbRoutine(buffer_handle_t *resultBuffer,
2778 uint32_t resultFrameNumber)
2779 {
2780 LOGD("E: frame number %d", resultFrameNumber);
2781 Vector<mm_camera_super_buf_t *> pendingCbs;
2782
2783 /* release the input buffer and input metadata buffer if used */
2784 if (0 > mMemory.getHeapBufferIndex(resultFrameNumber)) {
2785 /* mOfflineMemory and mOfflineMetaMemory used only for input reprocessing */
2786 int32_t rc = releaseOfflineMemory(resultFrameNumber);
2787 if (NO_ERROR != rc) {
2788 LOGE("Error releasing offline memory rc = %d", rc);
2789 }
2790 /* Since reprocessing is done, send the callback to release the input buffer */
2791 if (mChannelCB) {
2792 mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
2793 }
2794 }
2795
2796 if (mBypass) {
2797 int32_t rc = handleOfflinePpCallback(resultFrameNumber, pendingCbs);
2798 if (rc != NO_ERROR) {
2799 return;
2800 }
2801 }
2802
2803 issueChannelCb(resultBuffer, resultFrameNumber);
2804
2805 // Call all pending callbacks to return buffers
2806 for (size_t i = 0; i < pendingCbs.size(); i++) {
2807 QCamera3ProcessingChannel::streamCbRoutine(
2808 pendingCbs[i], mStreams[0]);
2809 }
2810
2811 }
2812
2813 /*===========================================================================
2814 * FUNCTION : needsFramePostprocessing
2815 *
2816 * DESCRIPTION:
2817 *
2818 * PARAMETERS :
2819 *
2820 * RETURN :
2821 * TRUE if frame needs to be postprocessed
2822 * FALSE is frame does not need to be postprocessed
2823 *
2824 *==========================================================================*/
needsFramePostprocessing(metadata_buffer_t * meta)2825 bool QCamera3YUVChannel::needsFramePostprocessing(metadata_buffer_t *meta)
2826 {
2827 bool ppNeeded = false;
2828
2829 //sharpness
2830 IF_META_AVAILABLE(cam_edge_application_t, edgeMode,
2831 CAM_INTF_META_EDGE_MODE, meta) {
2832 mEdgeMode = *edgeMode;
2833 }
2834
2835 //wnr
2836 IF_META_AVAILABLE(uint32_t, noiseRedMode,
2837 CAM_INTF_META_NOISE_REDUCTION_MODE, meta) {
2838 mNoiseRedMode = *noiseRedMode;
2839 }
2840
2841 //crop region
2842 IF_META_AVAILABLE(cam_crop_region_t, scalerCropRegion,
2843 CAM_INTF_META_SCALER_CROP_REGION, meta) {
2844 mCropRegion = *scalerCropRegion;
2845 }
2846
2847 if ((CAM_EDGE_MODE_OFF != mEdgeMode.edge_mode) &&
2848 (CAM_EDGE_MODE_ZERO_SHUTTER_LAG != mEdgeMode.edge_mode)) {
2849 ppNeeded = true;
2850 }
2851 if ((CAM_NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG != mNoiseRedMode) &&
2852 (CAM_NOISE_REDUCTION_MODE_OFF != mNoiseRedMode) &&
2853 (CAM_NOISE_REDUCTION_MODE_MINIMAL != mNoiseRedMode)) {
2854 ppNeeded = true;
2855 }
2856 if ((mCropRegion.width < (int32_t)mCamera3Stream->width) ||
2857 (mCropRegion.height < (int32_t)mCamera3Stream->height)) {
2858 ppNeeded = true;
2859 }
2860
2861 return ppNeeded;
2862 }
2863
2864 /*===========================================================================
2865 * FUNCTION : handleOfflinePpCallback
2866 *
2867 * DESCRIPTION: callback function for the reprocessed frame from offline
2868 * postprocessing.
2869 *
2870 * PARAMETERS :
2871 * @resultFrameNumber : frame number on which the buffer was requested
2872 * @pendingCbs : pending buffers to be returned first
2873 *
2874 * RETURN : int32_t type of status
2875 * NO_ERROR -- success
2876 * none-zero failure code
2877 *==========================================================================*/
handleOfflinePpCallback(uint32_t resultFrameNumber,Vector<mm_camera_super_buf_t * > & pendingCbs)2878 int32_t QCamera3YUVChannel::handleOfflinePpCallback(uint32_t resultFrameNumber,
2879 Vector<mm_camera_super_buf_t *>& pendingCbs)
2880 {
2881 Mutex::Autolock lock(mOfflinePpLock);
2882 List<PpInfo>::iterator ppInfo;
2883
2884 for (ppInfo = mOfflinePpInfoList.begin();
2885 ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
2886 if (ppInfo->frameNumber == resultFrameNumber) {
2887 break;
2888 }
2889 }
2890
2891 if (ppInfo == mOfflinePpInfoList.end()) {
2892 LOGI("Request of frame number %d is reprocessing",
2893 resultFrameNumber);
2894 return NO_ERROR;
2895 } else if (ppInfo != mOfflinePpInfoList.begin()) {
2896 LOGE("callback for frame number %d should be head of list",
2897 resultFrameNumber);
2898 return BAD_VALUE;
2899 }
2900
2901 if (ppInfo->offlinePpFlag) {
2902 // Need to get the input buffer frame index from the
2903 // mMemory object and add that to the free heap buffers list.
2904 int32_t bufferIndex =
2905 mMemory.getHeapBufferIndex(resultFrameNumber);
2906 if (bufferIndex < 0) {
2907 LOGE("Fatal %d: no buffer index for frame number %d",
2908 bufferIndex, resultFrameNumber);
2909 return BAD_VALUE;
2910 }
2911 mFreeHeapBufferList.push_back(bufferIndex);
2912 ppInfo = mOfflinePpInfoList.erase(ppInfo);
2913
2914 // Return pending buffer callbacks
2915 while (ppInfo != mOfflinePpInfoList.end() &&
2916 !ppInfo->offlinePpFlag && ppInfo->callback_buffer) {
2917
2918 // Call stream callbacks for cached buffers
2919 pendingCbs.push_back(ppInfo->callback_buffer);
2920
2921 ppInfo = mOfflinePpInfoList.erase(ppInfo);
2922 }
2923
2924 } else {
2925 LOGE("Fatal: request of frame number %d doesn't need"
2926 " offline postprocessing. However there is"
2927 " reprocessing callback.",
2928 resultFrameNumber);
2929 return BAD_VALUE;
2930 }
2931
2932 return NO_ERROR;
2933 }
2934
2935 /*===========================================================================
2936 * FUNCTION : getReprocessType
2937 *
2938 * DESCRIPTION: get the type of reprocess output supported by this channel
2939 *
2940 * PARAMETERS : NONE
2941 *
2942 * RETURN : reprocess_type_t : type of reprocess
2943 *==========================================================================*/
getReprocessType()2944 reprocess_type_t QCamera3YUVChannel::getReprocessType()
2945 {
2946 return REPROCESS_TYPE_YUV;
2947 }
2948
2949 /* QCamera3PicChannel methods */
2950
2951 /*===========================================================================
2952 * FUNCTION : jpegEvtHandle
2953 *
2954 * DESCRIPTION: Function registerd to mm-jpeg-interface to handle jpeg events.
2955 Construct result payload and call mChannelCb to deliver buffer
2956 to framework.
2957 *
2958 * PARAMETERS :
2959 * @status : status of jpeg job
2960 * @client_hdl: jpeg client handle
2961 * @jobId : jpeg job Id
2962 * @p_ouput : ptr to jpeg output result struct
2963 * @userdata : user data ptr
2964 *
2965 * RETURN : none
2966 *==========================================================================*/
jpegEvtHandle(jpeg_job_status_t status,uint32_t,uint32_t jobId,mm_jpeg_output_t * p_output,void * userdata)2967 void QCamera3PicChannel::jpegEvtHandle(jpeg_job_status_t status,
2968 uint32_t /*client_hdl*/,
2969 uint32_t jobId,
2970 mm_jpeg_output_t *p_output,
2971 void *userdata)
2972 {
2973 ATRACE_CALL();
2974 buffer_handle_t *resultBuffer = NULL;
2975 buffer_handle_t *jpegBufferHandle = NULL;
2976 int resultStatus = CAMERA3_BUFFER_STATUS_OK;
2977 camera3_stream_buffer_t result;
2978 camera3_jpeg_blob_t jpegHeader;
2979
2980 KPI_ATRACE_INT("SNAPSHOT", 0);
2981 QCamera3PicChannel *obj = (QCamera3PicChannel *)userdata;
2982 if (obj) {
2983 //Construct payload for process_capture_result. Call mChannelCb
2984
2985 qcamera_hal3_jpeg_data_t *job = obj->m_postprocessor.findJpegJobByJobId(jobId);
2986
2987 if ((job == NULL) || (status == JPEG_JOB_STATUS_ERROR)) {
2988 LOGE("Error in jobId: (%d) with status: %d", jobId, status);
2989 resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
2990 }
2991
2992 if (NULL != job) {
2993 uint32_t bufIdx = (uint32_t)job->jpeg_settings->out_buf_index;
2994 LOGD("jpeg out_buf_index: %d", bufIdx);
2995
2996 //Construct jpeg transient header of type camera3_jpeg_blob_t
2997 //Append at the end of jpeg image of buf_filled_len size
2998
2999 jpegHeader.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
3000 if (JPEG_JOB_STATUS_DONE == status) {
3001 jpegHeader.jpeg_size = (uint32_t)p_output->buf_filled_len;
3002 char* jpeg_buf = (char *)p_output->buf_vaddr;
3003
3004 ssize_t maxJpegSize = -1;
3005
3006 // Gralloc buffer may have additional padding for 4K page size
3007 // Follow size guidelines based on spec since framework relies
3008 // on that to reach end of buffer and with it the header
3009
3010 //Handle same as resultBuffer, but for readablity
3011 jpegBufferHandle =
3012 (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx);
3013
3014 if (NULL != jpegBufferHandle) {
3015 maxJpegSize = ((private_handle_t*)(*jpegBufferHandle))->width;
3016 if (maxJpegSize > obj->mMemory.getSize(bufIdx)) {
3017 maxJpegSize = obj->mMemory.getSize(bufIdx);
3018 }
3019
3020 size_t jpeg_eof_offset =
3021 (size_t)(maxJpegSize - (ssize_t)sizeof(jpegHeader));
3022 char *jpeg_eof = &jpeg_buf[jpeg_eof_offset];
3023 memcpy(jpeg_eof, &jpegHeader, sizeof(jpegHeader));
3024 obj->mMemory.cleanInvalidateCache(bufIdx);
3025 } else {
3026 LOGE("JPEG buffer not found and index: %d",
3027 bufIdx);
3028 resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
3029 }
3030 }
3031
3032 ////Use below data to issue framework callback
3033 resultBuffer =
3034 (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx);
3035 int32_t resultFrameNumber = obj->mMemory.getFrameNumber(bufIdx);
3036 int32_t rc = obj->mMemory.unregisterBuffer(bufIdx);
3037 if (NO_ERROR != rc) {
3038 LOGE("Error %d unregistering stream buffer %d",
3039 rc, bufIdx);
3040 }
3041
3042 result.stream = obj->mCamera3Stream;
3043 result.buffer = resultBuffer;
3044 result.status = resultStatus;
3045 result.acquire_fence = -1;
3046 result.release_fence = -1;
3047
3048 // Release any snapshot buffers before calling
3049 // the user callback. The callback can potentially
3050 // unblock pending requests to snapshot stream.
3051 int32_t snapshotIdx = -1;
3052 mm_camera_super_buf_t* src_frame = NULL;
3053
3054 if (job->src_reproc_frame)
3055 src_frame = job->src_reproc_frame;
3056 else
3057 src_frame = job->src_frame;
3058
3059 if (src_frame) {
3060 if (obj->mStreams[0]->getMyHandle() ==
3061 src_frame->bufs[0]->stream_id) {
3062 snapshotIdx = (int32_t)src_frame->bufs[0]->buf_idx;
3063 if (0 <= snapshotIdx) {
3064 Mutex::Autolock lock(obj->mFreeBuffersLock);
3065 obj->mFreeBufferList.push_back((uint32_t)snapshotIdx);
3066 }
3067 }
3068 }
3069
3070 LOGI("Issue Jpeg Callback frameNumber = %d status = %d",
3071 resultFrameNumber, resultStatus);
3072 if (obj->mChannelCB) {
3073 obj->mChannelCB(NULL,
3074 &result,
3075 (uint32_t)resultFrameNumber,
3076 false,
3077 obj->mUserData);
3078 }
3079
3080 // release internal data for jpeg job
3081 if ((NULL != job->fwk_frame) || (NULL != job->fwk_src_buffer)) {
3082 /* unregister offline input buffer */
3083 int32_t inputBufIndex =
3084 obj->mOfflineMemory.getGrallocBufferIndex((uint32_t)resultFrameNumber);
3085 if (0 <= inputBufIndex) {
3086 rc = obj->mOfflineMemory.unregisterBuffer(inputBufIndex);
3087 } else {
3088 LOGE("could not find the input buf index, frame number %d",
3089 resultFrameNumber);
3090 }
3091 if (NO_ERROR != rc) {
3092 LOGE("Error %d unregistering input buffer %d",
3093 rc, bufIdx);
3094 }
3095
3096 /* unregister offline meta buffer */
3097 int32_t metaBufIndex =
3098 obj->mOfflineMetaMemory.getHeapBufferIndex((uint32_t)resultFrameNumber);
3099 if (0 <= metaBufIndex) {
3100 Mutex::Autolock lock(obj->mFreeOfflineMetaBuffersLock);
3101 obj->mFreeOfflineMetaBuffersList.push_back((uint32_t)metaBufIndex);
3102 } else {
3103 LOGE("could not find the input meta buf index, frame number %d",
3104 resultFrameNumber);
3105 }
3106 }
3107 obj->m_postprocessor.releaseOfflineBuffers(false);
3108 obj->m_postprocessor.releaseJpegJobData(job);
3109 free(job);
3110 }
3111
3112 return;
3113 // }
3114 } else {
3115 LOGE("Null userdata in jpeg callback");
3116 }
3117 }
3118
QCamera3PicChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,channel_cb_routine cb_routine,cam_padding_info_t * paddingInfo,void * userData,camera3_stream_t * stream,uint32_t postprocess_mask,bool is4KVideo,bool isInputStreamConfigured,QCamera3Channel * metadataChannel,uint32_t numBuffers)3119 QCamera3PicChannel::QCamera3PicChannel(uint32_t cam_handle,
3120 uint32_t channel_handle,
3121 mm_camera_ops_t *cam_ops,
3122 channel_cb_routine cb_routine,
3123 cam_padding_info_t *paddingInfo,
3124 void *userData,
3125 camera3_stream_t *stream,
3126 uint32_t postprocess_mask,
3127 bool is4KVideo,
3128 bool isInputStreamConfigured,
3129 QCamera3Channel *metadataChannel,
3130 uint32_t numBuffers) :
3131 QCamera3ProcessingChannel(cam_handle, channel_handle,
3132 cam_ops, cb_routine, paddingInfo, userData,
3133 stream, CAM_STREAM_TYPE_SNAPSHOT,
3134 postprocess_mask, metadataChannel, numBuffers),
3135 mNumSnapshotBufs(0),
3136 mInputBufferHint(isInputStreamConfigured),
3137 mYuvMemory(NULL),
3138 mFrameLen(0)
3139 {
3140 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
3141 m_max_pic_dim = hal_obj->calcMaxJpegDim();
3142 mYuvWidth = stream->width;
3143 mYuvHeight = stream->height;
3144 mStreamType = CAM_STREAM_TYPE_SNAPSHOT;
3145 // Use same pixelformat for 4K video case
3146 mStreamFormat = is4KVideo ?
3147 getStreamDefaultFormat(CAM_STREAM_TYPE_VIDEO)
3148 :getStreamDefaultFormat(CAM_STREAM_TYPE_SNAPSHOT);
3149 int32_t rc = m_postprocessor.initJpeg(jpegEvtHandle, &m_max_pic_dim, this);
3150 if (rc != 0) {
3151 LOGE("Init Postprocessor failed");
3152 }
3153 }
3154
3155 /*===========================================================================
3156 * FUNCTION : flush
3157 *
3158 * DESCRIPTION: flush pic channel, which will stop all processing within, including
3159 * the reprocessing channel in postprocessor and YUV stream.
3160 *
3161 * PARAMETERS : none
3162 *
3163 * RETURN : int32_t type of status
3164 * NO_ERROR -- success
3165 * none-zero failure code
3166 *==========================================================================*/
flush()3167 int32_t QCamera3PicChannel::flush()
3168 {
3169 int32_t rc = NO_ERROR;
3170 if(!m_bIsActive) {
3171 LOGE("Attempt to flush inactive channel");
3172 return NO_INIT;
3173 }
3174
3175 rc = m_postprocessor.flush();
3176 if (rc == 0) {
3177 LOGE("Postprocessor flush failed, rc = %d", rc);
3178 return rc;
3179 }
3180
3181 if (0 < mOfflineMetaMemory.getCnt()) {
3182 mOfflineMetaMemory.deallocate();
3183 }
3184 if (0 < mOfflineMemory.getCnt()) {
3185 mOfflineMemory.unregisterBuffers();
3186 }
3187 Mutex::Autolock lock(mFreeBuffersLock);
3188 mFreeBufferList.clear();
3189 for (uint32_t i = 0; i < mCamera3Stream->max_buffers; i++) {
3190 mFreeBufferList.push_back(i);
3191 }
3192 return rc;
3193 }
3194
3195
~QCamera3PicChannel()3196 QCamera3PicChannel::~QCamera3PicChannel()
3197 {
3198 }
3199
initialize(cam_is_type_t isType)3200 int32_t QCamera3PicChannel::initialize(cam_is_type_t isType)
3201 {
3202 int32_t rc = NO_ERROR;
3203 cam_dimension_t streamDim;
3204 cam_stream_type_t streamType;
3205 cam_format_t streamFormat;
3206
3207 if (NULL == mCamera3Stream) {
3208 LOGE("Camera stream uninitialized");
3209 return NO_INIT;
3210 }
3211
3212 if (1 <= m_numStreams) {
3213 // Only one stream per channel supported in v3 Hal
3214 return NO_ERROR;
3215 }
3216
3217 mIsType = isType;
3218 streamType = mStreamType;
3219 streamFormat = mStreamFormat;
3220 streamDim.width = (int32_t)mYuvWidth;
3221 streamDim.height = (int32_t)mYuvHeight;
3222
3223 mNumSnapshotBufs = mCamera3Stream->max_buffers;
3224 rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
3225 ROTATE_0, (uint8_t)mCamera3Stream->max_buffers, mPostProcMask,
3226 mIsType);
3227
3228 if (NO_ERROR != rc) {
3229 LOGE("Initialize failed, rc = %d", rc);
3230 return rc;
3231 }
3232
3233 /* initialize offline meta memory for input reprocess */
3234 rc = QCamera3ProcessingChannel::initialize(isType);
3235 if (NO_ERROR != rc) {
3236 LOGE("Processing Channel initialize failed, rc = %d",
3237 rc);
3238 }
3239
3240 return rc;
3241 }
3242
3243 /*===========================================================================
3244 * FUNCTION : request
3245 *
3246 * DESCRIPTION: handle the request - either with an input buffer or a direct
3247 * output request
3248 *
3249 * PARAMETERS :
3250 * @buffer : pointer to the output buffer
3251 * @frameNumber : frame number of the request
3252 * @pInputBuffer : pointer to input buffer if an input request
3253 * @metadata : parameters associated with the request
3254 *
3255 * RETURN : 0 on a success start of capture
3256 * -EINVAL on invalid input
3257 * -ENODEV on serious error
3258 *==========================================================================*/
request(buffer_handle_t * buffer,uint32_t frameNumber,camera3_stream_buffer_t * pInputBuffer,metadata_buffer_t * metadata)3259 int32_t QCamera3PicChannel::request(buffer_handle_t *buffer,
3260 uint32_t frameNumber,
3261 camera3_stream_buffer_t *pInputBuffer,
3262 metadata_buffer_t *metadata)
3263 {
3264 ATRACE_CALL();
3265 //FIX ME: Return buffer back in case of failures below.
3266
3267 int32_t rc = NO_ERROR;
3268
3269 reprocess_config_t reproc_cfg;
3270 cam_dimension_t dim;
3271 memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
3272 //make sure to set the correct input stream dim in case of YUV size override
3273 //and recalculate the plane info
3274 dim.width = (int32_t)mYuvWidth;
3275 dim.height = (int32_t)mYuvHeight;
3276 setReprocConfig(reproc_cfg, pInputBuffer, metadata, mStreamFormat, dim);
3277
3278 // Picture stream has already been started before any request comes in
3279 if (!m_bIsActive) {
3280 LOGE("Channel not started!!");
3281 return NO_INIT;
3282 }
3283
3284 int index = mMemory.getMatchBufIndex((void*)buffer);
3285
3286 if(index < 0) {
3287 rc = registerBuffer(buffer, mIsType);
3288 if (NO_ERROR != rc) {
3289 LOGE("On-the-fly buffer registration failed %d",
3290 rc);
3291 return rc;
3292 }
3293
3294 index = mMemory.getMatchBufIndex((void*)buffer);
3295 if (index < 0) {
3296 LOGE("Could not find object among registered buffers");
3297 return DEAD_OBJECT;
3298 }
3299 }
3300 LOGD("buffer index %d, frameNumber: %u", index, frameNumber);
3301
3302 rc = mMemory.markFrameNumber((uint32_t)index, frameNumber);
3303
3304 // Start postprocessor
3305 startPostProc(reproc_cfg);
3306
3307 // Queue jpeg settings
3308 rc = queueJpegSetting((uint32_t)index, metadata);
3309
3310 if (pInputBuffer == NULL) {
3311 Mutex::Autolock lock(mFreeBuffersLock);
3312 uint32_t bufIdx;
3313 if (mFreeBufferList.empty()) {
3314 rc = mYuvMemory->allocateOne(mFrameLen);
3315 if (rc < 0) {
3316 LOGE("Failed to allocate heap buffer. Fatal");
3317 return rc;
3318 } else {
3319 bufIdx = (uint32_t)rc;
3320 }
3321 } else {
3322 List<uint32_t>::iterator it = mFreeBufferList.begin();
3323 bufIdx = *it;
3324 mFreeBufferList.erase(it);
3325 }
3326 mYuvMemory->markFrameNumber(bufIdx, frameNumber);
3327 mStreams[0]->bufDone(bufIdx);
3328 } else {
3329 qcamera_fwk_input_pp_data_t *src_frame = NULL;
3330 src_frame = (qcamera_fwk_input_pp_data_t *)calloc(1,
3331 sizeof(qcamera_fwk_input_pp_data_t));
3332 if (src_frame == NULL) {
3333 LOGE("No memory for src frame");
3334 return NO_MEMORY;
3335 }
3336 rc = setFwkInputPPData(src_frame, pInputBuffer, &reproc_cfg, metadata,
3337 NULL /*fwk output buffer*/, frameNumber);
3338 if (NO_ERROR != rc) {
3339 LOGE("Error %d while setting framework input PP data", rc);
3340 free(src_frame);
3341 return rc;
3342 }
3343 LOGH("Post-process started");
3344 m_postprocessor.processData(src_frame);
3345 }
3346 return rc;
3347 }
3348
3349
3350
3351 /*===========================================================================
3352 * FUNCTION : dataNotifyCB
3353 *
3354 * DESCRIPTION: Channel Level callback used for super buffer data notify.
3355 * This function is registered with mm-camera-interface to handle
3356 * data notify
3357 *
3358 * PARAMETERS :
3359 * @recvd_frame : stream frame received
3360 * userdata : user data ptr
3361 *
3362 * RETURN : none
3363 *==========================================================================*/
dataNotifyCB(mm_camera_super_buf_t * recvd_frame,void * userdata)3364 void QCamera3PicChannel::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
3365 void *userdata)
3366 {
3367 ATRACE_CALL();
3368 LOGD("E\n");
3369 QCamera3PicChannel *channel = (QCamera3PicChannel *)userdata;
3370
3371 if (channel == NULL) {
3372 LOGE("invalid channel pointer");
3373 return;
3374 }
3375
3376 if(channel->m_numStreams != 1) {
3377 LOGE("Error: Bug: This callback assumes one stream per channel");
3378 return;
3379 }
3380
3381
3382 if(channel->mStreams[0] == NULL) {
3383 LOGE("Error: Invalid Stream object");
3384 return;
3385 }
3386
3387 channel->QCamera3PicChannel::streamCbRoutine(recvd_frame, channel->mStreams[0]);
3388
3389 LOGD("X\n");
3390 return;
3391 }
3392
3393 /*===========================================================================
3394 * FUNCTION : streamCbRoutine
3395 *
3396 * DESCRIPTION:
3397 *
3398 * PARAMETERS :
3399 * @super_frame : the super frame with filled buffer
3400 * @stream : stream on which the buffer was requested and filled
3401 *
3402 * RETURN : none
3403 *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)3404 void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
3405 QCamera3Stream *stream)
3406 {
3407 ATRACE_CALL();
3408 //TODO
3409 //Used only for getting YUV. Jpeg callback will be sent back from channel
3410 //directly to HWI. Refer to func jpegEvtHandle
3411
3412 //Got the yuv callback. Calling yuv callback handler in PostProc
3413 uint8_t frameIndex;
3414 mm_camera_super_buf_t* frame = NULL;
3415 cam_dimension_t dim;
3416 cam_frame_len_offset_t offset;
3417
3418 memset(&dim, 0, sizeof(dim));
3419 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
3420
3421 if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
3422 LOGE("Error with the stream callback");
3423 return;
3424 }
3425
3426 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
3427 LOGD("recvd buf_idx: %u for further processing",
3428 (uint32_t)frameIndex);
3429 if(frameIndex >= mNumSnapshotBufs) {
3430 LOGE("Error, Invalid index for buffer");
3431 if(stream) {
3432 Mutex::Autolock lock(mFreeBuffersLock);
3433 mFreeBufferList.push_back(frameIndex);
3434 stream->bufDone(frameIndex);
3435 }
3436 return;
3437 }
3438
3439 frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
3440 if (frame == NULL) {
3441 LOGE("Error allocating memory to save received_frame structure.");
3442 if(stream) {
3443 Mutex::Autolock lock(mFreeBuffersLock);
3444 mFreeBufferList.push_back(frameIndex);
3445 stream->bufDone(frameIndex);
3446 }
3447 return;
3448 }
3449 *frame = *super_frame;
3450 stream->getFrameDimension(dim);
3451 stream->getFrameOffset(offset);
3452 dumpYUV(frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_INPUT_REPROCESS);
3453
3454 m_postprocessor.processData(frame);
3455 free(super_frame);
3456 return;
3457 }
3458
getStreamBufs(uint32_t len)3459 QCamera3StreamMem* QCamera3PicChannel::getStreamBufs(uint32_t len)
3460 {
3461 mYuvMemory = new QCamera3StreamMem(mCamera3Stream->max_buffers, false);
3462 if (!mYuvMemory) {
3463 LOGE("unable to create metadata memory");
3464 return NULL;
3465 }
3466 mFrameLen = len;
3467
3468 return mYuvMemory;
3469 }
3470
putStreamBufs()3471 void QCamera3PicChannel::putStreamBufs()
3472 {
3473 QCamera3ProcessingChannel::putStreamBufs();
3474
3475 mYuvMemory->deallocate();
3476 delete mYuvMemory;
3477 mYuvMemory = NULL;
3478 mFreeBufferList.clear();
3479 }
3480
queueJpegSetting(uint32_t index,metadata_buffer_t * metadata)3481 int32_t QCamera3PicChannel::queueJpegSetting(uint32_t index, metadata_buffer_t *metadata)
3482 {
3483 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
3484 jpeg_settings_t *settings =
3485 (jpeg_settings_t *)malloc(sizeof(jpeg_settings_t));
3486
3487 if (!settings) {
3488 LOGE("out of memory allocating jpeg_settings");
3489 return -ENOMEM;
3490 }
3491
3492 memset(settings, 0, sizeof(jpeg_settings_t));
3493
3494 settings->out_buf_index = index;
3495
3496 settings->jpeg_orientation = 0;
3497 IF_META_AVAILABLE(int32_t, orientation, CAM_INTF_META_JPEG_ORIENTATION, metadata) {
3498 settings->jpeg_orientation = *orientation;
3499 }
3500
3501 settings->jpeg_quality = 85;
3502 IF_META_AVAILABLE(uint32_t, quality1, CAM_INTF_META_JPEG_QUALITY, metadata) {
3503 settings->jpeg_quality = (uint8_t) *quality1;
3504 }
3505
3506 IF_META_AVAILABLE(uint32_t, quality2, CAM_INTF_META_JPEG_THUMB_QUALITY, metadata) {
3507 settings->jpeg_thumb_quality = (uint8_t) *quality2;
3508 }
3509
3510 IF_META_AVAILABLE(cam_dimension_t, dimension, CAM_INTF_META_JPEG_THUMB_SIZE, metadata) {
3511 settings->thumbnail_size = *dimension;
3512 }
3513
3514 settings->gps_timestamp_valid = 0;
3515 IF_META_AVAILABLE(int64_t, timestamp, CAM_INTF_META_JPEG_GPS_TIMESTAMP, metadata) {
3516 settings->gps_timestamp = *timestamp;
3517 settings->gps_timestamp_valid = 1;
3518 }
3519
3520 settings->gps_coordinates_valid = 0;
3521 IF_META_AVAILABLE(double, coordinates, CAM_INTF_META_JPEG_GPS_COORDINATES, metadata) {
3522 memcpy(settings->gps_coordinates, coordinates, 3*sizeof(double));
3523 settings->gps_coordinates_valid = 1;
3524 }
3525
3526 IF_META_AVAILABLE(uint8_t, proc_methods, CAM_INTF_META_JPEG_GPS_PROC_METHODS, metadata) {
3527 memset(settings->gps_processing_method, 0,
3528 sizeof(settings->gps_processing_method));
3529 strlcpy(settings->gps_processing_method, (const char *)proc_methods,
3530 sizeof(settings->gps_processing_method));
3531 }
3532
3533 // Image description
3534 const char *eepromVersion = hal_obj->getEepromVersionInfo();
3535 const uint32_t *ldafCalib = hal_obj->getLdafCalib();
3536 if ((eepromVersion && strlen(eepromVersion)) ||
3537 ldafCalib) {
3538 int len = 0;
3539 settings->image_desc_valid = true;
3540 if (eepromVersion && strlen(eepromVersion)) {
3541 len = snprintf(settings->image_desc, sizeof(settings->image_desc),
3542 "M:%s ", eepromVersion);
3543 }
3544 if (ldafCalib) {
3545 snprintf(settings->image_desc + len,
3546 sizeof(settings->image_desc) - len, "L:%u-%u",
3547 ldafCalib[0], ldafCalib[1]);
3548 }
3549 }
3550
3551 return m_postprocessor.processJpegSettingData(settings);
3552 }
3553
3554
overrideYuvSize(uint32_t width,uint32_t height)3555 void QCamera3PicChannel::overrideYuvSize(uint32_t width, uint32_t height)
3556 {
3557 mYuvWidth = width;
3558 mYuvHeight = height;
3559 }
3560
3561 /*===========================================================================
3562 * FUNCTION : getReprocessType
3563 *
3564 * DESCRIPTION: get the type of reprocess output supported by this channel
3565 *
3566 * PARAMETERS : NONE
3567 *
3568 * RETURN : reprocess_type_t : type of reprocess
3569 *==========================================================================*/
getReprocessType()3570 reprocess_type_t QCamera3PicChannel::getReprocessType()
3571 {
3572 /* a picture channel could either use the postprocessor for reprocess+jpeg
3573 or only for reprocess */
3574 reprocess_type_t expectedReprocess;
3575 if (mPostProcMask == CAM_QCOM_FEATURE_NONE || mInputBufferHint) {
3576 expectedReprocess = REPROCESS_TYPE_JPEG;
3577 } else {
3578 expectedReprocess = REPROCESS_TYPE_NONE;
3579 }
3580 LOGH("expectedReprocess from Pic Channel is %d", expectedReprocess);
3581 return expectedReprocess;
3582 }
3583
3584
3585 /*===========================================================================
3586 * FUNCTION : QCamera3ReprocessChannel
3587 *
3588 * DESCRIPTION: constructor of QCamera3ReprocessChannel
3589 *
3590 * PARAMETERS :
3591 * @cam_handle : camera handle
3592 * @cam_ops : ptr to camera ops table
3593 * @pp_mask : post-proccess feature mask
3594 *
3595 * RETURN : none
3596 *==========================================================================*/
QCamera3ReprocessChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,channel_cb_routine cb_routine,cam_padding_info_t * paddingInfo,uint32_t postprocess_mask,void * userData,void * ch_hdl)3597 QCamera3ReprocessChannel::QCamera3ReprocessChannel(uint32_t cam_handle,
3598 uint32_t channel_handle,
3599 mm_camera_ops_t *cam_ops,
3600 channel_cb_routine cb_routine,
3601 cam_padding_info_t *paddingInfo,
3602 uint32_t postprocess_mask,
3603 void *userData, void *ch_hdl) :
3604 /* In case of framework reprocessing, pproc and jpeg operations could be
3605 * parallelized by allowing 1 extra buffer for reprocessing output:
3606 * ch_hdl->getNumBuffers() + 1 */
3607 QCamera3Channel(cam_handle, channel_handle, cam_ops, cb_routine, paddingInfo,
3608 postprocess_mask, userData,
3609 ((QCamera3ProcessingChannel *)ch_hdl)->getNumBuffers()
3610 + (MAX_REPROCESS_PIPELINE_STAGES - 1)),
3611 inputChHandle(ch_hdl),
3612 mOfflineBuffersIndex(-1),
3613 mFrameLen(0),
3614 mReprocessType(REPROCESS_TYPE_NONE),
3615 m_pSrcChannel(NULL),
3616 m_pMetaChannel(NULL),
3617 mMemory(NULL),
3618 mGrallocMemory(0),
3619 mReprocessPerfMode(false)
3620 {
3621 memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
3622 mOfflineBuffersIndex = mNumBuffers -1;
3623 mOfflineMetaIndex = (int32_t) (2*mNumBuffers -1);
3624 }
3625
3626
3627 /*===========================================================================
3628 * FUNCTION : QCamera3ReprocessChannel
3629 *
3630 * DESCRIPTION: constructor of QCamera3ReprocessChannel
3631 *
3632 * PARAMETERS :
3633 * @cam_handle : camera handle
3634 * @cam_ops : ptr to camera ops table
3635 * @pp_mask : post-proccess feature mask
3636 *
3637 * RETURN : none
3638 *==========================================================================*/
initialize(cam_is_type_t isType)3639 int32_t QCamera3ReprocessChannel::initialize(cam_is_type_t isType)
3640 {
3641 int32_t rc = NO_ERROR;
3642 mm_camera_channel_attr_t attr;
3643
3644 memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
3645 attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS;
3646 attr.max_unmatched_frames = 1;
3647
3648 m_handle = m_camOps->add_channel(m_camHandle,
3649 &attr,
3650 NULL,
3651 this);
3652 if (m_handle == 0) {
3653 LOGE("Add channel failed");
3654 return UNKNOWN_ERROR;
3655 }
3656
3657 mIsType = isType;
3658 return rc;
3659 }
3660
3661 /*===========================================================================
3662 * FUNCTION : registerBuffer
3663 *
3664 * DESCRIPTION: register streaming buffer to the channel object
3665 *
3666 * PARAMETERS :
3667 * @buffer : buffer to be registered
3668 * @isType : the image stabilization type for the buffer
3669 *
3670 * RETURN : int32_t type of status
3671 * NO_ERROR -- success
3672 * none-zero failure code
3673 *==========================================================================*/
registerBuffer(buffer_handle_t * buffer,cam_is_type_t isType)3674 int32_t QCamera3ReprocessChannel::registerBuffer(buffer_handle_t *buffer,
3675 cam_is_type_t isType)
3676 {
3677 ATRACE_CALL();
3678 int rc = 0;
3679 mIsType = isType;
3680 cam_stream_type_t streamType;
3681
3682 if (buffer == NULL) {
3683 LOGE("Error: Cannot register a NULL buffer");
3684 return BAD_VALUE;
3685 }
3686
3687 if ((uint32_t)mGrallocMemory.getCnt() > (mNumBuffers - 1)) {
3688 LOGE("Trying to register more buffers than initially requested");
3689 return BAD_VALUE;
3690 }
3691
3692 if (0 == m_numStreams) {
3693 rc = initialize(mIsType);
3694 if (rc != NO_ERROR) {
3695 LOGE("Couldn't initialize camera stream %d",
3696 rc);
3697 return rc;
3698 }
3699 }
3700
3701 streamType = mStreams[0]->getMyType();
3702 rc = mGrallocMemory.registerBuffer(buffer, streamType);
3703 if (ALREADY_EXISTS == rc) {
3704 return NO_ERROR;
3705 } else if (NO_ERROR != rc) {
3706 LOGE("Buffer %p couldn't be registered %d", buffer, rc);
3707 return rc;
3708 }
3709
3710 return rc;
3711 }
3712
3713 /*===========================================================================
3714 * FUNCTION : QCamera3ReprocessChannel
3715 *
3716 * DESCRIPTION: constructor of QCamera3ReprocessChannel
3717 *
3718 * PARAMETERS :
3719 * @cam_handle : camera handle
3720 * @cam_ops : ptr to camera ops table
3721 * @pp_mask : post-proccess feature mask
3722 *
3723 * RETURN : none
3724 *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)3725 void QCamera3ReprocessChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
3726 QCamera3Stream *stream)
3727 {
3728 //Got the pproc data callback. Now send to jpeg encoding
3729 uint8_t frameIndex;
3730 uint32_t resultFrameNumber;
3731 mm_camera_super_buf_t* frame = NULL;
3732 QCamera3ProcessingChannel *obj = (QCamera3ProcessingChannel *)inputChHandle;
3733 cam_dimension_t dim;
3734 cam_frame_len_offset_t offset;
3735
3736 memset(&dim, 0, sizeof(dim));
3737 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
3738 if(!super_frame) {
3739 LOGE("Invalid Super buffer");
3740 return;
3741 }
3742
3743 if(super_frame->num_bufs != 1) {
3744 LOGE("Multiple streams are not supported");
3745 return;
3746 }
3747 if(super_frame->bufs[0] == NULL ) {
3748 LOGE("Error, Super buffer frame does not contain valid buffer");
3749 return;
3750 }
3751 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
3752
3753
3754 if (mReprocessType == REPROCESS_TYPE_JPEG) {
3755 resultFrameNumber = mMemory->getFrameNumber(frameIndex);
3756 frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
3757 if (frame == NULL) {
3758 LOGE("Error allocating memory to save received_frame structure.");
3759 if(stream) {
3760 stream->bufDone(frameIndex);
3761 }
3762 return;
3763 }
3764 LOGI("bufIndex: %u recvd from post proc",
3765 (uint32_t)frameIndex);
3766 *frame = *super_frame;
3767
3768 stream->getFrameDimension(dim);
3769 stream->getFrameOffset(offset);
3770 dumpYUV(frame->bufs[0], dim, offset, QCAMERA_DUMP_FRM_SNAPSHOT);
3771 /* Since reprocessing is done, send the callback to release the input buffer */
3772 if (mChannelCB) {
3773 mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
3774 }
3775 obj->m_postprocessor.processPPData(frame);
3776 } else {
3777 buffer_handle_t *resultBuffer;
3778 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
3779 resultBuffer = (buffer_handle_t *)mGrallocMemory.getBufferHandle(frameIndex);
3780 resultFrameNumber = mGrallocMemory.getFrameNumber(frameIndex);
3781 int32_t rc = stream->bufRelease(frameIndex);
3782 if (NO_ERROR != rc) {
3783 LOGE("Error %d releasing stream buffer %d",
3784 rc, frameIndex);
3785 }
3786 rc = mGrallocMemory.unregisterBuffer(frameIndex);
3787 if (NO_ERROR != rc) {
3788 LOGE("Error %d unregistering stream buffer %d",
3789 rc, frameIndex);
3790 }
3791 obj->reprocessCbRoutine(resultBuffer, resultFrameNumber);
3792
3793 obj->m_postprocessor.releaseOfflineBuffers(false);
3794 qcamera_hal3_pp_data_t *pp_job = obj->m_postprocessor.dequeuePPJob(resultFrameNumber);
3795 if (pp_job != NULL) {
3796 obj->m_postprocessor.releasePPJobData(pp_job);
3797 }
3798 free(pp_job);
3799 resetToCamPerfNormal(resultFrameNumber);
3800 }
3801 free(super_frame);
3802 return;
3803 }
3804
3805 /*===========================================================================
3806 * FUNCTION : resetToCamPerfNormal
3807 *
3808 * DESCRIPTION: Set the perf mode to normal if all the priority frames
3809 * have been reprocessed
3810 *
3811 * PARAMETERS :
3812 * @frameNumber: Frame number of the reprocess completed frame
3813 *
3814 * RETURN : QCamera3StreamMem *
3815 *==========================================================================*/
resetToCamPerfNormal(uint32_t frameNumber)3816 int32_t QCamera3ReprocessChannel::resetToCamPerfNormal(uint32_t frameNumber)
3817 {
3818 int32_t rc = NO_ERROR;
3819 bool resetToPerfNormal = false;
3820 {
3821 Mutex::Autolock lock(mPriorityFramesLock);
3822 /* remove the priority frame number from the list */
3823 for (size_t i = 0; i < mPriorityFrames.size(); i++) {
3824 if (mPriorityFrames[i] == frameNumber) {
3825 mPriorityFrames.removeAt(i);
3826 }
3827 }
3828 /* reset the perf mode if pending priority frame list is empty */
3829 if (mReprocessPerfMode && mPriorityFrames.empty()) {
3830 resetToPerfNormal = true;
3831 }
3832 }
3833 if (resetToPerfNormal) {
3834 QCamera3Stream *pStream = mStreams[0];
3835 cam_stream_parm_buffer_t param;
3836 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t));
3837
3838 param.type = CAM_STREAM_PARAM_TYPE_REQUEST_OPS_MODE;
3839 param.perf_mode = CAM_PERF_NORMAL;
3840 rc = pStream->setParameter(param);
3841 {
3842 Mutex::Autolock lock(mPriorityFramesLock);
3843 mReprocessPerfMode = false;
3844 }
3845 }
3846 return rc;
3847 }
3848
3849 /*===========================================================================
3850 * FUNCTION : getStreamBufs
3851 *
3852 * DESCRIPTION: register the buffers of the reprocess channel
3853 *
3854 * PARAMETERS : none
3855 *
3856 * RETURN : QCamera3StreamMem *
3857 *==========================================================================*/
getStreamBufs(uint32_t len)3858 QCamera3StreamMem* QCamera3ReprocessChannel::getStreamBufs(uint32_t len)
3859 {
3860 if (mReprocessType == REPROCESS_TYPE_JPEG) {
3861 mMemory = new QCamera3StreamMem(mNumBuffers, false);
3862 if (!mMemory) {
3863 LOGE("unable to create reproc memory");
3864 return NULL;
3865 }
3866 mFrameLen = len;
3867 return mMemory;
3868 }
3869 return &mGrallocMemory;
3870 }
3871
3872 /*===========================================================================
3873 * FUNCTION : putStreamBufs
3874 *
3875 * DESCRIPTION: release the reprocess channel buffers
3876 *
3877 * PARAMETERS : none
3878 *
3879 * RETURN :
3880 *==========================================================================*/
putStreamBufs()3881 void QCamera3ReprocessChannel::putStreamBufs()
3882 {
3883 if (mReprocessType == REPROCESS_TYPE_JPEG) {
3884 mMemory->deallocate();
3885 delete mMemory;
3886 mMemory = NULL;
3887 mFreeBufferList.clear();
3888 } else {
3889 mGrallocMemory.unregisterBuffers();
3890 }
3891 }
3892
3893 /*===========================================================================
3894 * FUNCTION : ~QCamera3ReprocessChannel
3895 *
3896 * DESCRIPTION: destructor of QCamera3ReprocessChannel
3897 *
3898 * PARAMETERS : none
3899 *
3900 * RETURN : none
3901 *==========================================================================*/
~QCamera3ReprocessChannel()3902 QCamera3ReprocessChannel::~QCamera3ReprocessChannel()
3903 {
3904 destroy();
3905
3906 if (m_handle) {
3907 m_camOps->delete_channel(m_camHandle, m_handle);
3908 LOGD("deleting channel %d", m_handle);
3909 m_handle = 0;
3910 }
3911 }
3912
3913 /*===========================================================================
3914 * FUNCTION : start
3915 *
3916 * DESCRIPTION: start reprocess channel.
3917 *
3918 * PARAMETERS :
3919 *
3920 * RETURN : int32_t type of status
3921 * NO_ERROR -- success
3922 * none-zero failure code
3923 *==========================================================================*/
start()3924 int32_t QCamera3ReprocessChannel::start()
3925 {
3926 ATRACE_CALL();
3927 int32_t rc = NO_ERROR;
3928
3929 rc = QCamera3Channel::start();
3930
3931 if (rc == NO_ERROR) {
3932 rc = m_camOps->start_channel(m_camHandle, m_handle);
3933
3934 // Check failure
3935 if (rc != NO_ERROR) {
3936 LOGE("start_channel failed %d", rc);
3937 QCamera3Channel::stop();
3938 }
3939 }
3940 return rc;
3941 }
3942
3943 /*===========================================================================
3944 * FUNCTION : stop
3945 *
3946 * DESCRIPTION: stop reprocess channel.
3947 *
3948 * PARAMETERS : none
3949 *
3950 * RETURN : int32_t type of status
3951 * NO_ERROR -- success
3952 * none-zero failure code
3953 *==========================================================================*/
stop()3954 int32_t QCamera3ReprocessChannel::stop()
3955 {
3956 ATRACE_CALL();
3957 int32_t rc = NO_ERROR;
3958
3959 rc = QCamera3Channel::stop();
3960 unmapOfflineBuffers(true);
3961
3962 rc |= m_camOps->stop_channel(m_camHandle, m_handle);
3963
3964 return rc;
3965 }
3966
3967 /*===========================================================================
3968 * FUNCTION : getStreamBySrcHandle
3969 *
3970 * DESCRIPTION: find reprocess stream by its source stream handle
3971 *
3972 * PARAMETERS :
3973 * @srcHandle : source stream handle
3974 *
3975 * RETURN : ptr to reprocess stream if found. NULL if not found
3976 *==========================================================================*/
getStreamBySrcHandle(uint32_t srcHandle)3977 QCamera3Stream * QCamera3ReprocessChannel::getStreamBySrcHandle(uint32_t srcHandle)
3978 {
3979 QCamera3Stream *pStream = NULL;
3980
3981 for (uint32_t i = 0; i < m_numStreams; i++) {
3982 if (mSrcStreamHandles[i] == srcHandle) {
3983 pStream = mStreams[i];
3984 break;
3985 }
3986 }
3987 return pStream;
3988 }
3989
3990 /*===========================================================================
3991 * FUNCTION : getSrcStreamBySrcHandle
3992 *
3993 * DESCRIPTION: find source stream by source stream handle
3994 *
3995 * PARAMETERS :
3996 * @srcHandle : source stream handle
3997 *
3998 * RETURN : ptr to reprocess stream if found. NULL if not found
3999 *==========================================================================*/
getSrcStreamBySrcHandle(uint32_t srcHandle)4000 QCamera3Stream * QCamera3ReprocessChannel::getSrcStreamBySrcHandle(uint32_t srcHandle)
4001 {
4002 QCamera3Stream *pStream = NULL;
4003
4004 if (NULL == m_pSrcChannel) {
4005 return NULL;
4006 }
4007
4008 for (uint32_t i = 0; i < m_numStreams; i++) {
4009 if (mSrcStreamHandles[i] == srcHandle) {
4010 pStream = m_pSrcChannel->getStreamByIndex(i);
4011 break;
4012 }
4013 }
4014 return pStream;
4015 }
4016
4017 /*===========================================================================
4018 * FUNCTION : unmapOfflineBuffers
4019 *
4020 * DESCRIPTION: Unmaps offline buffers
4021 *
4022 * PARAMETERS : none
4023 *
4024 * RETURN : int32_t type of status
4025 * NO_ERROR -- success
4026 * none-zero failure code
4027 *==========================================================================*/
unmapOfflineBuffers(bool all)4028 int32_t QCamera3ReprocessChannel::unmapOfflineBuffers(bool all)
4029 {
4030 int rc = NO_ERROR;
4031 if (!mOfflineBuffers.empty()) {
4032 QCamera3Stream *stream = NULL;
4033 List<OfflineBuffer>::iterator it = mOfflineBuffers.begin();
4034 for (; it != mOfflineBuffers.end(); it++) {
4035 stream = (*it).stream;
4036 if (NULL != stream) {
4037 rc = stream->unmapBuf((*it).type,
4038 (*it).index,
4039 -1);
4040 if (NO_ERROR != rc) {
4041 LOGE("Error during offline buffer unmap %d",
4042 rc);
4043 }
4044 LOGD("Unmapped buffer with index %d", (*it).index);
4045 }
4046 if (!all) {
4047 mOfflineBuffers.erase(it);
4048 break;
4049 }
4050 }
4051 if (all) {
4052 mOfflineBuffers.clear();
4053 }
4054 }
4055
4056 if (!mOfflineMetaBuffers.empty()) {
4057 QCamera3Stream *stream = NULL;
4058 List<OfflineBuffer>::iterator it = mOfflineMetaBuffers.begin();
4059 for (; it != mOfflineMetaBuffers.end(); it++) {
4060 stream = (*it).stream;
4061 if (NULL != stream) {
4062 rc = stream->unmapBuf((*it).type,
4063 (*it).index,
4064 -1);
4065 if (NO_ERROR != rc) {
4066 LOGE("Error during offline buffer unmap %d",
4067 rc);
4068 }
4069 LOGD("Unmapped meta buffer with index %d", (*it).index);
4070 }
4071 if (!all) {
4072 mOfflineMetaBuffers.erase(it);
4073 break;
4074 }
4075 }
4076 if (all) {
4077 mOfflineMetaBuffers.clear();
4078 }
4079 }
4080 return rc;
4081 }
4082
4083 /*===========================================================================
4084 * FUNCTION : bufDone
4085 *
4086 * DESCRIPTION: Return reprocess stream buffer to free buffer list.
4087 * Note that this function doesn't queue buffer back to kernel.
4088 * It's up to doReprocessOffline to do that instead.
4089 * PARAMETERS :
4090 * @recvd_frame : stream buf frame to be returned
4091 *
4092 * RETURN : int32_t type of status
4093 * NO_ERROR -- success
4094 * none-zero failure code
4095 *==========================================================================*/
bufDone(mm_camera_super_buf_t * recvd_frame)4096 int32_t QCamera3ReprocessChannel::bufDone(mm_camera_super_buf_t *recvd_frame)
4097 {
4098 int rc = NO_ERROR;
4099 if (recvd_frame && recvd_frame->num_bufs == 1) {
4100 Mutex::Autolock lock(mFreeBuffersLock);
4101 uint32_t buf_idx = recvd_frame->bufs[0]->buf_idx;
4102 mFreeBufferList.push_back(buf_idx);
4103
4104 } else {
4105 LOGE("Fatal. Not supposed to be here");
4106 rc = BAD_VALUE;
4107 }
4108
4109 return rc;
4110 }
4111
4112 /*===========================================================================
4113 * FUNCTION : overrideMetadata
4114 *
4115 * DESCRIPTION: Override metadata entry such as rotation, crop, and CDS info.
4116 *
4117 * PARAMETERS :
4118 * @frame : input frame from source stream
4119 * meta_buffer: metadata buffer
4120 * @metadata : corresponding metadata
4121 * @fwk_frame :
4122 *
4123 * RETURN : int32_t type of status
4124 * NO_ERROR -- success
4125 * none-zero failure code
4126 *==========================================================================*/
overrideMetadata(qcamera_hal3_pp_buffer_t * pp_buffer,mm_camera_buf_def_t * meta_buffer,jpeg_settings_t * jpeg_settings,qcamera_fwk_input_pp_data_t & fwk_frame)4127 int32_t QCamera3ReprocessChannel::overrideMetadata(qcamera_hal3_pp_buffer_t *pp_buffer,
4128 mm_camera_buf_def_t *meta_buffer, jpeg_settings_t *jpeg_settings,
4129 qcamera_fwk_input_pp_data_t &fwk_frame)
4130 {
4131 int32_t rc = NO_ERROR;
4132 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
4133 if ((NULL == meta_buffer) || (NULL == pp_buffer) || (NULL == pp_buffer->input) ||
4134 (NULL == hal_obj)) {
4135 return BAD_VALUE;
4136 }
4137
4138 metadata_buffer_t *meta = (metadata_buffer_t *)meta_buffer->buffer;
4139 mm_camera_super_buf_t *frame = pp_buffer->input;
4140 if (NULL == meta) {
4141 return BAD_VALUE;
4142 }
4143
4144 for (uint32_t i = 0; i < frame->num_bufs; i++) {
4145 QCamera3Stream *pStream = getStreamBySrcHandle(frame->bufs[i]->stream_id);
4146 QCamera3Stream *pSrcStream = getSrcStreamBySrcHandle(frame->bufs[i]->stream_id);
4147
4148 if (pStream != NULL && pSrcStream != NULL) {
4149 if (jpeg_settings) {
4150 // Find rotation info for reprocess stream
4151 cam_rotation_info_t rotation_info;
4152 memset(&rotation_info, 0, sizeof(rotation_info));
4153 if (jpeg_settings->jpeg_orientation == 0) {
4154 rotation_info.rotation = ROTATE_0;
4155 } else if (jpeg_settings->jpeg_orientation == 90) {
4156 rotation_info.rotation = ROTATE_90;
4157 } else if (jpeg_settings->jpeg_orientation == 180) {
4158 rotation_info.rotation = ROTATE_180;
4159 } else if (jpeg_settings->jpeg_orientation == 270) {
4160 rotation_info.rotation = ROTATE_270;
4161 }
4162 rotation_info.streamId = mStreams[0]->getMyServerID();
4163 ADD_SET_PARAM_ENTRY_TO_BATCH(meta, CAM_INTF_PARM_ROTATION, rotation_info);
4164 }
4165
4166 // Find and insert crop info for reprocess stream
4167 IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) {
4168 if (MAX_NUM_STREAMS > crop_data->num_of_streams) {
4169 for (int j = 0; j < crop_data->num_of_streams; j++) {
4170 if (crop_data->crop_info[j].stream_id ==
4171 pSrcStream->getMyServerID()) {
4172
4173 // Store crop/roi information for offline reprocess
4174 // in the reprocess stream slot
4175 crop_data->crop_info[crop_data->num_of_streams].crop =
4176 crop_data->crop_info[j].crop;
4177 crop_data->crop_info[crop_data->num_of_streams].roi_map =
4178 crop_data->crop_info[j].roi_map;
4179 crop_data->crop_info[crop_data->num_of_streams].stream_id =
4180 mStreams[0]->getMyServerID();
4181 crop_data->num_of_streams++;
4182
4183 LOGD("Reprocess stream server id: %d",
4184 mStreams[0]->getMyServerID());
4185 LOGD("Found offline reprocess crop %dx%d %dx%d",
4186 crop_data->crop_info[j].crop.left,
4187 crop_data->crop_info[j].crop.top,
4188 crop_data->crop_info[j].crop.width,
4189 crop_data->crop_info[j].crop.height);
4190 LOGD("Found offline reprocess roimap %dx%d %dx%d",
4191 crop_data->crop_info[j].roi_map.left,
4192 crop_data->crop_info[j].roi_map.top,
4193 crop_data->crop_info[j].roi_map.width,
4194 crop_data->crop_info[j].roi_map.height);
4195
4196 break;
4197 }
4198 }
4199 } else {
4200 LOGE("No space to add reprocess stream crop/roi information");
4201 }
4202 }
4203
4204 IF_META_AVAILABLE(cam_cds_data_t, cdsInfo, CAM_INTF_META_CDS_DATA, meta) {
4205 uint8_t cnt = cdsInfo->num_of_streams;
4206 if (cnt <= MAX_NUM_STREAMS) {
4207 cam_stream_cds_info_t repro_cds_info;
4208 memset(&repro_cds_info, 0, sizeof(repro_cds_info));
4209 repro_cds_info.stream_id = mStreams[0]->getMyServerID();
4210 for (size_t i = 0; i < cnt; i++) {
4211 if (cdsInfo->cds_info[i].stream_id ==
4212 pSrcStream->getMyServerID()) {
4213 repro_cds_info.cds_enable =
4214 cdsInfo->cds_info[i].cds_enable;
4215 break;
4216 }
4217 }
4218 cdsInfo->num_of_streams = 1;
4219 cdsInfo->cds_info[0] = repro_cds_info;
4220 } else {
4221 LOGE("No space to add reprocess stream cds information");
4222 }
4223 }
4224
4225 fwk_frame.input_buffer = *frame->bufs[i];
4226 fwk_frame.metadata_buffer = *meta_buffer;
4227 fwk_frame.output_buffer = pp_buffer->output;
4228 break;
4229 } else {
4230 LOGE("Source/Re-process streams are invalid");
4231 rc |= BAD_VALUE;
4232 }
4233 }
4234
4235 return rc;
4236 }
4237
4238 /*===========================================================================
4239 * FUNCTION : overrideFwkMetadata
4240 *
4241 * DESCRIPTION: Override frameworks metadata such as crop, and CDS data.
4242 *
4243 * PARAMETERS :
4244 * @frame : input frame for reprocessing
4245 *
4246 * RETURN : int32_t type of status
4247 * NO_ERROR -- success
4248 * none-zero failure code
4249 *==========================================================================*/
overrideFwkMetadata(qcamera_fwk_input_pp_data_t * frame)4250 int32_t QCamera3ReprocessChannel::overrideFwkMetadata(
4251 qcamera_fwk_input_pp_data_t *frame)
4252 {
4253 if (NULL == frame) {
4254 LOGE("Incorrect input frame");
4255 return BAD_VALUE;
4256 }
4257
4258 if (NULL == frame->metadata_buffer.buffer) {
4259 LOGE("No metadata available");
4260 return BAD_VALUE;
4261 }
4262
4263 // Find and insert crop info for reprocess stream
4264 metadata_buffer_t *meta = (metadata_buffer_t *) frame->metadata_buffer.buffer;
4265 IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) {
4266 if (1 == crop_data->num_of_streams) {
4267 // Store crop/roi information for offline reprocess
4268 // in the reprocess stream slot
4269 crop_data->crop_info[crop_data->num_of_streams].crop =
4270 crop_data->crop_info[0].crop;
4271 crop_data->crop_info[crop_data->num_of_streams].roi_map =
4272 crop_data->crop_info[0].roi_map;
4273 crop_data->crop_info[crop_data->num_of_streams].stream_id =
4274 mStreams[0]->getMyServerID();
4275 crop_data->num_of_streams++;
4276
4277 LOGD("Reprocess stream server id: %d",
4278 mStreams[0]->getMyServerID());
4279 LOGD("Found offline reprocess crop %dx%d %dx%d",
4280 crop_data->crop_info[0].crop.left,
4281 crop_data->crop_info[0].crop.top,
4282 crop_data->crop_info[0].crop.width,
4283 crop_data->crop_info[0].crop.height);
4284 LOGD("Found offline reprocess roi map %dx%d %dx%d",
4285 crop_data->crop_info[0].roi_map.left,
4286 crop_data->crop_info[0].roi_map.top,
4287 crop_data->crop_info[0].roi_map.width,
4288 crop_data->crop_info[0].roi_map.height);
4289 } else {
4290 LOGE("Incorrect number of offline crop data entries %d",
4291 crop_data->num_of_streams);
4292 return BAD_VALUE;
4293 }
4294 } else {
4295 LOGW("Crop data not present");
4296 }
4297
4298 IF_META_AVAILABLE(cam_cds_data_t, cdsInfo, CAM_INTF_META_CDS_DATA, meta) {
4299 if (1 == cdsInfo->num_of_streams) {
4300 cdsInfo->cds_info[0].stream_id = mStreams[0]->getMyServerID();
4301 } else {
4302 LOGE("Incorrect number of offline cds info entries %d",
4303 cdsInfo->num_of_streams);
4304 return BAD_VALUE;
4305 }
4306 }
4307
4308 return NO_ERROR;
4309 }
4310
4311 /*===========================================================================
4312 * FUNCTION : doReprocessOffline
4313 *
4314 * DESCRIPTION: request to do a reprocess on the frame
4315 *
4316 * PARAMETERS :
4317 * @frame : input frame for reprocessing
4318 * @isPriorityFrame: Hint that this frame is of priority, equivalent to
4319 * real time, even though it is processed in offline mechanism
4320 *
4321 * RETURN : int32_t type of status
4322 * NO_ERROR -- success
4323 * none-zero failure code
4324 *==========================================================================*/
doReprocessOffline(qcamera_fwk_input_pp_data_t * frame,bool isPriorityFrame)4325 int32_t QCamera3ReprocessChannel::doReprocessOffline(
4326 qcamera_fwk_input_pp_data_t *frame, bool isPriorityFrame)
4327 {
4328 int32_t rc = 0;
4329 int index;
4330 OfflineBuffer mappedBuffer;
4331
4332 if (m_numStreams < 1) {
4333 LOGE("No reprocess stream is created");
4334 return -1;
4335 }
4336
4337 if (NULL == frame) {
4338 LOGE("Incorrect input frame");
4339 return BAD_VALUE;
4340 }
4341
4342 if (NULL == frame->metadata_buffer.buffer) {
4343 LOGE("No metadata available");
4344 return BAD_VALUE;
4345 }
4346
4347 if (NULL == frame->input_buffer.buffer) {
4348 LOGE("No input buffer available");
4349 return BAD_VALUE;
4350 }
4351
4352 if ((0 == m_numStreams) || (NULL == mStreams[0])) {
4353 LOGE("Reprocess stream not initialized!");
4354 return NO_INIT;
4355 }
4356
4357 QCamera3Stream *pStream = mStreams[0];
4358
4359 //qbuf the output buffer if it was allocated by the framework
4360 if (mReprocessType != REPROCESS_TYPE_JPEG && frame->output_buffer != NULL) {
4361 if(!m_bIsActive) {
4362 rc = registerBuffer(frame->output_buffer, mIsType);
4363 if (NO_ERROR != rc) {
4364 LOGE("On-the-fly buffer registration failed %d",
4365 rc);
4366 return rc;
4367 }
4368
4369 rc = start();
4370 if (NO_ERROR != rc) {
4371 return rc;
4372 }
4373 }
4374 index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer);
4375 if(index < 0) {
4376 rc = registerBuffer(frame->output_buffer, mIsType);
4377 if (NO_ERROR != rc) {
4378 LOGE("On-the-fly buffer registration failed %d",
4379 rc);
4380 return rc;
4381 }
4382
4383 index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer);
4384 if (index < 0) {
4385 LOGE("Could not find object among registered buffers");
4386 return DEAD_OBJECT;
4387 }
4388 }
4389 rc = pStream->bufDone(index);
4390 if(rc != NO_ERROR) {
4391 LOGE("Failed to Q new buffer to stream");
4392 return rc;
4393 }
4394 rc = mGrallocMemory.markFrameNumber(index, frame->frameNumber);
4395
4396 } else if (mReprocessType == REPROCESS_TYPE_JPEG) {
4397 Mutex::Autolock lock(mFreeBuffersLock);
4398 uint32_t bufIdx;
4399 if (mFreeBufferList.empty()) {
4400 rc = mMemory->allocateOne(mFrameLen);
4401 if (rc < 0) {
4402 LOGE("Failed allocating heap buffer. Fatal");
4403 return BAD_VALUE;
4404 } else {
4405 bufIdx = (uint32_t)rc;
4406 }
4407 } else {
4408 bufIdx = *(mFreeBufferList.begin());
4409 mFreeBufferList.erase(mFreeBufferList.begin());
4410 }
4411
4412 mMemory->markFrameNumber(bufIdx, frame->frameNumber);
4413 rc = pStream->bufDone(bufIdx);
4414 if (rc != NO_ERROR) {
4415 LOGE("Failed to queue new buffer to stream");
4416 return rc;
4417 }
4418 }
4419
4420 int32_t max_idx = (int32_t) (mNumBuffers - 1);
4421 //loop back the indices if max burst count reached
4422 if (mOfflineBuffersIndex == max_idx) {
4423 mOfflineBuffersIndex = -1;
4424 }
4425 uint32_t buf_idx = (uint32_t)(mOfflineBuffersIndex + 1);
4426 rc = pStream->mapBuf(
4427 CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4428 buf_idx, -1,
4429 frame->input_buffer.fd, frame->input_buffer.frame_len);
4430 if (NO_ERROR == rc) {
4431 mappedBuffer.index = buf_idx;
4432 mappedBuffer.stream = pStream;
4433 mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF;
4434 mOfflineBuffers.push_back(mappedBuffer);
4435 mOfflineBuffersIndex = (int32_t)buf_idx;
4436 LOGD("Mapped buffer with index %d", mOfflineBuffersIndex);
4437 }
4438
4439 max_idx = (int32_t) ((mNumBuffers * 2) - 1);
4440 //loop back the indices if max burst count reached
4441 if (mOfflineMetaIndex == max_idx) {
4442 mOfflineMetaIndex = (int32_t) (mNumBuffers - 1);
4443 }
4444 uint32_t meta_buf_idx = (uint32_t)(mOfflineMetaIndex + 1);
4445 rc |= pStream->mapBuf(
4446 CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF,
4447 meta_buf_idx, -1,
4448 frame->metadata_buffer.fd, frame->metadata_buffer.frame_len);
4449 if (NO_ERROR == rc) {
4450 mappedBuffer.index = meta_buf_idx;
4451 mappedBuffer.stream = pStream;
4452 mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF;
4453 mOfflineMetaBuffers.push_back(mappedBuffer);
4454 mOfflineMetaIndex = (int32_t)meta_buf_idx;
4455 LOGD("Mapped meta buffer with index %d", mOfflineMetaIndex);
4456 }
4457
4458 if (rc == NO_ERROR) {
4459 cam_stream_parm_buffer_t param;
4460 uint32_t numPendingPriorityFrames = 0;
4461
4462 if(isPriorityFrame && (mReprocessType != REPROCESS_TYPE_JPEG)) {
4463 Mutex::Autolock lock(mPriorityFramesLock);
4464 /* read the length before pushing the frame number to check if
4465 * vector is empty */
4466 numPendingPriorityFrames = mPriorityFrames.size();
4467 mPriorityFrames.push(frame->frameNumber);
4468 }
4469
4470 if(isPriorityFrame && !numPendingPriorityFrames &&
4471 (mReprocessType != REPROCESS_TYPE_JPEG)) {
4472 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t));
4473 param.type = CAM_STREAM_PARAM_TYPE_REQUEST_OPS_MODE;
4474 param.perf_mode = CAM_PERF_HIGH_PERFORMANCE;
4475 rc = pStream->setParameter(param);
4476 if (rc != NO_ERROR) {
4477 ALOGE("%s: setParameter for CAM_PERF_HIGH_PERFORMANCE failed",
4478 __func__);
4479 }
4480 {
4481 Mutex::Autolock lock(mPriorityFramesLock);
4482 mReprocessPerfMode = true;
4483 }
4484 }
4485
4486 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t));
4487 param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
4488 param.reprocess.buf_index = buf_idx;
4489 param.reprocess.frame_idx = frame->input_buffer.frame_idx;
4490 param.reprocess.meta_present = 1;
4491 param.reprocess.meta_buf_index = meta_buf_idx;
4492
4493 LOGI("Offline reprocessing id = %d buf Id = %d meta index = %d",
4494 param.reprocess.frame_idx, param.reprocess.buf_index,
4495 param.reprocess.meta_buf_index);
4496 rc = pStream->setParameter(param);
4497 if (rc != NO_ERROR) {
4498 LOGE("stream setParameter for reprocess failed");
4499 resetToCamPerfNormal(frame->frameNumber);
4500 }
4501 } else {
4502 LOGE("Input buffer memory map failed: %d", rc);
4503 }
4504
4505 return rc;
4506 }
4507
4508 /*===========================================================================
4509 * FUNCTION : doReprocess
4510 *
4511 * DESCRIPTION: request to do a reprocess on the frame
4512 *
4513 * PARAMETERS :
4514 * @buf_fd : fd to the input buffer that needs reprocess
4515 * @buf_lenght : length of the input buffer
4516 * @ret_val : result of reprocess.
4517 * Example: Could be faceID in case of register face image.
4518 * @meta_frame : metadata frame.
4519 *
4520 * RETURN : int32_t type of status
4521 * NO_ERROR -- success
4522 * none-zero failure code
4523 *==========================================================================*/
doReprocess(int buf_fd,size_t buf_length,int32_t & ret_val,mm_camera_super_buf_t * meta_frame)4524 int32_t QCamera3ReprocessChannel::doReprocess(int buf_fd, size_t buf_length,
4525 int32_t &ret_val, mm_camera_super_buf_t *meta_frame)
4526 {
4527 int32_t rc = 0;
4528 if (m_numStreams < 1) {
4529 LOGE("No reprocess stream is created");
4530 return -1;
4531 }
4532 if (meta_frame == NULL) {
4533 LOGE("Did not get corresponding metadata in time");
4534 return -1;
4535 }
4536
4537 uint8_t buf_idx = 0;
4538 for (uint32_t i = 0; i < m_numStreams; i++) {
4539 rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4540 buf_idx, -1,
4541 buf_fd, buf_length);
4542
4543 if (rc == NO_ERROR) {
4544 cam_stream_parm_buffer_t param;
4545 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t));
4546 param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
4547 param.reprocess.buf_index = buf_idx;
4548 param.reprocess.meta_present = 1;
4549 param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID();
4550 param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx;
4551
4552 LOGI("Online reprocessing id = %d buf Id = %d meta index = %d",
4553 param.reprocess.frame_idx, param.reprocess.buf_index,
4554 param.reprocess.meta_buf_index);
4555 rc = mStreams[i]->setParameter(param);
4556 if (rc == NO_ERROR) {
4557 ret_val = param.reprocess.ret_val;
4558 }
4559 mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4560 buf_idx, -1);
4561 }
4562 }
4563 return rc;
4564 }
4565
4566 /*===========================================================================
4567 * FUNCTION : addReprocStreamsFromSource
4568 *
4569 * DESCRIPTION: add reprocess streams from input source channel
4570 *
4571 * PARAMETERS :
4572 * @config : pp feature configuration
4573 * @src_config : source reprocess configuration
4574 * @isType : type of image stabilization required on this stream
4575 * @pMetaChannel : ptr to metadata channel to get corresp. metadata
4576 *
4577 *
4578 * RETURN : int32_t type of status
4579 * NO_ERROR -- success
4580 * none-zero failure code
4581 *==========================================================================*/
addReprocStreamsFromSource(cam_pp_feature_config_t & pp_config,const reprocess_config_t & src_config,cam_is_type_t is_type,QCamera3Channel * pMetaChannel)4582 int32_t QCamera3ReprocessChannel::addReprocStreamsFromSource(cam_pp_feature_config_t &pp_config,
4583 const reprocess_config_t &src_config , cam_is_type_t is_type,
4584 QCamera3Channel *pMetaChannel)
4585 {
4586 int32_t rc = 0;
4587 cam_stream_reproc_config_t reprocess_config;
4588 cam_stream_type_t streamType;
4589
4590 cam_dimension_t streamDim = src_config.output_stream_dim;
4591
4592 if (NULL != src_config.src_channel) {
4593 QCamera3Stream *pSrcStream = src_config.src_channel->getStreamByIndex(0);
4594 if (pSrcStream == NULL) {
4595 LOGE("source channel doesn't have a stream");
4596 return BAD_VALUE;
4597 }
4598 mSrcStreamHandles[m_numStreams] = pSrcStream->getMyHandle();
4599 }
4600
4601 streamType = CAM_STREAM_TYPE_OFFLINE_PROC;
4602 reprocess_config.pp_type = CAM_OFFLINE_REPROCESS_TYPE;
4603
4604 reprocess_config.offline.input_fmt = src_config.stream_format;
4605 reprocess_config.offline.input_dim = src_config.input_stream_dim;
4606 reprocess_config.offline.input_buf_planes.plane_info =
4607 src_config.input_stream_plane_info.plane_info;
4608 reprocess_config.offline.num_of_bufs = (uint8_t)mNumBuffers;
4609 reprocess_config.offline.input_type = src_config.stream_type;
4610
4611 reprocess_config.pp_feature_config = pp_config;
4612 QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
4613 m_handle,
4614 m_camOps,
4615 &mPaddingInfo,
4616 (QCamera3Channel*)this);
4617 if (pStream == NULL) {
4618 LOGE("No mem for Stream");
4619 return NO_MEMORY;
4620 }
4621
4622 rc = pStream->init(streamType, src_config.stream_format,
4623 streamDim, ROTATE_0, &reprocess_config,
4624 (uint8_t)mNumBuffers,
4625 reprocess_config.pp_feature_config.feature_mask,
4626 is_type,
4627 0,/* batchSize */
4628 QCamera3Channel::streamCbRoutine, this);
4629
4630 if (rc == 0) {
4631 mStreams[m_numStreams] = pStream;
4632 m_numStreams++;
4633 } else {
4634 LOGE("failed to create reprocess stream");
4635 delete pStream;
4636 }
4637
4638 if (rc == NO_ERROR) {
4639 m_pSrcChannel = src_config.src_channel;
4640 m_pMetaChannel = pMetaChannel;
4641 mReprocessType = src_config.reprocess_type;
4642 LOGD("mReprocessType is %d", mReprocessType);
4643 }
4644 mm_camera_req_buf_t buf;
4645 memset(&buf, 0x0, sizeof(buf));
4646 buf.type = MM_CAMERA_REQ_SUPER_BUF;
4647 buf.num_buf_requested = 1;
4648 if(m_camOps->request_super_buf(m_camHandle,m_handle, &buf) < 0) {
4649 LOGE("Request for super buffer failed");
4650 }
4651 return rc;
4652 }
4653
4654 /* QCamera3SupportChannel methods */
4655
4656 cam_dimension_t QCamera3SupportChannel::kDim = {640, 480};
4657
QCamera3SupportChannel(uint32_t cam_handle,uint32_t channel_handle,mm_camera_ops_t * cam_ops,cam_padding_info_t * paddingInfo,uint32_t postprocess_mask,cam_stream_type_t streamType,cam_dimension_t * dim,cam_format_t streamFormat,uint8_t hw_analysis_supported,void * userData,uint32_t numBuffers)4658 QCamera3SupportChannel::QCamera3SupportChannel(uint32_t cam_handle,
4659 uint32_t channel_handle,
4660 mm_camera_ops_t *cam_ops,
4661 cam_padding_info_t *paddingInfo,
4662 uint32_t postprocess_mask,
4663 cam_stream_type_t streamType,
4664 cam_dimension_t *dim,
4665 cam_format_t streamFormat,
4666 uint8_t hw_analysis_supported,
4667 void *userData, uint32_t numBuffers) :
4668 QCamera3Channel(cam_handle, channel_handle, cam_ops,
4669 NULL, paddingInfo, postprocess_mask,
4670 userData, numBuffers),
4671 mMemory(NULL)
4672 {
4673 memcpy(&mDim, dim, sizeof(cam_dimension_t));
4674 mStreamType = streamType;
4675 mStreamFormat = streamFormat;
4676 // Make Analysis same as Preview format
4677 if (!hw_analysis_supported && mStreamType == CAM_STREAM_TYPE_ANALYSIS) {
4678 mStreamFormat = getStreamDefaultFormat(CAM_STREAM_TYPE_PREVIEW);
4679 }
4680 }
4681
~QCamera3SupportChannel()4682 QCamera3SupportChannel::~QCamera3SupportChannel()
4683 {
4684 destroy();
4685
4686 if (mMemory) {
4687 mMemory->deallocate();
4688 delete mMemory;
4689 mMemory = NULL;
4690 }
4691 }
4692
initialize(cam_is_type_t isType)4693 int32_t QCamera3SupportChannel::initialize(cam_is_type_t isType)
4694 {
4695 int32_t rc;
4696
4697 if (mMemory || m_numStreams > 0) {
4698 LOGE("metadata channel already initialized");
4699 return -EINVAL;
4700 }
4701
4702 mIsType = isType;
4703 rc = QCamera3Channel::addStream(mStreamType,
4704 mStreamFormat, mDim, ROTATE_0, MIN_STREAMING_BUFFER_NUM,
4705 mPostProcMask, mIsType);
4706 if (rc < 0) {
4707 LOGE("addStream failed");
4708 }
4709 return rc;
4710 }
4711
request(buffer_handle_t *,uint32_t)4712 int32_t QCamera3SupportChannel::request(buffer_handle_t * /*buffer*/,
4713 uint32_t /*frameNumber*/)
4714 {
4715 return NO_ERROR;
4716 }
4717
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream *)4718 void QCamera3SupportChannel::streamCbRoutine(
4719 mm_camera_super_buf_t *super_frame,
4720 QCamera3Stream * /*stream*/)
4721 {
4722 if (super_frame == NULL || super_frame->num_bufs != 1) {
4723 LOGE("super_frame is not valid");
4724 return;
4725 }
4726 bufDone(super_frame);
4727 free(super_frame);
4728 }
4729
getStreamBufs(uint32_t len)4730 QCamera3StreamMem* QCamera3SupportChannel::getStreamBufs(uint32_t len)
4731 {
4732 int rc;
4733 mMemory = new QCamera3StreamMem(mNumBuffers);
4734 if (!mMemory) {
4735 LOGE("unable to create heap memory");
4736 return NULL;
4737 }
4738 rc = mMemory->allocateAll(len);
4739 if (rc < 0) {
4740 LOGE("unable to allocate heap memory");
4741 delete mMemory;
4742 mMemory = NULL;
4743 return NULL;
4744 }
4745 return mMemory;
4746 }
4747
putStreamBufs()4748 void QCamera3SupportChannel::putStreamBufs()
4749 {
4750 mMemory->deallocate();
4751 delete mMemory;
4752 mMemory = NULL;
4753 }
4754
4755 }; // namespace qcamera
4756