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