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
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)1804 void QCamera3RawChannel::streamCbRoutine(
1805 mm_camera_super_buf_t *super_frame,
1806 QCamera3Stream * stream)
1807 {
1808 ATRACE_CALL();
1809 /* Move this back down once verified */
1810 if (mRawDump)
1811 dumpRawSnapshot(super_frame->bufs[0]);
1812
1813 if (mIsRaw16) {
1814 if (RAW_FORMAT == CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG)
1815 convertMipiToRaw16(super_frame->bufs[0]);
1816 else
1817 convertLegacyToRaw16(super_frame->bufs[0]);
1818 }
1819
1820 //Make sure cache coherence because extra processing is done
1821 mMemory.cleanInvalidateCache(super_frame->bufs[0]->buf_idx);
1822
1823 QCamera3RegularChannel::streamCbRoutine(super_frame, stream);
1824 return;
1825 }
1826
dumpRawSnapshot(mm_camera_buf_def_t * frame)1827 void QCamera3RawChannel::dumpRawSnapshot(mm_camera_buf_def_t *frame)
1828 {
1829 QCamera3Stream *stream = getStreamByIndex(0);
1830 if (stream != NULL) {
1831 char buf[FILENAME_MAX];
1832 memset(buf, 0, sizeof(buf));
1833 cam_dimension_t dim;
1834 memset(&dim, 0, sizeof(dim));
1835 stream->getFrameDimension(dim);
1836
1837 cam_frame_len_offset_t offset;
1838 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
1839 stream->getFrameOffset(offset);
1840 snprintf(buf, sizeof(buf), QCAMERA_DUMP_FRM_LOCATION"r_%d_%dx%d.raw",
1841 frame->frame_idx, offset.mp[0].stride, offset.mp[0].scanline);
1842
1843 int file_fd = open(buf, O_RDWR| O_CREAT, 0644);
1844 if (file_fd >= 0) {
1845 ssize_t written_len = write(file_fd, frame->buffer, frame->frame_len);
1846 ALOGE("%s: written number of bytes %zd", __func__, written_len);
1847 close(file_fd);
1848 } else {
1849 ALOGE("%s: failed to open file to dump image", __func__);
1850 }
1851 } else {
1852 ALOGE("%s: Could not find stream", __func__);
1853 }
1854
1855 }
1856
convertLegacyToRaw16(mm_camera_buf_def_t * frame)1857 void QCamera3RawChannel::convertLegacyToRaw16(mm_camera_buf_def_t *frame)
1858 {
1859 // Convert image buffer from Opaque raw format to RAW16 format
1860 // 10bit Opaque raw is stored in the format of:
1861 // 0000 - p5 - p4 - p3 - p2 - p1 - p0
1862 // where p0 to p5 are 6 pixels (each is 10bit)_and most significant
1863 // 4 bits are 0s. Each 64bit word contains 6 pixels.
1864
1865 QCamera3Stream *stream = getStreamByIndex(0);
1866 if (stream != NULL) {
1867 cam_dimension_t dim;
1868 memset(&dim, 0, sizeof(dim));
1869 stream->getFrameDimension(dim);
1870
1871 cam_frame_len_offset_t offset;
1872 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
1873 stream->getFrameOffset(offset);
1874
1875 uint32_t raw16_stride = ((uint32_t)dim.width + 15U) & ~15U;
1876 uint16_t* raw16_buffer = (uint16_t *)frame->buffer;
1877
1878 // In-place format conversion.
1879 // Raw16 format always occupy more memory than opaque raw10.
1880 // Convert to Raw16 by iterating through all pixels from bottom-right
1881 // to top-left of the image.
1882 // One special notes:
1883 // 1. Cross-platform raw16's stride is 16 pixels.
1884 // 2. Opaque raw10's stride is 6 pixels, and aligned to 16 bytes.
1885 for (int32_t ys = dim.height - 1; ys >= 0; ys--) {
1886 uint32_t y = (uint32_t)ys;
1887 uint64_t* row_start = (uint64_t *)frame->buffer +
1888 y * (uint32_t)offset.mp[0].stride_in_bytes / 8;
1889 for (int32_t xs = dim.width - 1; xs >= 0; xs--) {
1890 uint32_t x = (uint32_t)xs;
1891 uint16_t raw16_pixel = 0x3FF & (row_start[x/6] >> (10*(x%6)));
1892 raw16_buffer[y*raw16_stride+x] = raw16_pixel;
1893 }
1894 }
1895 } else {
1896 ALOGE("%s: Could not find stream", __func__);
1897 }
1898
1899 }
1900
convertMipiToRaw16(mm_camera_buf_def_t * frame)1901 void QCamera3RawChannel::convertMipiToRaw16(mm_camera_buf_def_t *frame)
1902 {
1903 // Convert image buffer from mipi10 raw format to RAW16 format
1904 // mipi10 opaque raw is stored in the format of:
1905 // P3(1:0) P2(1:0) P1(1:0) P0(1:0) P3(9:2) P2(9:2) P1(9:2) P0(9:2)
1906 // 4 pixels occupy 5 bytes, no padding needed
1907
1908 QCamera3Stream *stream = getStreamByIndex(0);
1909 if (stream != NULL) {
1910 cam_dimension_t dim;
1911 memset(&dim, 0, sizeof(dim));
1912 stream->getFrameDimension(dim);
1913
1914 cam_frame_len_offset_t offset;
1915 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
1916 stream->getFrameOffset(offset);
1917
1918 uint32_t raw16_stride = ((uint32_t)dim.width + 15U) & ~15U;
1919 uint16_t* raw16_buffer = (uint16_t *)frame->buffer;
1920
1921 // Some raw processing may be needed prior to conversion.
1922 static bool raw_proc_lib_load_attempted = false;
1923 static void *raw_proc_lib = NULL;
1924 static void *raw_proc_fn = NULL;
1925 if (! raw_proc_lib && ! raw_proc_lib_load_attempted) {
1926 raw_proc_lib_load_attempted = true;
1927 raw_proc_lib = dlopen("libgoog_rownr.so", RTLD_NOW);
1928 if (raw_proc_lib) {
1929 *(void **)&raw_proc_fn = dlsym(raw_proc_lib, "rownr_process_bayer10");
1930 }
1931 }
1932 if (raw_proc_fn) {
1933 int (*raw_proc)(unsigned char*,int,int,int,int) =
1934 (int (*)(unsigned char*,int,int,int,int))(raw_proc_fn);
1935 raw_proc((unsigned char*)(frame->buffer), 0, dim.width, dim.height,
1936 offset.mp[0].stride_in_bytes);
1937 }
1938
1939 // In-place format conversion.
1940 // Raw16 format always occupy more memory than opaque raw10.
1941 // Convert to Raw16 by iterating through all pixels from bottom-right
1942 // to top-left of the image.
1943 // One special notes:
1944 // 1. Cross-platform raw16's stride is 16 pixels.
1945 // 2. mipi raw10's stride is 4 pixels, and aligned to 16 bytes.
1946 for (int32_t ys = dim.height - 1; ys >= 0; ys--) {
1947 uint32_t y = (uint32_t)ys;
1948 uint8_t* row_start = (uint8_t *)frame->buffer +
1949 y * (uint32_t)offset.mp[0].stride_in_bytes;
1950 for (int32_t xs = dim.width - 1; xs >= 0; xs--) {
1951 uint32_t x = (uint32_t)xs;
1952 uint8_t upper_8bit = row_start[5*(x/4)+x%4];
1953 uint8_t lower_2bit = ((row_start[5*(x/4)+4] >> (x%4)) & 0x3);
1954 uint16_t raw16_pixel =
1955 (uint16_t)(((uint16_t)upper_8bit)<<2 |
1956 (uint16_t)lower_2bit);
1957 raw16_buffer[y*raw16_stride+x] = raw16_pixel;
1958 }
1959 }
1960 } else {
1961 ALOGE("%s: Could not find stream", __func__);
1962 }
1963
1964 }
1965
1966 /*===========================================================================
1967 * FUNCTION : getReprocessType
1968 *
1969 * DESCRIPTION: get the type of reprocess output supported by this channel
1970 *
1971 * PARAMETERS : NONE
1972 *
1973 * RETURN : reprocess_type_t : type of reprocess
1974 *==========================================================================*/
getReprocessType()1975 reprocess_type_t QCamera3RawChannel::getReprocessType()
1976 {
1977 return REPROCESS_TYPE_RAW;
1978 }
1979
1980
1981 /*************************************************************************************/
1982 // RAW Dump Channel related functions
1983
1984 /*===========================================================================
1985 * FUNCTION : QCamera3RawDumpChannel
1986 *
1987 * DESCRIPTION: Constructor for RawDumpChannel
1988 *
1989 * PARAMETERS :
1990 * @cam_handle : Handle for Camera
1991 * @cam_ops : Function pointer table
1992 * @rawDumpSize : Dimensions for the Raw stream
1993 * @paddinginfo : Padding information for stream
1994 * @userData : Cookie for parent
1995 * @pp mask : PP feature mask for this stream
1996 * @numBuffers : number of max dequeued buffers
1997 *
1998 * RETURN : NA
1999 *==========================================================================*/
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)2000 QCamera3RawDumpChannel::QCamera3RawDumpChannel(uint32_t cam_handle,
2001 uint32_t channel_handle,
2002 mm_camera_ops_t *cam_ops,
2003 cam_dimension_t rawDumpSize,
2004 cam_padding_info_t *paddingInfo,
2005 void *userData,
2006 uint32_t postprocess_mask, uint32_t numBuffers) :
2007 QCamera3Channel(cam_handle, channel_handle, cam_ops, NULL,
2008 paddingInfo, postprocess_mask,
2009 userData, numBuffers),
2010 mDim(rawDumpSize),
2011 mMemory(NULL)
2012 {
2013 char prop[PROPERTY_VALUE_MAX];
2014 property_get("persist.camera.raw.dump", prop, "0");
2015 mRawDump = atoi(prop);
2016 }
2017
2018 /*===========================================================================
2019 * FUNCTION : QCamera3RawDumpChannel
2020 *
2021 * DESCRIPTION: Destructor for RawDumpChannel
2022 *
2023 * PARAMETERS :
2024 *
2025 * RETURN : NA
2026 *==========================================================================*/
2027
~QCamera3RawDumpChannel()2028 QCamera3RawDumpChannel::~QCamera3RawDumpChannel()
2029 {
2030 }
2031
2032 /*===========================================================================
2033 * FUNCTION : dumpRawSnapshot
2034 *
2035 * DESCRIPTION: Helper function to dump Raw frames
2036 *
2037 * PARAMETERS :
2038 * @frame : stream buf frame to be dumped
2039 *
2040 * RETURN : NA
2041 *==========================================================================*/
dumpRawSnapshot(mm_camera_buf_def_t * frame)2042 void QCamera3RawDumpChannel::dumpRawSnapshot(mm_camera_buf_def_t *frame)
2043 {
2044 QCamera3Stream *stream = getStreamByIndex(0);
2045 if (stream != NULL) {
2046 char buf[FILENAME_MAX];
2047 struct timeval tv;
2048 struct tm timeinfo_data;
2049 struct tm *timeinfo;
2050
2051 cam_dimension_t dim;
2052 memset(&dim, 0, sizeof(dim));
2053 stream->getFrameDimension(dim);
2054
2055 cam_frame_len_offset_t offset;
2056 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
2057 stream->getFrameOffset(offset);
2058
2059 gettimeofday(&tv, NULL);
2060 timeinfo = localtime_r(&tv.tv_sec, &timeinfo_data);
2061
2062 if (NULL != timeinfo) {
2063 memset(buf, 0, sizeof(buf));
2064 snprintf(buf, sizeof(buf),
2065 QCAMERA_DUMP_FRM_LOCATION
2066 "%04d-%02d-%02d-%02d-%02d-%02d-%06ld_%d_%dx%d.raw",
2067 timeinfo->tm_year + 1900, timeinfo->tm_mon + 1,
2068 timeinfo->tm_mday, timeinfo->tm_hour,
2069 timeinfo->tm_min, timeinfo->tm_sec,tv.tv_usec,
2070 frame->frame_idx, dim.width, dim.height);
2071
2072 int file_fd = open(buf, O_RDWR| O_CREAT, 0777);
2073 if (file_fd >= 0) {
2074 ssize_t written_len =
2075 write(file_fd, frame->buffer, offset.frame_len);
2076 CDBG("%s: written number of bytes %zd", __func__, written_len);
2077 close(file_fd);
2078 } else {
2079 ALOGE("%s: failed to open file to dump image", __func__);
2080 }
2081 } else {
2082 ALOGE("%s: localtime_r() error", __func__);
2083 }
2084 } else {
2085 ALOGE("%s: Could not find stream", __func__);
2086 }
2087
2088 }
2089
2090 /*===========================================================================
2091 * FUNCTION : streamCbRoutine
2092 *
2093 * DESCRIPTION: Callback routine invoked for each frame generated for
2094 * Rawdump channel
2095 *
2096 * PARAMETERS :
2097 * @super_frame : stream buf frame generated
2098 * @stream : Underlying Stream object cookie
2099 *
2100 * RETURN : NA
2101 *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)2102 void QCamera3RawDumpChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
2103 QCamera3Stream *stream)
2104 {
2105 CDBG("%s: E",__func__);
2106 if (super_frame == NULL || super_frame->num_bufs != 1) {
2107 ALOGE("%s: super_frame is not valid", __func__);
2108 return;
2109 }
2110
2111 if (mRawDump)
2112 dumpRawSnapshot(super_frame->bufs[0]);
2113
2114 bufDone(super_frame);
2115 free(super_frame);
2116 }
2117
2118 /*===========================================================================
2119 * FUNCTION : getStreamBufs
2120 *
2121 * DESCRIPTION: Callback function provided to interface to get buffers.
2122 *
2123 * PARAMETERS :
2124 * @len : Length of each buffer to be allocated
2125 *
2126 * RETURN : NULL on buffer allocation failure
2127 * QCamera3StreamMem object on sucess
2128 *==========================================================================*/
getStreamBufs(uint32_t len)2129 QCamera3StreamMem* QCamera3RawDumpChannel::getStreamBufs(uint32_t len)
2130 {
2131 int rc;
2132 mMemory = new QCamera3StreamMem(mNumBuffers);
2133
2134 if (!mMemory) {
2135 ALOGE("%s: unable to create heap memory", __func__);
2136 return NULL;
2137 }
2138 rc = mMemory->allocateAll((size_t)len);
2139 if (rc < 0) {
2140 ALOGE("%s: unable to allocate heap memory", __func__);
2141 delete mMemory;
2142 mMemory = NULL;
2143 return NULL;
2144 }
2145 return mMemory;
2146 }
2147
2148 /*===========================================================================
2149 * FUNCTION : putStreamBufs
2150 *
2151 * DESCRIPTION: Callback function provided to interface to return buffers.
2152 * Although no handles are actually returned, implicitl assumption
2153 * that interface will no longer use buffers and channel can
2154 * deallocated if necessary.
2155 *
2156 * PARAMETERS : NA
2157 *
2158 * RETURN : NA
2159 *==========================================================================*/
putStreamBufs()2160 void QCamera3RawDumpChannel::putStreamBufs()
2161 {
2162 mMemory->deallocate();
2163 delete mMemory;
2164 mMemory = NULL;
2165 }
2166
2167 /*===========================================================================
2168 * FUNCTION : request
2169 *
2170 * DESCRIPTION: Request function used as trigger
2171 *
2172 * PARAMETERS :
2173 * @recvd_frame : buffer- this will be NULL since this is internal channel
2174 * @frameNumber : Undefined again since this is internal stream
2175 *
2176 * RETURN : int32_t type of status
2177 * NO_ERROR -- success
2178 * none-zero failure code
2179 *==========================================================================*/
request(buffer_handle_t *,uint32_t)2180 int32_t QCamera3RawDumpChannel::request(buffer_handle_t * /*buffer*/,
2181 uint32_t /*frameNumber*/)
2182 {
2183 if (!m_bIsActive) {
2184 return QCamera3Channel::start();
2185 }
2186 else
2187 return 0;
2188 }
2189
2190 /*===========================================================================
2191 * FUNCTION : intialize
2192 *
2193 * DESCRIPTION: Initializes channel params and creates underlying stream
2194 *
2195 * PARAMETERS :
2196 * @isType : type of image stabilization required on this stream
2197 *
2198 * RETURN : int32_t type of status
2199 * NO_ERROR -- success
2200 * none-zero failure code
2201 *==========================================================================*/
initialize(cam_is_type_t isType)2202 int32_t QCamera3RawDumpChannel::initialize(cam_is_type_t isType)
2203 {
2204 int32_t rc;
2205
2206 mIsType = isType;
2207 rc = QCamera3Channel::addStream(CAM_STREAM_TYPE_RAW,
2208 CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG, mDim, ROTATE_0, (uint8_t)mNumBuffers,
2209 mPostProcMask, mIsType);
2210 if (rc < 0) {
2211 ALOGE("%s: addStream failed", __func__);
2212 }
2213 return rc;
2214 }
2215 /*************************************************************************************/
2216
2217 /* QCamera3YUVChannel methods */
2218
2219 /*===========================================================================
2220 * FUNCTION : QCamera3YUVChannel
2221 *
2222 * DESCRIPTION: constructor of QCamera3YUVChannel
2223 *
2224 * PARAMETERS :
2225 * @cam_handle : camera handle
2226 * @cam_ops : ptr to camera ops table
2227 * @cb_routine : callback routine to frame aggregator
2228 * @paddingInfo : padding information for the stream
2229 * @stream : camera3_stream_t structure
2230 * @stream_type: Channel stream type
2231 * @postprocess_mask: the postprocess mask for streams of this channel
2232 * @metadataChannel: handle to the metadataChannel
2233 * RETURN : none
2234 *==========================================================================*/
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)2235 QCamera3YUVChannel::QCamera3YUVChannel(uint32_t cam_handle,
2236 uint32_t channel_handle,
2237 mm_camera_ops_t *cam_ops,
2238 channel_cb_routine cb_routine,
2239 cam_padding_info_t *paddingInfo,
2240 void *userData,
2241 camera3_stream_t *stream,
2242 cam_stream_type_t stream_type,
2243 uint32_t postprocess_mask,
2244 QCamera3Channel *metadataChannel) :
2245 QCamera3ProcessingChannel(cam_handle, channel_handle, cam_ops,
2246 cb_routine, paddingInfo, userData, stream, stream_type,
2247 postprocess_mask, metadataChannel)
2248 {
2249
2250 mBypass = (postprocess_mask == CAM_QCOM_FEATURE_NONE);
2251 mFrameLen = 0;
2252 mEdgeMode.edge_mode = CAM_EDGE_MODE_OFF;
2253 mEdgeMode.sharpness = 0;
2254 mNoiseRedMode = CAM_NOISE_REDUCTION_MODE_OFF;
2255 memset(&mCropRegion, 0, sizeof(mCropRegion));
2256 }
2257
2258 /*===========================================================================
2259 * FUNCTION : ~QCamera3YUVChannel
2260 *
2261 * DESCRIPTION: destructor of QCamera3YUVChannel
2262 *
2263 * PARAMETERS : none
2264 *
2265 *
2266 * RETURN : none
2267 *==========================================================================*/
~QCamera3YUVChannel()2268 QCamera3YUVChannel::~QCamera3YUVChannel()
2269 {
2270 // Deallocation of heap buffers allocated in mMemory is freed
2271 // automatically by its destructor
2272 }
2273
2274 /*===========================================================================
2275 * FUNCTION : initialize
2276 *
2277 * DESCRIPTION: Initialize and add camera channel & stream
2278 *
2279 * PARAMETERS :
2280 * @isType : the image stabilization type
2281 *
2282 * RETURN : int32_t type of status
2283 * NO_ERROR -- success
2284 * none-zero failure code
2285 *==========================================================================*/
initialize(cam_is_type_t isType)2286 int32_t QCamera3YUVChannel::initialize(cam_is_type_t isType)
2287 {
2288 ATRACE_CALL();
2289 int32_t rc = NO_ERROR;
2290 cam_dimension_t streamDim;
2291
2292 if (NULL == mCamera3Stream) {
2293 ALOGE("%s: Camera stream uninitialized", __func__);
2294 return NO_INIT;
2295 }
2296
2297 if (1 <= m_numStreams) {
2298 // Only one stream per channel supported in v3 Hal
2299 return NO_ERROR;
2300 }
2301
2302 mIsType = isType;
2303 mStreamFormat = CALLBACK_FORMAT;
2304 streamDim.width = mCamera3Stream->width;
2305 streamDim.height = mCamera3Stream->height;
2306
2307 rc = QCamera3Channel::addStream(mStreamType,
2308 mStreamFormat,
2309 streamDim,
2310 ROTATE_0,
2311 mNumBufs,
2312 mPostProcMask,
2313 mIsType);
2314 if (rc < 0) {
2315 ALOGE("%s: addStream failed", __func__);
2316 return rc;
2317 }
2318
2319 cam_stream_buf_plane_info_t buf_planes;
2320 cam_padding_info_t paddingInfo = *mPaddingInfo;
2321
2322 memset(&buf_planes, 0, sizeof(buf_planes));
2323 //to ensure a big enough buffer size set the height and width
2324 //padding to max(height padding, width padding)
2325 paddingInfo.width_padding = MAX(paddingInfo.width_padding, paddingInfo.height_padding);
2326 paddingInfo.height_padding = paddingInfo.width_padding;
2327
2328 rc = mm_stream_calc_offset_snapshot(mStreamFormat, &streamDim, &paddingInfo,
2329 &buf_planes);
2330 if (rc < 0) {
2331 ALOGE("%s: mm_stream_calc_offset_preview failed", __func__);
2332 return rc;
2333 }
2334
2335 mFrameLen = buf_planes.plane_info.frame_len;
2336
2337 if (NO_ERROR != rc) {
2338 ALOGE("%s: Initialize failed, rc = %d", __func__, rc);
2339 return rc;
2340 }
2341
2342 /* initialize offline meta memory for input reprocess */
2343 rc = QCamera3ProcessingChannel::initialize(isType);
2344 if (NO_ERROR != rc) {
2345 ALOGE("%s: Processing Channel initialize failed, rc = %d",
2346 __func__, rc);
2347 }
2348
2349 return rc;
2350 }
2351
2352 /*===========================================================================
2353 * FUNCTION : request
2354 *
2355 * DESCRIPTION: entry function for a request on a YUV stream. This function
2356 * has the logic to service a request based on its type
2357 *
2358 * PARAMETERS :
2359 * @buffer : pointer to the output buffer
2360 * @frameNumber : frame number of the request
2361 * @pInputBuffer : pointer to input buffer if an input request
2362 * @metadata : parameters associated with the request
2363 *
2364 * RETURN : 0 on a success start of capture
2365 * -EINVAL on invalid input
2366 * -ENODEV on serious error
2367 *==========================================================================*/
request(buffer_handle_t * buffer,uint32_t frameNumber,camera3_stream_buffer_t * pInputBuffer,metadata_buffer_t * metadata,bool & needMetadata)2368 int32_t QCamera3YUVChannel::request(buffer_handle_t *buffer,
2369 uint32_t frameNumber,
2370 camera3_stream_buffer_t* pInputBuffer,
2371 metadata_buffer_t* metadata, bool &needMetadata)
2372 {
2373 int32_t rc = NO_ERROR;
2374 int index;
2375 Mutex::Autolock lock(mOfflinePpLock);
2376
2377 CDBG("%s: pInputBuffer is %p", __func__, pInputBuffer);
2378 CDBG("%s, frame number %d", __func__, frameNumber);
2379 if (NULL == buffer || NULL == metadata) {
2380 ALOGE("%s: Invalid buffer/metadata in channel request", __func__);
2381 return BAD_VALUE;
2382 }
2383
2384 PpInfo ppInfo;
2385 memset(&ppInfo, 0, sizeof(ppInfo));
2386 ppInfo.frameNumber = frameNumber;
2387 ppInfo.offlinePpFlag = false;
2388 if (mBypass && !pInputBuffer ) {
2389 ppInfo.offlinePpFlag = needsFramePostprocessing(metadata);
2390 ppInfo.output = buffer;
2391 mOfflinePpInfoList.push_back(ppInfo);
2392 }
2393
2394 CDBG("%s: offlinePpFlag is %d", __func__, ppInfo.offlinePpFlag);
2395 needMetadata = ppInfo.offlinePpFlag;
2396 if (!ppInfo.offlinePpFlag) {
2397 // regular request
2398 return QCamera3ProcessingChannel::request(buffer, frameNumber,
2399 pInputBuffer, metadata);
2400 } else {
2401 if(!m_bIsActive) {
2402 rc = start();
2403 if (NO_ERROR != rc)
2404 return rc;
2405 } else {
2406 CDBG("%s: Request on an existing stream",__func__);
2407 }
2408
2409 //we need to send this frame through the CPP
2410 //Allocate heap memory, then buf done on the buffer
2411 uint32_t bufIdx;
2412 if (mFreeHeapBufferList.empty()) {
2413 rc = mMemory.allocateOne(mFrameLen);
2414 if (rc < 0) {
2415 ALOGE("%s: Failed allocating heap buffer. Fatal", __func__);
2416 return BAD_VALUE;
2417 } else {
2418 bufIdx = (uint32_t)rc;
2419 }
2420 } else {
2421 bufIdx = *(mFreeHeapBufferList.begin());
2422 mFreeHeapBufferList.erase(mFreeHeapBufferList.begin());
2423 }
2424
2425 /* Configure and start postproc if necessary */
2426 reprocess_config_t reproc_cfg;
2427 cam_dimension_t dim;
2428 memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
2429 memset(&dim, 0, sizeof(dim));
2430 mStreams[0]->getFrameDimension(dim);
2431 setReprocConfig(reproc_cfg, NULL, metadata, mStreamFormat, dim);
2432
2433 // Start postprocessor without input buffer
2434 startPostProc(reproc_cfg);
2435
2436 CDBG("%s: erasing %d", __func__, bufIdx);
2437
2438 mMemory.markFrameNumber(bufIdx, frameNumber);
2439 mStreams[0]->bufDone(bufIdx);
2440
2441 }
2442 return rc;
2443 }
2444
2445 /*===========================================================================
2446 * FUNCTION : streamCbRoutine
2447 *
2448 * DESCRIPTION:
2449 *
2450 * PARAMETERS :
2451 * @super_frame : the super frame with filled buffer
2452 * @stream : stream on which the buffer was requested and filled
2453 *
2454 * RETURN : none
2455 *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)2456 void QCamera3YUVChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
2457 QCamera3Stream *stream)
2458 {
2459 ATRACE_CALL();
2460 uint8_t frameIndex;
2461 int32_t resultFrameNumber;
2462
2463 if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
2464 ALOGE("%s: Error with the stream callback", __func__);
2465 return;
2466 }
2467
2468 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
2469 if(frameIndex >= mNumBufs) {
2470 ALOGE("%s: Error, Invalid index for buffer",__func__);
2471 stream->bufDone(frameIndex);
2472 return;
2473 }
2474
2475 if (mBypass) {
2476 List<PpInfo>::iterator ppInfo;
2477
2478 Mutex::Autolock lock(mOfflinePpLock);
2479 resultFrameNumber = mMemory.getFrameNumber(frameIndex);
2480 for (ppInfo = mOfflinePpInfoList.begin();
2481 ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
2482 if (ppInfo->frameNumber == (uint32_t)resultFrameNumber) {
2483 break;
2484 }
2485 }
2486 CDBG("%s, frame index %d, frame number %d", __func__, frameIndex, resultFrameNumber);
2487 //check the reprocessing required flag against the frame number
2488 if (ppInfo == mOfflinePpInfoList.end()) {
2489 ALOGE("%s: Error, request for frame number is a reprocess.", __func__);
2490 stream->bufDone(frameIndex);
2491 return;
2492 }
2493
2494 if (ppInfo->offlinePpFlag) {
2495 mm_camera_super_buf_t *frame =
2496 (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
2497 if (frame == NULL) {
2498 ALOGE("%s: Error allocating memory to save received_frame structure.",
2499 __func__);
2500 if(stream) {
2501 stream->bufDone(frameIndex);
2502 }
2503 return;
2504 }
2505
2506 *frame = *super_frame;
2507 m_postprocessor.processData(frame, ppInfo->output, resultFrameNumber);
2508 free(super_frame);
2509 return;
2510 } else {
2511 if (ppInfo != mOfflinePpInfoList.begin()) {
2512 // There is pending reprocess buffer, cache current buffer
2513 if (ppInfo->callback_buffer != NULL) {
2514 ALOGE("%s: Fatal: cached callback_buffer is already present",
2515 __func__);
2516
2517 }
2518 ppInfo->callback_buffer = super_frame;
2519 return;
2520 } else {
2521 mOfflinePpInfoList.erase(ppInfo);
2522 }
2523 }
2524 }
2525
2526 QCamera3ProcessingChannel::streamCbRoutine(super_frame, stream);
2527 return;
2528 }
2529
2530 /*===========================================================================
2531 * FUNCTION : reprocessCbRoutine
2532 *
2533 * DESCRIPTION: callback function for the reprocessed frame. This frame now
2534 * should be returned to the framework. This same callback is
2535 * used during input reprocessing or offline postprocessing
2536 *
2537 * PARAMETERS :
2538 * @resultBuffer : buffer containing the reprocessed data
2539 * @resultFrameNumber : frame number on which the buffer was requested
2540 *
2541 * RETURN : NONE
2542 *
2543 *==========================================================================*/
reprocessCbRoutine(buffer_handle_t * resultBuffer,uint32_t resultFrameNumber)2544 void QCamera3YUVChannel::reprocessCbRoutine(buffer_handle_t *resultBuffer,
2545 uint32_t resultFrameNumber)
2546 {
2547 CDBG("%s E: frame number %d", __func__, resultFrameNumber);
2548 Vector<mm_camera_super_buf_t *> pendingCbs;
2549
2550 /* release the input buffer and input metadata buffer if used */
2551 if (0 > mMemory.getHeapBufferIndex(resultFrameNumber)) {
2552 /* mOfflineMemory and mOfflineMetaMemory used only for input reprocessing */
2553 int32_t rc = releaseOfflineMemory(resultFrameNumber);
2554 if (NO_ERROR != rc) {
2555 ALOGE("%s: Error releasing offline memory rc = %d", __func__, rc);
2556 }
2557 /* Since reprocessing is done, send the callback to release the input buffer */
2558 if (mChannelCB) {
2559 mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
2560 }
2561 }
2562
2563 if (mBypass) {
2564 int32_t rc = handleOfflinePpCallback(resultFrameNumber, pendingCbs);
2565 if (rc != NO_ERROR) {
2566 return;
2567 }
2568 }
2569
2570 issueChannelCb(resultBuffer, resultFrameNumber);
2571
2572 // Call all pending callbacks to return buffers
2573 for (size_t i = 0; i < pendingCbs.size(); i++) {
2574 QCamera3ProcessingChannel::streamCbRoutine(
2575 pendingCbs[i], mStreams[0]);
2576 }
2577
2578 }
2579
2580 /*===========================================================================
2581 * FUNCTION : needsFramePostprocessing
2582 *
2583 * DESCRIPTION:
2584 *
2585 * PARAMETERS :
2586 *
2587 * RETURN :
2588 * TRUE if frame needs to be postprocessed
2589 * FALSE is frame does not need to be postprocessed
2590 *
2591 *==========================================================================*/
needsFramePostprocessing(metadata_buffer_t * meta)2592 bool QCamera3YUVChannel::needsFramePostprocessing(metadata_buffer_t *meta)
2593 {
2594 bool ppNeeded = false;
2595
2596 //sharpness
2597 IF_META_AVAILABLE(cam_edge_application_t, edgeMode,
2598 CAM_INTF_META_EDGE_MODE, meta) {
2599 mEdgeMode = *edgeMode;
2600 }
2601
2602 //wnr
2603 IF_META_AVAILABLE(uint32_t, noiseRedMode,
2604 CAM_INTF_META_NOISE_REDUCTION_MODE, meta) {
2605 mNoiseRedMode = *noiseRedMode;
2606 }
2607
2608 //crop region
2609 IF_META_AVAILABLE(cam_crop_region_t, scalerCropRegion,
2610 CAM_INTF_META_SCALER_CROP_REGION, meta) {
2611 mCropRegion = *scalerCropRegion;
2612 }
2613
2614 if ((CAM_EDGE_MODE_OFF != mEdgeMode.edge_mode) &&
2615 (CAM_EDGE_MODE_ZERO_SHUTTER_LAG != mEdgeMode.edge_mode)) {
2616 ppNeeded = true;
2617 }
2618 if ((CAM_NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG != mNoiseRedMode) &&
2619 (CAM_NOISE_REDUCTION_MODE_OFF != mNoiseRedMode) &&
2620 (CAM_NOISE_REDUCTION_MODE_MINIMAL != mNoiseRedMode)) {
2621 ppNeeded = true;
2622 }
2623 if ((mCropRegion.width < (int32_t)mCamera3Stream->width) ||
2624 (mCropRegion.height < (int32_t)mCamera3Stream->height)) {
2625 ppNeeded = true;
2626 }
2627
2628 return ppNeeded;
2629 }
2630
2631 /*===========================================================================
2632 * FUNCTION : handleOfflinePpCallback
2633 *
2634 * DESCRIPTION: callback function for the reprocessed frame from offline
2635 * postprocessing.
2636 *
2637 * PARAMETERS :
2638 * @resultFrameNumber : frame number on which the buffer was requested
2639 * @pendingCbs : pending buffers to be returned first
2640 *
2641 * RETURN : int32_t type of status
2642 * NO_ERROR -- success
2643 * none-zero failure code
2644 *==========================================================================*/
handleOfflinePpCallback(uint32_t resultFrameNumber,Vector<mm_camera_super_buf_t * > & pendingCbs)2645 int32_t QCamera3YUVChannel::handleOfflinePpCallback(uint32_t resultFrameNumber,
2646 Vector<mm_camera_super_buf_t *>& pendingCbs)
2647 {
2648 Mutex::Autolock lock(mOfflinePpLock);
2649 List<PpInfo>::iterator ppInfo;
2650
2651 for (ppInfo = mOfflinePpInfoList.begin();
2652 ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
2653 if (ppInfo->frameNumber == resultFrameNumber) {
2654 break;
2655 }
2656 }
2657
2658 if (ppInfo == mOfflinePpInfoList.end()) {
2659 ALOGI("%s: Request of frame number %d is reprocessing",
2660 __func__, resultFrameNumber);
2661 return NO_ERROR;
2662 } else if (ppInfo != mOfflinePpInfoList.begin()) {
2663 ALOGE("%s: callback for frame number %d should be head of list",
2664 __func__, resultFrameNumber);
2665 return BAD_VALUE;
2666 }
2667
2668 if (ppInfo->offlinePpFlag) {
2669 // Need to get the input buffer frame index from the
2670 // mMemory object and add that to the free heap buffers list.
2671 int32_t bufferIndex =
2672 mMemory.getHeapBufferIndex(resultFrameNumber);
2673 if (bufferIndex < 0) {
2674 ALOGE("%s: Fatal %d: no buffer index for frame number %d",
2675 __func__, bufferIndex, resultFrameNumber);
2676 return BAD_VALUE;
2677 }
2678 mFreeHeapBufferList.push_back(bufferIndex);
2679 ppInfo = mOfflinePpInfoList.erase(ppInfo);
2680
2681 // Return pending buffer callbacks
2682 while (ppInfo != mOfflinePpInfoList.end() &&
2683 !ppInfo->offlinePpFlag && ppInfo->callback_buffer) {
2684
2685 // Call stream callbacks for cached buffers
2686 pendingCbs.push_back(ppInfo->callback_buffer);
2687
2688 ppInfo = mOfflinePpInfoList.erase(ppInfo);
2689 }
2690
2691 } else {
2692 ALOGE("%s: Fatal: request of frame number %d doesn't need"
2693 " offline postprocessing. However there is"
2694 " reprocessing callback.", __func__,
2695 resultFrameNumber);
2696 return BAD_VALUE;
2697 }
2698
2699 return NO_ERROR;
2700 }
2701
2702 /*===========================================================================
2703 * FUNCTION : getReprocessType
2704 *
2705 * DESCRIPTION: get the type of reprocess output supported by this channel
2706 *
2707 * PARAMETERS : NONE
2708 *
2709 * RETURN : reprocess_type_t : type of reprocess
2710 *==========================================================================*/
getReprocessType()2711 reprocess_type_t QCamera3YUVChannel::getReprocessType()
2712 {
2713 return REPROCESS_TYPE_YUV;
2714 }
2715
2716 /* QCamera3PicChannel methods */
2717
2718 /*===========================================================================
2719 * FUNCTION : jpegEvtHandle
2720 *
2721 * DESCRIPTION: Function registerd to mm-jpeg-interface to handle jpeg events.
2722 Construct result payload and call mChannelCb to deliver buffer
2723 to framework.
2724 *
2725 * PARAMETERS :
2726 * @status : status of jpeg job
2727 * @client_hdl: jpeg client handle
2728 * @jobId : jpeg job Id
2729 * @p_ouput : ptr to jpeg output result struct
2730 * @userdata : user data ptr
2731 *
2732 * RETURN : none
2733 *==========================================================================*/
jpegEvtHandle(jpeg_job_status_t status,uint32_t,uint32_t jobId,mm_jpeg_output_t * p_output,void * userdata)2734 void QCamera3PicChannel::jpegEvtHandle(jpeg_job_status_t status,
2735 uint32_t /*client_hdl*/,
2736 uint32_t jobId,
2737 mm_jpeg_output_t *p_output,
2738 void *userdata)
2739 {
2740 ATRACE_CALL();
2741 buffer_handle_t *resultBuffer = NULL;
2742 buffer_handle_t *jpegBufferHandle = NULL;
2743 int resultStatus = CAMERA3_BUFFER_STATUS_OK;
2744 camera3_stream_buffer_t result;
2745 camera3_jpeg_blob_t jpegHeader;
2746
2747 QCamera3PicChannel *obj = (QCamera3PicChannel *)userdata;
2748 if (obj) {
2749 //Construct payload for process_capture_result. Call mChannelCb
2750
2751 qcamera_hal3_jpeg_data_t *job = obj->m_postprocessor.findJpegJobByJobId(jobId);
2752
2753 if ((job == NULL) || (status == JPEG_JOB_STATUS_ERROR)) {
2754 ALOGE("%s: Error in jobId: (%d) with status: %d", __func__, jobId, status);
2755 resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
2756 }
2757
2758 if (NULL != job) {
2759 uint32_t bufIdx = (uint32_t)job->jpeg_settings->out_buf_index;
2760 CDBG("%s: jpeg out_buf_index: %d", __func__, bufIdx);
2761
2762 //Construct jpeg transient header of type camera3_jpeg_blob_t
2763 //Append at the end of jpeg image of buf_filled_len size
2764
2765 jpegHeader.jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
2766 if (JPEG_JOB_STATUS_DONE == status) {
2767 jpegHeader.jpeg_size = (uint32_t)p_output->buf_filled_len;
2768 char* jpeg_buf = (char *)p_output->buf_vaddr;
2769
2770 ssize_t maxJpegSize = -1;
2771
2772 // Gralloc buffer may have additional padding for 4K page size
2773 // Follow size guidelines based on spec since framework relies
2774 // on that to reach end of buffer and with it the header
2775
2776 //Handle same as resultBuffer, but for readablity
2777 jpegBufferHandle =
2778 (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx);
2779
2780 if (NULL != jpegBufferHandle) {
2781 maxJpegSize = ((private_handle_t*)(*jpegBufferHandle))->width;
2782 if (maxJpegSize > obj->mMemory.getSize(bufIdx)) {
2783 maxJpegSize = obj->mMemory.getSize(bufIdx);
2784 }
2785
2786 size_t jpeg_eof_offset =
2787 (size_t)(maxJpegSize - (ssize_t)sizeof(jpegHeader));
2788 char *jpeg_eof = &jpeg_buf[jpeg_eof_offset];
2789 memcpy(jpeg_eof, &jpegHeader, sizeof(jpegHeader));
2790 obj->mMemory.cleanInvalidateCache(bufIdx);
2791 } else {
2792 ALOGE("%s: JPEG buffer not found and index: %d",
2793 __func__,
2794 bufIdx);
2795 resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
2796 }
2797 }
2798
2799 ////Use below data to issue framework callback
2800 resultBuffer =
2801 (buffer_handle_t *)obj->mMemory.getBufferHandle(bufIdx);
2802 int32_t resultFrameNumber = obj->mMemory.getFrameNumber(bufIdx);
2803 int32_t rc = obj->mMemory.unregisterBuffer(bufIdx);
2804 if (NO_ERROR != rc) {
2805 ALOGE("%s: Error %d unregistering stream buffer %d",
2806 __func__, rc, bufIdx);
2807 }
2808
2809 result.stream = obj->mCamera3Stream;
2810 result.buffer = resultBuffer;
2811 result.status = resultStatus;
2812 result.acquire_fence = -1;
2813 result.release_fence = -1;
2814
2815 // Release any snapshot buffers before calling
2816 // the user callback. The callback can potentially
2817 // unblock pending requests to snapshot stream.
2818 int32_t snapshotIdx = -1;
2819 mm_camera_super_buf_t* src_frame = NULL;
2820
2821 if (job->src_reproc_frame)
2822 src_frame = job->src_reproc_frame;
2823 else
2824 src_frame = job->src_frame;
2825
2826 if (src_frame) {
2827 if (obj->mStreams[0]->getMyHandle() ==
2828 src_frame->bufs[0]->stream_id) {
2829 snapshotIdx = (int32_t)src_frame->bufs[0]->buf_idx;
2830 } else {
2831 ALOGE("%s: Snapshot stream id %d and source frame %d don't match!",
2832 __func__, obj->mStreams[0]->getMyHandle(),
2833 src_frame->bufs[0]->stream_id);
2834 }
2835 }
2836 if (0 <= snapshotIdx) {
2837 Mutex::Autolock lock(obj->mFreeBuffersLock);
2838 obj->mFreeBufferList.push_back((uint32_t)snapshotIdx);
2839 } else {
2840 ALOGE("%s: Snapshot buffer not found!", __func__);
2841 }
2842
2843 CDBG("%s: Issue Callback", __func__);
2844 if (obj->mChannelCB) {
2845 obj->mChannelCB(NULL,
2846 &result,
2847 (uint32_t)resultFrameNumber,
2848 false,
2849 obj->mUserData);
2850 }
2851
2852 // release internal data for jpeg job
2853 if ((NULL != job->fwk_frame) || (NULL != job->fwk_src_buffer)) {
2854 /* unregister offline input buffer */
2855 int32_t inputBufIndex =
2856 obj->mOfflineMemory.getGrallocBufferIndex((uint32_t)resultFrameNumber);
2857 if (0 <= inputBufIndex) {
2858 rc = obj->mOfflineMemory.unregisterBuffer(inputBufIndex);
2859 } else {
2860 ALOGE("%s: could not find the input buf index, frame number %d",
2861 __func__, resultFrameNumber);
2862 }
2863 if (NO_ERROR != rc) {
2864 ALOGE("%s: Error %d unregistering input buffer %d",
2865 __func__, rc, bufIdx);
2866 }
2867
2868 /* unregister offline meta buffer */
2869 int32_t metaBufIndex =
2870 obj->mOfflineMetaMemory.getHeapBufferIndex((uint32_t)resultFrameNumber);
2871 if (0 <= metaBufIndex) {
2872 Mutex::Autolock lock(obj->mFreeOfflineMetaBuffersLock);
2873 obj->mFreeOfflineMetaBuffersList.push_back((uint32_t)metaBufIndex);
2874 } else {
2875 ALOGE("%s: could not find the input meta buf index, frame number %d",
2876 __func__, resultFrameNumber);
2877 }
2878 }
2879 obj->m_postprocessor.releaseOfflineBuffers();
2880 obj->m_postprocessor.releaseJpegJobData(job);
2881 free(job);
2882 }
2883
2884 return;
2885 // }
2886 } else {
2887 ALOGE("%s: Null userdata in jpeg callback", __func__);
2888 }
2889 }
2890
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)2891 QCamera3PicChannel::QCamera3PicChannel(uint32_t cam_handle,
2892 uint32_t channel_handle,
2893 mm_camera_ops_t *cam_ops,
2894 channel_cb_routine cb_routine,
2895 cam_padding_info_t *paddingInfo,
2896 void *userData,
2897 camera3_stream_t *stream,
2898 uint32_t postprocess_mask,
2899 bool is4KVideo,
2900 bool isInputStreamConfigured,
2901 QCamera3Channel *metadataChannel,
2902 uint32_t numBuffers) :
2903 QCamera3ProcessingChannel(cam_handle, channel_handle,
2904 cam_ops, cb_routine, paddingInfo, userData,
2905 stream, CAM_STREAM_TYPE_SNAPSHOT,
2906 postprocess_mask, metadataChannel, numBuffers),
2907 mNumSnapshotBufs(0),
2908 mInputBufferHint(isInputStreamConfigured),
2909 mYuvMemory(NULL),
2910 mFrameLen(0)
2911 {
2912 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
2913 m_max_pic_dim = hal_obj->calcMaxJpegDim();
2914 mYuvWidth = stream->width;
2915 mYuvHeight = stream->height;
2916 mStreamType = CAM_STREAM_TYPE_SNAPSHOT;
2917 // Use same pixelformat for 4K video case
2918 mStreamFormat = is4KVideo ? VIDEO_FORMAT : SNAPSHOT_FORMAT;
2919 int32_t rc = m_postprocessor.initJpeg(jpegEvtHandle, &m_max_pic_dim, this);
2920 if (rc != 0) {
2921 ALOGE("Init Postprocessor failed");
2922 }
2923 }
2924
~QCamera3PicChannel()2925 QCamera3PicChannel::~QCamera3PicChannel()
2926 {
2927 }
2928
initialize(cam_is_type_t isType)2929 int32_t QCamera3PicChannel::initialize(cam_is_type_t isType)
2930 {
2931 int32_t rc = NO_ERROR;
2932 cam_dimension_t streamDim;
2933 cam_stream_type_t streamType;
2934 cam_format_t streamFormat;
2935 mm_camera_channel_attr_t attr;
2936
2937 if (NULL == mCamera3Stream) {
2938 ALOGE("%s: Camera stream uninitialized", __func__);
2939 return NO_INIT;
2940 }
2941
2942 if (1 <= m_numStreams) {
2943 // Only one stream per channel supported in v3 Hal
2944 return NO_ERROR;
2945 }
2946
2947 mIsType = isType;
2948 streamType = mStreamType;
2949 streamFormat = mStreamFormat;
2950 streamDim.width = (int32_t)mYuvWidth;
2951 streamDim.height = (int32_t)mYuvHeight;
2952
2953 mNumSnapshotBufs = mCamera3Stream->max_buffers;
2954 rc = QCamera3Channel::addStream(streamType, streamFormat, streamDim,
2955 ROTATE_0, (uint8_t)mCamera3Stream->max_buffers, mPostProcMask,
2956 mIsType);
2957
2958 if (NO_ERROR != rc) {
2959 ALOGE("%s: Initialize failed, rc = %d", __func__, rc);
2960 return rc;
2961 }
2962
2963 /* initialize offline meta memory for input reprocess */
2964 rc = QCamera3ProcessingChannel::initialize(isType);
2965 if (NO_ERROR != rc) {
2966 ALOGE("%s: Processing Channel initialize failed, rc = %d",
2967 __func__, rc);
2968 }
2969
2970 return rc;
2971 }
2972
2973 /*===========================================================================
2974 * FUNCTION : request
2975 *
2976 * DESCRIPTION: handle the request - either with an input buffer or a direct
2977 * output request
2978 *
2979 * PARAMETERS :
2980 * @buffer : pointer to the output buffer
2981 * @frameNumber : frame number of the request
2982 * @pInputBuffer : pointer to input buffer if an input request
2983 * @metadata : parameters associated with the request
2984 *
2985 * RETURN : 0 on a success start of capture
2986 * -EINVAL on invalid input
2987 * -ENODEV on serious error
2988 *==========================================================================*/
request(buffer_handle_t * buffer,uint32_t frameNumber,camera3_stream_buffer_t * pInputBuffer,metadata_buffer_t * metadata)2989 int32_t QCamera3PicChannel::request(buffer_handle_t *buffer,
2990 uint32_t frameNumber,
2991 camera3_stream_buffer_t *pInputBuffer,
2992 metadata_buffer_t *metadata)
2993 {
2994 ATRACE_CALL();
2995 //FIX ME: Return buffer back in case of failures below.
2996
2997 int32_t rc = NO_ERROR;
2998
2999 reprocess_config_t reproc_cfg;
3000 cam_dimension_t dim;
3001 memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
3002 //make sure to set the correct input stream dim in case of YUV size override
3003 //and recalculate the plane info
3004 dim.width = (int32_t)mYuvWidth;
3005 dim.height = (int32_t)mYuvHeight;
3006 setReprocConfig(reproc_cfg, pInputBuffer, metadata, mStreamFormat, dim);
3007
3008 // Picture stream has already been started before any request comes in
3009 if (!m_bIsActive) {
3010 ALOGE("%s: Channel not started!!", __func__);
3011 return NO_INIT;
3012 }
3013
3014 int index = mMemory.getMatchBufIndex((void*)buffer);
3015
3016 if(index < 0) {
3017 rc = registerBuffer(buffer, mIsType);
3018 if (NO_ERROR != rc) {
3019 ALOGE("%s: On-the-fly buffer registration failed %d",
3020 __func__, rc);
3021 return rc;
3022 }
3023
3024 index = mMemory.getMatchBufIndex((void*)buffer);
3025 if (index < 0) {
3026 ALOGE("%s: Could not find object among registered buffers",__func__);
3027 return DEAD_OBJECT;
3028 }
3029 }
3030 CDBG("%s: buffer index %d, frameNumber: %u", __func__, index, frameNumber);
3031
3032 rc = mMemory.markFrameNumber((uint32_t)index, frameNumber);
3033
3034 // Start postprocessor
3035 startPostProc(reproc_cfg);
3036
3037 // Queue jpeg settings
3038 rc = queueJpegSetting((uint32_t)index, metadata);
3039
3040 if (pInputBuffer == NULL) {
3041 Mutex::Autolock lock(mFreeBuffersLock);
3042 uint32_t bufIdx;
3043 if (mFreeBufferList.empty()) {
3044 rc = mYuvMemory->allocateOne(mFrameLen);
3045 if (rc < 0) {
3046 ALOGE("%s: Failed to allocate heap buffer. Fatal", __func__);
3047 return rc;
3048 } else {
3049 bufIdx = (uint32_t)rc;
3050 }
3051 } else {
3052 List<uint32_t>::iterator it = mFreeBufferList.begin();
3053 bufIdx = *it;
3054 mFreeBufferList.erase(it);
3055 }
3056 mYuvMemory->markFrameNumber(bufIdx, frameNumber);
3057 mStreams[0]->bufDone(bufIdx);
3058 } else {
3059 qcamera_fwk_input_pp_data_t *src_frame = NULL;
3060 src_frame = (qcamera_fwk_input_pp_data_t *)calloc(1,
3061 sizeof(qcamera_fwk_input_pp_data_t));
3062 if (src_frame == NULL) {
3063 ALOGE("%s: No memory for src frame", __func__);
3064 return NO_MEMORY;
3065 }
3066 rc = setFwkInputPPData(src_frame, pInputBuffer, &reproc_cfg, metadata,
3067 NULL /*fwk output buffer*/, frameNumber);
3068 if (NO_ERROR != rc) {
3069 ALOGE("%s: Error %d while setting framework input PP data", __func__, rc);
3070 free(src_frame);
3071 return rc;
3072 }
3073 CDBG_HIGH("%s: Post-process started", __func__);
3074 CDBG_HIGH("%s: Issue call to reprocess", __func__);
3075 m_postprocessor.processData(src_frame);
3076 }
3077 return rc;
3078 }
3079
3080
3081 /*===========================================================================
3082 * FUNCTION : dataNotifyCB
3083 *
3084 * DESCRIPTION: Channel Level callback used for super buffer data notify.
3085 * This function is registered with mm-camera-interface to handle
3086 * data notify
3087 *
3088 * PARAMETERS :
3089 * @recvd_frame : stream frame received
3090 * userdata : user data ptr
3091 *
3092 * RETURN : none
3093 *==========================================================================*/
dataNotifyCB(mm_camera_super_buf_t * recvd_frame,void * userdata)3094 void QCamera3PicChannel::dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
3095 void *userdata)
3096 {
3097 ATRACE_CALL();
3098 CDBG("%s: E\n", __func__);
3099 QCamera3PicChannel *channel = (QCamera3PicChannel *)userdata;
3100
3101 if (channel == NULL) {
3102 ALOGE("%s: invalid channel pointer", __func__);
3103 return;
3104 }
3105
3106 if(channel->m_numStreams != 1) {
3107 ALOGE("%s: Error: Bug: This callback assumes one stream per channel",__func__);
3108 return;
3109 }
3110
3111
3112 if(channel->mStreams[0] == NULL) {
3113 ALOGE("%s: Error: Invalid Stream object",__func__);
3114 return;
3115 }
3116
3117 channel->QCamera3PicChannel::streamCbRoutine(recvd_frame, channel->mStreams[0]);
3118
3119 CDBG("%s: X\n", __func__);
3120 return;
3121 }
3122
3123 /*===========================================================================
3124 * FUNCTION : streamCbRoutine
3125 *
3126 * DESCRIPTION:
3127 *
3128 * PARAMETERS :
3129 * @super_frame : the super frame with filled buffer
3130 * @stream : stream on which the buffer was requested and filled
3131 *
3132 * RETURN : none
3133 *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)3134 void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
3135 QCamera3Stream *stream)
3136 {
3137 ATRACE_CALL();
3138 //TODO
3139 //Used only for getting YUV. Jpeg callback will be sent back from channel
3140 //directly to HWI. Refer to func jpegEvtHandle
3141
3142 //Got the yuv callback. Calling yuv callback handler in PostProc
3143 uint8_t frameIndex;
3144 mm_camera_super_buf_t* frame = NULL;
3145
3146 if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
3147 ALOGE("%s: Error with the stream callback", __func__);
3148 return;
3149 }
3150
3151 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
3152 CDBG("%s: recvd buf_idx: %u for further processing",
3153 __func__, (uint32_t)frameIndex);
3154 if(frameIndex >= mNumSnapshotBufs) {
3155 ALOGE("%s: Error, Invalid index for buffer",__func__);
3156 if(stream) {
3157 Mutex::Autolock lock(mFreeBuffersLock);
3158 mFreeBufferList.push_back(frameIndex);
3159 stream->bufDone(frameIndex);
3160 }
3161 return;
3162 }
3163
3164 frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
3165 if (frame == NULL) {
3166 ALOGE("%s: Error allocating memory to save received_frame structure.",
3167 __func__);
3168 if(stream) {
3169 Mutex::Autolock lock(mFreeBuffersLock);
3170 mFreeBufferList.push_back(frameIndex);
3171 stream->bufDone(frameIndex);
3172 }
3173 return;
3174 }
3175 *frame = *super_frame;
3176
3177 if (mYUVDump) {
3178 cam_dimension_t dim;
3179 memset(&dim, 0, sizeof(dim));
3180 stream->getFrameDimension(dim);
3181 cam_frame_len_offset_t offset;
3182 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
3183 stream->getFrameOffset(offset);
3184 dumpYUV(frame->bufs[0], dim, offset, 1);
3185 }
3186
3187 m_postprocessor.processData(frame);
3188 free(super_frame);
3189 return;
3190 }
3191
getStreamBufs(uint32_t len)3192 QCamera3StreamMem* QCamera3PicChannel::getStreamBufs(uint32_t len)
3193 {
3194 int rc = 0;
3195
3196 mYuvMemory = new QCamera3StreamMem(mCamera3Stream->max_buffers, false);
3197 if (!mYuvMemory) {
3198 ALOGE("%s: unable to create metadata memory", __func__);
3199 return NULL;
3200 }
3201 mFrameLen = len;
3202
3203 return mYuvMemory;
3204 }
3205
putStreamBufs()3206 void QCamera3PicChannel::putStreamBufs()
3207 {
3208 QCamera3ProcessingChannel::putStreamBufs();
3209
3210 mYuvMemory->deallocate();
3211 delete mYuvMemory;
3212 mYuvMemory = NULL;
3213 mFreeBufferList.clear();
3214 }
3215
queueJpegSetting(uint32_t index,metadata_buffer_t * metadata)3216 int32_t QCamera3PicChannel::queueJpegSetting(uint32_t index, metadata_buffer_t *metadata)
3217 {
3218 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
3219 jpeg_settings_t *settings =
3220 (jpeg_settings_t *)malloc(sizeof(jpeg_settings_t));
3221
3222 if (!settings) {
3223 ALOGE("%s: out of memory allocating jpeg_settings", __func__);
3224 return -ENOMEM;
3225 }
3226
3227 memset(settings, 0, sizeof(jpeg_settings_t));
3228
3229 settings->out_buf_index = index;
3230
3231 settings->jpeg_orientation = 0;
3232 IF_META_AVAILABLE(int32_t, orientation, CAM_INTF_META_JPEG_ORIENTATION, metadata) {
3233 settings->jpeg_orientation = *orientation;
3234 }
3235
3236 settings->jpeg_quality = 85;
3237 IF_META_AVAILABLE(uint32_t, quality1, CAM_INTF_META_JPEG_QUALITY, metadata) {
3238 settings->jpeg_quality = (uint8_t) *quality1;
3239 }
3240
3241 IF_META_AVAILABLE(uint32_t, quality2, CAM_INTF_META_JPEG_THUMB_QUALITY, metadata) {
3242 settings->jpeg_thumb_quality = (uint8_t) *quality2;
3243 }
3244
3245 IF_META_AVAILABLE(cam_dimension_t, dimension, CAM_INTF_META_JPEG_THUMB_SIZE, metadata) {
3246 settings->thumbnail_size = *dimension;
3247 }
3248
3249 settings->gps_timestamp_valid = 0;
3250 IF_META_AVAILABLE(int64_t, timestamp, CAM_INTF_META_JPEG_GPS_TIMESTAMP, metadata) {
3251 settings->gps_timestamp = *timestamp;
3252 settings->gps_timestamp_valid = 1;
3253 }
3254
3255 settings->gps_coordinates_valid = 0;
3256 IF_META_AVAILABLE(double, coordinates, CAM_INTF_META_JPEG_GPS_COORDINATES, metadata) {
3257 memcpy(settings->gps_coordinates, coordinates, 3*sizeof(double));
3258 settings->gps_coordinates_valid = 1;
3259 }
3260
3261 IF_META_AVAILABLE(uint8_t, proc_methods, CAM_INTF_META_JPEG_GPS_PROC_METHODS, metadata) {
3262 memset(settings->gps_processing_method, 0,
3263 sizeof(settings->gps_processing_method));
3264 strlcpy(settings->gps_processing_method, (const char *)proc_methods,
3265 sizeof(settings->gps_processing_method));
3266 }
3267
3268 // Image description
3269 const char *eepromVersion = hal_obj->getEepromVersionInfo();
3270 const uint32_t *ldafCalib = hal_obj->getLdafCalib();
3271 if ((eepromVersion && strlen(eepromVersion)) ||
3272 ldafCalib) {
3273 int len = 0;
3274 settings->image_desc_valid = true;
3275 if (eepromVersion && strlen(eepromVersion)) {
3276 len = snprintf(settings->image_desc, sizeof(settings->image_desc),
3277 "M:%s ", eepromVersion);
3278 }
3279 if (ldafCalib) {
3280 snprintf(settings->image_desc + len,
3281 sizeof(settings->image_desc) - len, "L:%u-%u",
3282 ldafCalib[0], ldafCalib[1]);
3283 }
3284 }
3285
3286 return m_postprocessor.processJpegSettingData(settings);
3287 }
3288
3289 /*===========================================================================
3290 * FUNCTION : overrideYuvSize
3291 *
3292 * DESCRIPTION: constructor of QCamera3ReprocessChannel
3293 *
3294 * PARAMETERS :
3295 * @width : new width
3296 * @height : new height
3297 *
3298 * RETURN : none
3299 *==========================================================================*/
overrideYuvSize(uint32_t width,uint32_t height)3300 void QCamera3PicChannel::overrideYuvSize(uint32_t width, uint32_t height)
3301 {
3302 mYuvWidth = width;
3303 mYuvHeight = height;
3304 }
3305
3306 /*===========================================================================
3307 * FUNCTION : getReprocessType
3308 *
3309 * DESCRIPTION: get the type of reprocess output supported by this channel
3310 *
3311 * PARAMETERS : NONE
3312 *
3313 * RETURN : reprocess_type_t : type of reprocess
3314 *==========================================================================*/
getReprocessType()3315 reprocess_type_t QCamera3PicChannel::getReprocessType()
3316 {
3317 /* a picture channel could either use the postprocessor for reprocess+jpeg
3318 or only for reprocess */
3319 reprocess_type_t expectedReprocess;
3320 if (mPostProcMask == CAM_QCOM_FEATURE_NONE || mInputBufferHint) {
3321 expectedReprocess = REPROCESS_TYPE_JPEG;
3322 } else {
3323 expectedReprocess = REPROCESS_TYPE_NONE;
3324 }
3325 CDBG_HIGH("%s: expectedReprocess from Pic Channel is %d", __func__, expectedReprocess);
3326 return expectedReprocess;
3327 }
3328
3329 /* Reprocess Channel methods */
3330
3331 /*===========================================================================
3332 * FUNCTION : QCamera3ReprocessChannel
3333 *
3334 * DESCRIPTION: constructor of QCamera3ReprocessChannel
3335 *
3336 * PARAMETERS :
3337 * @cam_handle : camera handle
3338 * @cam_ops : ptr to camera ops table
3339 * @pp_mask : post-proccess feature mask
3340 *
3341 * RETURN : none
3342 *==========================================================================*/
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)3343 QCamera3ReprocessChannel::QCamera3ReprocessChannel(uint32_t cam_handle,
3344 uint32_t channel_handle,
3345 mm_camera_ops_t *cam_ops,
3346 channel_cb_routine cb_routine,
3347 cam_padding_info_t *paddingInfo,
3348 uint32_t postprocess_mask,
3349 void *userData, void *ch_hdl) :
3350 /* In case of framework reprocessing, pproc and jpeg operations could be
3351 * parallelized by allowing 1 extra buffer for reprocessing output:
3352 * ch_hdl->getNumBuffers() + 1 */
3353 QCamera3Channel(cam_handle, channel_handle, cam_ops, cb_routine, paddingInfo,
3354 postprocess_mask, userData,
3355 ((QCamera3ProcessingChannel *)ch_hdl)->getNumBuffers()
3356 + (MAX_REPROCESS_PIPELINE_STAGES - 1)),
3357 inputChHandle(ch_hdl),
3358 mOfflineBuffersIndex(-1),
3359 mFrameLen(0),
3360 mReprocessType(REPROCESS_TYPE_NONE),
3361 m_pSrcChannel(NULL),
3362 m_pMetaChannel(NULL),
3363 mMemory(NULL),
3364 mGrallocMemory(0)
3365 {
3366 memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
3367 mOfflineBuffersIndex = mNumBuffers -1;
3368 mOfflineMetaIndex = (int32_t) (2*mNumBuffers -1);
3369 }
3370
3371
3372 /*===========================================================================
3373 * FUNCTION : QCamera3ReprocessChannel
3374 *
3375 * DESCRIPTION: constructor of QCamera3ReprocessChannel
3376 *
3377 * PARAMETERS :
3378 * @cam_handle : camera handle
3379 * @cam_ops : ptr to camera ops table
3380 * @pp_mask : post-proccess feature mask
3381 *
3382 * RETURN : none
3383 *==========================================================================*/
initialize(cam_is_type_t isType)3384 int32_t QCamera3ReprocessChannel::initialize(cam_is_type_t isType)
3385 {
3386 int32_t rc = NO_ERROR;
3387 mm_camera_channel_attr_t attr;
3388
3389 memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
3390 attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS;
3391 attr.max_unmatched_frames = 1;
3392
3393 m_handle = m_camOps->add_channel(m_camHandle,
3394 &attr,
3395 NULL,
3396 this);
3397 if (m_handle == 0) {
3398 ALOGE("%s: Add channel failed", __func__);
3399 return UNKNOWN_ERROR;
3400 }
3401
3402 mIsType = isType;
3403 return rc;
3404 }
3405
3406 /*===========================================================================
3407 * FUNCTION : registerBuffer
3408 *
3409 * DESCRIPTION: register streaming buffer to the channel object
3410 *
3411 * PARAMETERS :
3412 * @buffer : buffer to be registered
3413 * @isType : the image stabilization type for the buffer
3414 *
3415 * RETURN : int32_t type of status
3416 * NO_ERROR -- success
3417 * none-zero failure code
3418 *==========================================================================*/
registerBuffer(buffer_handle_t * buffer,cam_is_type_t isType)3419 int32_t QCamera3ReprocessChannel::registerBuffer(buffer_handle_t *buffer,
3420 cam_is_type_t isType)
3421 {
3422 ATRACE_CALL();
3423 int rc = 0;
3424 mIsType = isType;
3425 cam_stream_type_t streamType;
3426
3427 if (buffer == NULL) {
3428 ALOGE("%s: Error: Cannot register a NULL buffer", __func__);
3429 return BAD_VALUE;
3430 }
3431
3432 if ((uint32_t)mGrallocMemory.getCnt() > (mNumBuffers - 1)) {
3433 ALOGE("%s: Trying to register more buffers than initially requested",
3434 __func__);
3435 return BAD_VALUE;
3436 }
3437
3438 if (0 == m_numStreams) {
3439 rc = initialize(mIsType);
3440 if (rc != NO_ERROR) {
3441 ALOGE("%s: Couldn't initialize camera stream %d",
3442 __func__, rc);
3443 return rc;
3444 }
3445 }
3446
3447 streamType = mStreams[0]->getMyType();
3448 rc = mGrallocMemory.registerBuffer(buffer, streamType);
3449 if (ALREADY_EXISTS == rc) {
3450 return NO_ERROR;
3451 } else if (NO_ERROR != rc) {
3452 ALOGE("%s: Buffer %p couldn't be registered %d", __func__, buffer, rc);
3453 return rc;
3454 }
3455
3456 return rc;
3457 }
3458
3459 /*===========================================================================
3460 * FUNCTION : QCamera3ReprocessChannel
3461 *
3462 * DESCRIPTION: constructor of QCamera3ReprocessChannel
3463 *
3464 * PARAMETERS :
3465 * @cam_handle : camera handle
3466 * @cam_ops : ptr to camera ops table
3467 * @pp_mask : post-proccess feature mask
3468 *
3469 * RETURN : none
3470 *==========================================================================*/
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream * stream)3471 void QCamera3ReprocessChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
3472 QCamera3Stream *stream)
3473 {
3474 //Got the pproc data callback. Now send to jpeg encoding
3475 uint8_t frameIndex;
3476 uint32_t resultFrameNumber;
3477 mm_camera_super_buf_t* frame = NULL;
3478 QCamera3ProcessingChannel *obj = (QCamera3ProcessingChannel *)inputChHandle;
3479
3480 if(!super_frame) {
3481 ALOGE("%s: Invalid Super buffer",__func__);
3482 return;
3483 }
3484
3485 if(super_frame->num_bufs != 1) {
3486 ALOGE("%s: Multiple streams are not supported",__func__);
3487 return;
3488 }
3489 if(super_frame->bufs[0] == NULL ) {
3490 ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
3491 __func__);
3492 return;
3493 }
3494 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
3495
3496 if (mYUVDump) {
3497 cam_dimension_t dim;
3498 memset(&dim, 0, sizeof(dim));
3499 stream->getFrameDimension(dim);
3500 cam_frame_len_offset_t offset;
3501 memset(&offset, 0, sizeof(cam_frame_len_offset_t));
3502 stream->getFrameOffset(offset);
3503 dumpYUV(super_frame->bufs[0], dim, offset, 2);
3504 }
3505
3506 if (mReprocessType == REPROCESS_TYPE_JPEG) {
3507 resultFrameNumber = mMemory->getFrameNumber(frameIndex);
3508 frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
3509 if (frame == NULL) {
3510 ALOGE("%s: Error allocating memory to save received_frame structure.",
3511 __func__);
3512 if(stream) {
3513 stream->bufDone(frameIndex);
3514 }
3515 return;
3516 }
3517 CDBG("%s: bufIndex: %u recvd from post proc",
3518 __func__, (uint32_t)frameIndex);
3519 *frame = *super_frame;
3520
3521 /* Since reprocessing is done, send the callback to release the input buffer */
3522 if (mChannelCB) {
3523 mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
3524 }
3525 obj->m_postprocessor.processPPData(frame);
3526 } else {
3527 buffer_handle_t *resultBuffer;
3528 frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
3529 resultBuffer = (buffer_handle_t *)mGrallocMemory.getBufferHandle(frameIndex);
3530 resultFrameNumber = mGrallocMemory.getFrameNumber(frameIndex);
3531 int32_t rc = stream->bufRelease(frameIndex);
3532 if (NO_ERROR != rc) {
3533 ALOGE("%s: Error %d releasing stream buffer %d",
3534 __func__, rc, frameIndex);
3535 }
3536 rc = mGrallocMemory.unregisterBuffer(frameIndex);
3537 if (NO_ERROR != rc) {
3538 ALOGE("%s: Error %d unregistering stream buffer %d",
3539 __func__, rc, frameIndex);
3540 }
3541 obj->reprocessCbRoutine(resultBuffer, resultFrameNumber);
3542
3543 obj->m_postprocessor.releaseOfflineBuffers();
3544 qcamera_hal3_pp_data_t *pp_job = obj->m_postprocessor.dequeuePPJob(resultFrameNumber);
3545 if (pp_job != NULL) {
3546 obj->m_postprocessor.releasePPJobData(pp_job);
3547 }
3548 free(pp_job);
3549 }
3550 free(super_frame);
3551 return;
3552 }
3553
3554 /*===========================================================================
3555 * FUNCTION : getStreamBufs
3556 *
3557 * DESCRIPTION: register the buffers of the reprocess channel
3558 *
3559 * PARAMETERS : none
3560 *
3561 * RETURN : QCamera3StreamMem *
3562 *==========================================================================*/
getStreamBufs(uint32_t len)3563 QCamera3StreamMem* QCamera3ReprocessChannel::getStreamBufs(uint32_t len)
3564 {
3565 int rc = 0;
3566 if (mReprocessType == REPROCESS_TYPE_JPEG) {
3567 mMemory = new QCamera3StreamMem(mNumBuffers, false);
3568 if (!mMemory) {
3569 ALOGE("%s: unable to create reproc memory", __func__);
3570 return NULL;
3571 }
3572 mFrameLen = len;
3573 return mMemory;
3574 }
3575 return &mGrallocMemory;
3576 }
3577
3578 /*===========================================================================
3579 * FUNCTION : putStreamBufs
3580 *
3581 * DESCRIPTION: release the reprocess channel buffers
3582 *
3583 * PARAMETERS : none
3584 *
3585 * RETURN :
3586 *==========================================================================*/
putStreamBufs()3587 void QCamera3ReprocessChannel::putStreamBufs()
3588 {
3589 if (mReprocessType == REPROCESS_TYPE_JPEG) {
3590 mMemory->deallocate();
3591 delete mMemory;
3592 mMemory = NULL;
3593 mFreeBufferList.clear();
3594 } else {
3595 mGrallocMemory.unregisterBuffers();
3596 }
3597 }
3598
3599 /*===========================================================================
3600 * FUNCTION : ~QCamera3ReprocessChannel
3601 *
3602 * DESCRIPTION: destructor of QCamera3ReprocessChannel
3603 *
3604 * PARAMETERS : none
3605 *
3606 * RETURN : none
3607 *==========================================================================*/
~QCamera3ReprocessChannel()3608 QCamera3ReprocessChannel::~QCamera3ReprocessChannel()
3609 {
3610 if (m_bIsActive)
3611 stop();
3612
3613 for (uint32_t i = 0; i < m_numStreams; i++) {
3614 if (mStreams[i] != NULL) {
3615 delete mStreams[i];
3616 mStreams[i] = 0;
3617 }
3618 }
3619 if (m_handle) {
3620 m_camOps->delete_channel(m_camHandle, m_handle);
3621 ALOGE("%s: deleting channel %d", __func__, m_handle);
3622 m_handle = 0;
3623 }
3624 m_numStreams = 0;
3625 }
3626
3627 /*===========================================================================
3628 * FUNCTION : start
3629 *
3630 * DESCRIPTION: start reprocess channel.
3631 *
3632 * PARAMETERS :
3633 *
3634 * RETURN : int32_t type of status
3635 * NO_ERROR -- success
3636 * none-zero failure code
3637 *==========================================================================*/
start()3638 int32_t QCamera3ReprocessChannel::start()
3639 {
3640 ATRACE_CALL();
3641 int32_t rc = NO_ERROR;
3642
3643 rc = QCamera3Channel::start();
3644
3645 if (rc == NO_ERROR) {
3646 rc = m_camOps->start_channel(m_camHandle, m_handle);
3647
3648 // Check failure
3649 if (rc != NO_ERROR) {
3650 ALOGE("%s: start_channel failed %d", __func__, rc);
3651 QCamera3Channel::stop();
3652 }
3653 }
3654 return rc;
3655 }
3656
3657 /*===========================================================================
3658 * FUNCTION : stop
3659 *
3660 * DESCRIPTION: stop reprocess channel.
3661 *
3662 * PARAMETERS : none
3663 *
3664 * RETURN : int32_t type of status
3665 * NO_ERROR -- success
3666 * none-zero failure code
3667 *==========================================================================*/
stop()3668 int32_t QCamera3ReprocessChannel::stop()
3669 {
3670 ATRACE_CALL();
3671 int32_t rc = NO_ERROR;
3672
3673 rc = QCamera3Channel::stop();
3674
3675 rc != m_camOps->stop_channel(m_camHandle, m_handle);
3676
3677 unmapOfflineBuffers(true);
3678
3679 return rc;
3680 }
3681
3682 /*===========================================================================
3683 * FUNCTION : getStreamBySrcHandle
3684 *
3685 * DESCRIPTION: find reprocess stream by its source stream handle
3686 *
3687 * PARAMETERS :
3688 * @srcHandle : source stream handle
3689 *
3690 * RETURN : ptr to reprocess stream if found. NULL if not found
3691 *==========================================================================*/
getStreamBySrcHandle(uint32_t srcHandle)3692 QCamera3Stream * QCamera3ReprocessChannel::getStreamBySrcHandle(uint32_t srcHandle)
3693 {
3694 QCamera3Stream *pStream = NULL;
3695
3696 for (uint32_t i = 0; i < m_numStreams; i++) {
3697 if (mSrcStreamHandles[i] == srcHandle) {
3698 pStream = mStreams[i];
3699 break;
3700 }
3701 }
3702 return pStream;
3703 }
3704
3705 /*===========================================================================
3706 * FUNCTION : getSrcStreamBySrcHandle
3707 *
3708 * DESCRIPTION: find source stream by source stream handle
3709 *
3710 * PARAMETERS :
3711 * @srcHandle : source stream handle
3712 *
3713 * RETURN : ptr to reprocess stream if found. NULL if not found
3714 *==========================================================================*/
getSrcStreamBySrcHandle(uint32_t srcHandle)3715 QCamera3Stream * QCamera3ReprocessChannel::getSrcStreamBySrcHandle(uint32_t srcHandle)
3716 {
3717 QCamera3Stream *pStream = NULL;
3718
3719 if (NULL == m_pSrcChannel) {
3720 return NULL;
3721 }
3722
3723 for (uint32_t i = 0; i < m_numStreams; i++) {
3724 if (mSrcStreamHandles[i] == srcHandle) {
3725 pStream = m_pSrcChannel->getStreamByIndex(i);
3726 break;
3727 }
3728 }
3729 return pStream;
3730 }
3731
3732 /*===========================================================================
3733 * FUNCTION : unmapOfflineBuffers
3734 *
3735 * DESCRIPTION: Unmaps offline buffers
3736 *
3737 * PARAMETERS : none
3738 *
3739 * RETURN : int32_t type of status
3740 * NO_ERROR -- success
3741 * none-zero failure code
3742 *==========================================================================*/
unmapOfflineBuffers(bool all)3743 int32_t QCamera3ReprocessChannel::unmapOfflineBuffers(bool all)
3744 {
3745 int rc = NO_ERROR;
3746 if (!mOfflineBuffers.empty()) {
3747 QCamera3Stream *stream = NULL;
3748 List<OfflineBuffer>::iterator it = mOfflineBuffers.begin();
3749 for (; it != mOfflineBuffers.end(); it++) {
3750 stream = (*it).stream;
3751 if (NULL != stream) {
3752 rc = stream->unmapBuf((*it).type,
3753 (*it).index,
3754 -1);
3755 if (NO_ERROR != rc) {
3756 ALOGE("%s: Error during offline buffer unmap %d",
3757 __func__, rc);
3758 }
3759 CDBG("%s: Unmapped buffer with index %d", __func__, (*it).index);
3760 }
3761 if (!all) {
3762 mOfflineBuffers.erase(it);
3763 break;
3764 }
3765 }
3766 if (all) {
3767 mOfflineBuffers.clear();
3768 }
3769 }
3770
3771 if (!mOfflineMetaBuffers.empty()) {
3772 QCamera3Stream *stream = NULL;
3773 List<OfflineBuffer>::iterator it = mOfflineMetaBuffers.begin();
3774 for (; it != mOfflineMetaBuffers.end(); it++) {
3775 stream = (*it).stream;
3776 if (NULL != stream) {
3777 rc = stream->unmapBuf((*it).type,
3778 (*it).index,
3779 -1);
3780 if (NO_ERROR != rc) {
3781 ALOGE("%s: Error during offline buffer unmap %d",
3782 __func__, rc);
3783 }
3784 CDBG("%s: Unmapped meta buffer with index %d", __func__, (*it).index);
3785 }
3786 if (!all) {
3787 mOfflineMetaBuffers.erase(it);
3788 break;
3789 }
3790 }
3791 if (all) {
3792 mOfflineMetaBuffers.clear();
3793 }
3794 }
3795 return rc;
3796 }
3797
3798 /*===========================================================================
3799 * FUNCTION : bufDone
3800 *
3801 * DESCRIPTION: Return reprocess stream buffer to free buffer list.
3802 * Note that this function doesn't queue buffer back to kernel.
3803 * It's up to doReprocessOffline to do that instead.
3804 * PARAMETERS :
3805 * @recvd_frame : stream buf frame to be returned
3806 *
3807 * RETURN : int32_t type of status
3808 * NO_ERROR -- success
3809 * none-zero failure code
3810 *==========================================================================*/
bufDone(mm_camera_super_buf_t * recvd_frame)3811 int32_t QCamera3ReprocessChannel::bufDone(mm_camera_super_buf_t *recvd_frame)
3812 {
3813 int rc = NO_ERROR;
3814 if (recvd_frame && recvd_frame->num_bufs == 1) {
3815 Mutex::Autolock lock(mFreeBuffersLock);
3816 uint32_t buf_idx = recvd_frame->bufs[0]->buf_idx;
3817 mFreeBufferList.push_back(buf_idx);
3818
3819 } else {
3820 ALOGE("%s: Fatal. Not supposed to be here", __func__);
3821 rc = BAD_VALUE;
3822 }
3823
3824 return rc;
3825 }
3826
3827 /*===========================================================================
3828 * FUNCTION : overrideMetadata
3829 *
3830 * DESCRIPTION: Override metadata entry such as rotation, crop, and CDS info.
3831 *
3832 * PARAMETERS :
3833 * @frame : input frame from source stream
3834 * meta_buffer: metadata buffer
3835 * @metadata : corresponding metadata
3836 * @fwk_frame :
3837 *
3838 * RETURN : int32_t type of status
3839 * NO_ERROR -- success
3840 * none-zero failure code
3841 *==========================================================================*/
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)3842 int32_t QCamera3ReprocessChannel::overrideMetadata(qcamera_hal3_pp_buffer_t *pp_buffer,
3843 mm_camera_buf_def_t *meta_buffer, jpeg_settings_t *jpeg_settings,
3844 qcamera_fwk_input_pp_data_t &fwk_frame)
3845 {
3846 int32_t rc = NO_ERROR;
3847 QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
3848 if ((NULL == meta_buffer) || (NULL == pp_buffer) || (NULL == pp_buffer->input) ||
3849 (NULL == hal_obj)) {
3850 return BAD_VALUE;
3851 }
3852
3853 metadata_buffer_t *meta = (metadata_buffer_t *)meta_buffer->buffer;
3854 mm_camera_super_buf_t *frame = pp_buffer->input;
3855 if (NULL == meta) {
3856 return BAD_VALUE;
3857 }
3858
3859 for (uint32_t i = 0; i < frame->num_bufs; i++) {
3860 QCamera3Stream *pStream = getStreamBySrcHandle(frame->bufs[i]->stream_id);
3861 QCamera3Stream *pSrcStream = getSrcStreamBySrcHandle(frame->bufs[i]->stream_id);
3862
3863 if (pStream != NULL && pSrcStream != NULL) {
3864 if (jpeg_settings) {
3865 // Find rotation info for reprocess stream
3866 cam_rotation_info_t rotation_info;
3867 memset(&rotation_info, 0, sizeof(rotation_info));
3868 if (jpeg_settings->jpeg_orientation == 0) {
3869 rotation_info.rotation = ROTATE_0;
3870 } else if (jpeg_settings->jpeg_orientation == 90) {
3871 rotation_info.rotation = ROTATE_90;
3872 } else if (jpeg_settings->jpeg_orientation == 180) {
3873 rotation_info.rotation = ROTATE_180;
3874 } else if (jpeg_settings->jpeg_orientation == 270) {
3875 rotation_info.rotation = ROTATE_270;
3876 }
3877 rotation_info.streamId = mStreams[0]->getMyServerID();
3878 ADD_SET_PARAM_ENTRY_TO_BATCH(meta, CAM_INTF_PARM_ROTATION, rotation_info);
3879 }
3880
3881 // Find and insert crop info for reprocess stream
3882 IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) {
3883 if (MAX_NUM_STREAMS > crop_data->num_of_streams) {
3884 for (int j = 0; j < crop_data->num_of_streams; j++) {
3885 if (crop_data->crop_info[j].stream_id ==
3886 pSrcStream->getMyServerID()) {
3887
3888 // Store crop/roi information for offline reprocess
3889 // in the reprocess stream slot
3890 crop_data->crop_info[crop_data->num_of_streams].crop =
3891 crop_data->crop_info[j].crop;
3892 crop_data->crop_info[crop_data->num_of_streams].roi_map =
3893 crop_data->crop_info[j].roi_map;
3894 crop_data->crop_info[crop_data->num_of_streams].stream_id =
3895 mStreams[0]->getMyServerID();
3896 crop_data->num_of_streams++;
3897
3898 CDBG("%s: Reprocess stream server id: %d",
3899 __func__, mStreams[0]->getMyServerID());
3900 CDBG("%s: Found offline reprocess crop %dx%d %dx%d",
3901 __func__,
3902 crop_data->crop_info[j].crop.left,
3903 crop_data->crop_info[j].crop.top,
3904 crop_data->crop_info[j].crop.width,
3905 crop_data->crop_info[j].crop.height);
3906 CDBG("%s: Found offline reprocess roimap %dx%d %dx%d",
3907 __func__,
3908 crop_data->crop_info[j].roi_map.left,
3909 crop_data->crop_info[j].roi_map.top,
3910 crop_data->crop_info[j].roi_map.width,
3911 crop_data->crop_info[j].roi_map.height);
3912
3913 break;
3914 }
3915 }
3916 } else {
3917 ALOGE("%s: No space to add reprocess stream crop/roi information",
3918 __func__);
3919 }
3920 }
3921
3922 IF_META_AVAILABLE(cam_cds_data_t, cdsInfo, CAM_INTF_META_CDS_DATA, meta) {
3923 uint8_t cnt = cdsInfo->num_of_streams;
3924 if (cnt <= MAX_NUM_STREAMS) {
3925 cam_stream_cds_info_t repro_cds_info;
3926 memset(&repro_cds_info, 0, sizeof(repro_cds_info));
3927 repro_cds_info.stream_id = mStreams[0]->getMyServerID();
3928 for (size_t i = 0; i < cnt; i++) {
3929 if (cdsInfo->cds_info[i].stream_id ==
3930 pSrcStream->getMyServerID()) {
3931 repro_cds_info.cds_enable =
3932 cdsInfo->cds_info[i].cds_enable;
3933 break;
3934 }
3935 }
3936 cdsInfo->num_of_streams = 1;
3937 cdsInfo->cds_info[0] = repro_cds_info;
3938 } else {
3939 ALOGE("%s: No space to add reprocess stream cds information",
3940 __func__);
3941 }
3942 }
3943
3944 fwk_frame.input_buffer = *frame->bufs[i];
3945 fwk_frame.metadata_buffer = *meta_buffer;
3946 fwk_frame.output_buffer = pp_buffer->output;
3947 break;
3948 } else {
3949 ALOGE("%s: Source/Re-process streams are invalid", __func__);
3950 rc |= BAD_VALUE;
3951 }
3952 }
3953
3954 return rc;
3955 }
3956
3957 /*===========================================================================
3958 * FUNCTION : overrideFwkMetadata
3959 *
3960 * DESCRIPTION: Override frameworks metadata such as crop, and CDS data.
3961 *
3962 * PARAMETERS :
3963 * @frame : input frame for reprocessing
3964 *
3965 * RETURN : int32_t type of status
3966 * NO_ERROR -- success
3967 * none-zero failure code
3968 *==========================================================================*/
overrideFwkMetadata(qcamera_fwk_input_pp_data_t * frame)3969 int32_t QCamera3ReprocessChannel::overrideFwkMetadata(
3970 qcamera_fwk_input_pp_data_t *frame)
3971 {
3972 if (NULL == frame) {
3973 ALOGE("%s: Incorrect input frame", __func__);
3974 return BAD_VALUE;
3975 }
3976
3977
3978 if (NULL == frame->metadata_buffer.buffer) {
3979 ALOGE("%s: No metadata available", __func__);
3980 return BAD_VALUE;
3981 }
3982
3983 // Find and insert crop info for reprocess stream
3984 metadata_buffer_t *meta = (metadata_buffer_t *) frame->metadata_buffer.buffer;
3985 IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) {
3986 if (1 == crop_data->num_of_streams) {
3987 // Store crop/roi information for offline reprocess
3988 // in the reprocess stream slot
3989 crop_data->crop_info[crop_data->num_of_streams].crop =
3990 crop_data->crop_info[0].crop;
3991 crop_data->crop_info[crop_data->num_of_streams].roi_map =
3992 crop_data->crop_info[0].roi_map;
3993 crop_data->crop_info[crop_data->num_of_streams].stream_id =
3994 mStreams[0]->getMyServerID();
3995 crop_data->num_of_streams++;
3996
3997 CDBG("%s: Reprocess stream server id: %d",
3998 __func__, mStreams[0]->getMyServerID());
3999 CDBG("%s: Found offline reprocess crop %dx%d %dx%d", __func__,
4000 crop_data->crop_info[0].crop.left,
4001 crop_data->crop_info[0].crop.top,
4002 crop_data->crop_info[0].crop.width,
4003 crop_data->crop_info[0].crop.height);
4004 CDBG("%s: Found offline reprocess roi map %dx%d %dx%d", __func__,
4005 crop_data->crop_info[0].roi_map.left,
4006 crop_data->crop_info[0].roi_map.top,
4007 crop_data->crop_info[0].roi_map.width,
4008 crop_data->crop_info[0].roi_map.height);
4009 } else {
4010 ALOGE("%s: Incorrect number of offline crop data entries %d",
4011 __func__,
4012 crop_data->num_of_streams);
4013 return BAD_VALUE;
4014 }
4015 } else {
4016 CDBG_HIGH("%s: Crop data not present", __func__);
4017 }
4018
4019 IF_META_AVAILABLE(cam_cds_data_t, cdsInfo, CAM_INTF_META_CDS_DATA, meta) {
4020 if (1 == cdsInfo->num_of_streams) {
4021 cdsInfo->cds_info[0].stream_id = mStreams[0]->getMyServerID();
4022 } else {
4023 ALOGE("%s: Incorrect number of offline cds info entries %d",
4024 __func__, cdsInfo->num_of_streams);
4025 return BAD_VALUE;
4026 }
4027 }
4028
4029 return NO_ERROR;
4030 }
4031
4032 /*===========================================================================
4033 * FUNCTION : doReprocessOffline
4034 *
4035 * DESCRIPTION: request to do a reprocess on the frame
4036 *
4037 * PARAMETERS :
4038 * @frame : input frame for reprocessing
4039 *
4040 * RETURN : int32_t type of status
4041 * NO_ERROR -- success
4042 * none-zero failure code
4043 *==========================================================================*/
doReprocessOffline(qcamera_fwk_input_pp_data_t * frame)4044 int32_t QCamera3ReprocessChannel::doReprocessOffline(qcamera_fwk_input_pp_data_t *frame)
4045 {
4046 int32_t rc = 0;
4047 int index;
4048 OfflineBuffer mappedBuffer;
4049
4050 if (m_numStreams < 1) {
4051 ALOGE("%s: No reprocess stream is created", __func__);
4052 return -1;
4053 }
4054
4055 if (NULL == frame) {
4056 ALOGE("%s: Incorrect input frame", __func__);
4057 return BAD_VALUE;
4058 }
4059
4060 if (NULL == frame->metadata_buffer.buffer) {
4061 ALOGE("%s: No metadata available", __func__);
4062 return BAD_VALUE;
4063 }
4064
4065 if (NULL == frame->input_buffer.buffer) {
4066 ALOGE("%s: No input buffer available", __func__);
4067 return BAD_VALUE;
4068 }
4069
4070 if ((0 == m_numStreams) || (NULL == mStreams[0])) {
4071 ALOGE("%s: Reprocess stream not initialized!", __func__);
4072 return NO_INIT;
4073 }
4074
4075 QCamera3Stream *pStream = mStreams[0];
4076
4077 //qbuf the output buffer if it was allocated by the framework
4078 if (mReprocessType != REPROCESS_TYPE_JPEG && frame->output_buffer != NULL) {
4079 if(!m_bIsActive) {
4080 rc = registerBuffer(frame->output_buffer, mIsType);
4081 if (NO_ERROR != rc) {
4082 ALOGE("%s: On-the-fly buffer registration failed %d",
4083 __func__, rc);
4084 return rc;
4085 }
4086
4087 rc = start();
4088 if (NO_ERROR != rc) {
4089 return rc;
4090 }
4091 }
4092 index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer);
4093 if(index < 0) {
4094 rc = registerBuffer(frame->output_buffer, mIsType);
4095 if (NO_ERROR != rc) {
4096 ALOGE("%s: On-the-fly buffer registration failed %d",
4097 __func__, rc);
4098 return rc;
4099 }
4100
4101 index = mGrallocMemory.getMatchBufIndex((void*)frame->output_buffer);
4102 if (index < 0) {
4103 ALOGE("%s: Could not find object among registered buffers",
4104 __func__);
4105 return DEAD_OBJECT;
4106 }
4107 }
4108 rc = pStream->bufDone(index);
4109 if(rc != NO_ERROR) {
4110 ALOGE("%s: Failed to Q new buffer to stream",__func__);
4111 return rc;
4112 }
4113 rc = mGrallocMemory.markFrameNumber(index, frame->frameNumber);
4114
4115 } else if (mReprocessType == REPROCESS_TYPE_JPEG) {
4116 Mutex::Autolock lock(mFreeBuffersLock);
4117 uint32_t bufIdx;
4118 if (mFreeBufferList.empty()) {
4119 rc = mMemory->allocateOne(mFrameLen);
4120 if (rc < 0) {
4121 ALOGE("%s: Failed allocating heap buffer. Fatal", __func__);
4122 return BAD_VALUE;
4123 } else {
4124 bufIdx = (uint32_t)rc;
4125 }
4126 } else {
4127 bufIdx = *(mFreeBufferList.begin());
4128 mFreeBufferList.erase(mFreeBufferList.begin());
4129 }
4130
4131 mMemory->markFrameNumber(bufIdx, frame->frameNumber);
4132 rc = pStream->bufDone(bufIdx);
4133 if (rc != NO_ERROR) {
4134 ALOGE("%s: Failed to queue new buffer to stream", __func__);
4135 return rc;
4136 }
4137 }
4138
4139 int32_t max_idx = (int32_t) (mNumBuffers - 1);
4140 //loop back the indices if max burst count reached
4141 if (mOfflineBuffersIndex == max_idx) {
4142 mOfflineBuffersIndex = -1;
4143 }
4144 uint32_t buf_idx = (uint32_t)(mOfflineBuffersIndex + 1);
4145 rc = pStream->mapBuf(
4146 CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4147 buf_idx, -1,
4148 frame->input_buffer.fd, frame->input_buffer.frame_len);
4149 if (NO_ERROR == rc) {
4150 mappedBuffer.index = buf_idx;
4151 mappedBuffer.stream = pStream;
4152 mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF;
4153 mOfflineBuffers.push_back(mappedBuffer);
4154 mOfflineBuffersIndex = (int32_t)buf_idx;
4155 CDBG("%s: Mapped buffer with index %d", __func__, mOfflineBuffersIndex);
4156 }
4157
4158 max_idx = (int32_t) ((mNumBuffers * 2) - 1);
4159 //loop back the indices if max burst count reached
4160 if (mOfflineMetaIndex == max_idx) {
4161 mOfflineMetaIndex = (int32_t) (mNumBuffers - 1);
4162 }
4163 uint32_t meta_buf_idx = (uint32_t)(mOfflineMetaIndex + 1);
4164 rc |= pStream->mapBuf(
4165 CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF,
4166 meta_buf_idx, -1,
4167 frame->metadata_buffer.fd, frame->metadata_buffer.frame_len);
4168 if (NO_ERROR == rc) {
4169 mappedBuffer.index = meta_buf_idx;
4170 mappedBuffer.stream = pStream;
4171 mappedBuffer.type = CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF;
4172 mOfflineMetaBuffers.push_back(mappedBuffer);
4173 mOfflineMetaIndex = (int32_t)meta_buf_idx;
4174 CDBG("%s: Mapped meta buffer with index %d", __func__, mOfflineMetaIndex);
4175 }
4176
4177 if (rc == NO_ERROR) {
4178 cam_stream_parm_buffer_t param;
4179 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t));
4180 param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
4181 param.reprocess.buf_index = buf_idx;
4182 param.reprocess.frame_idx = frame->input_buffer.frame_idx;
4183 param.reprocess.meta_present = 1;
4184 param.reprocess.meta_buf_index = meta_buf_idx;
4185 rc = pStream->setParameter(param);
4186 if (rc != NO_ERROR) {
4187 ALOGE("%s: stream setParameter for reprocess failed", __func__);
4188 }
4189 } else {
4190 ALOGE("%s: Input buffer memory map failed: %d", __func__, rc);
4191 }
4192
4193 return rc;
4194 }
4195
4196 /*===========================================================================
4197 * FUNCTION : doReprocess
4198 *
4199 * DESCRIPTION: request to do a reprocess on the frame
4200 *
4201 * PARAMETERS :
4202 * @buf_fd : fd to the input buffer that needs reprocess
4203 * @buf_lenght : length of the input buffer
4204 * @ret_val : result of reprocess.
4205 * Example: Could be faceID in case of register face image.
4206 * @meta_frame : metadata frame.
4207 *
4208 * RETURN : int32_t type of status
4209 * NO_ERROR -- success
4210 * none-zero failure code
4211 *==========================================================================*/
doReprocess(int buf_fd,size_t buf_length,int32_t & ret_val,mm_camera_super_buf_t * meta_frame)4212 int32_t QCamera3ReprocessChannel::doReprocess(int buf_fd, size_t buf_length,
4213 int32_t &ret_val, mm_camera_super_buf_t *meta_frame)
4214 {
4215 int32_t rc = 0;
4216 if (m_numStreams < 1) {
4217 ALOGE("%s: No reprocess stream is created", __func__);
4218 return -1;
4219 }
4220 if (meta_frame == NULL) {
4221 ALOGE("%s: Did not get corresponding metadata in time", __func__);
4222 return -1;
4223 }
4224
4225 uint8_t buf_idx = 0;
4226 for (uint32_t i = 0; i < m_numStreams; i++) {
4227 rc = mStreams[i]->mapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4228 buf_idx, -1,
4229 buf_fd, buf_length);
4230
4231 if (rc == NO_ERROR) {
4232 cam_stream_parm_buffer_t param;
4233 memset(¶m, 0, sizeof(cam_stream_parm_buffer_t));
4234 param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
4235 param.reprocess.buf_index = buf_idx;
4236 param.reprocess.meta_present = 1;
4237 param.reprocess.meta_stream_handle = m_pMetaChannel->mStreams[0]->getMyServerID();
4238 param.reprocess.meta_buf_index = meta_frame->bufs[0]->buf_idx;
4239 rc = mStreams[i]->setParameter(param);
4240 if (rc == NO_ERROR) {
4241 ret_val = param.reprocess.ret_val;
4242 }
4243 mStreams[i]->unmapBuf(CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
4244 buf_idx, -1);
4245 }
4246 }
4247 return rc;
4248 }
4249
4250 /*===========================================================================
4251 * FUNCTION : addReprocStreamsFromSource
4252 *
4253 * DESCRIPTION: add reprocess streams from input source channel
4254 *
4255 * PARAMETERS :
4256 * @config : pp feature configuration
4257 * @src_config : source reprocess configuration
4258 * @isType : type of image stabilization required on this stream
4259 * @pMetaChannel : ptr to metadata channel to get corresp. metadata
4260 *
4261 *
4262 * RETURN : int32_t type of status
4263 * NO_ERROR -- success
4264 * none-zero failure code
4265 *==========================================================================*/
addReprocStreamsFromSource(cam_pp_feature_config_t & pp_config,const reprocess_config_t & src_config,cam_is_type_t is_type,QCamera3Channel * pMetaChannel)4266 int32_t QCamera3ReprocessChannel::addReprocStreamsFromSource(cam_pp_feature_config_t &pp_config,
4267 const reprocess_config_t &src_config , cam_is_type_t is_type,
4268 QCamera3Channel *pMetaChannel)
4269 {
4270 int32_t rc = 0;
4271 cam_stream_reproc_config_t reprocess_config;
4272 cam_stream_type_t streamType;
4273
4274 cam_dimension_t streamDim = src_config.output_stream_dim;
4275
4276 if (NULL != src_config.src_channel) {
4277 QCamera3Stream *pSrcStream = src_config.src_channel->getStreamByIndex(0);
4278 if (pSrcStream == NULL) {
4279 ALOGE("%s: source channel doesn't have a stream", __func__);
4280 return BAD_VALUE;
4281 }
4282 mSrcStreamHandles[m_numStreams] = pSrcStream->getMyHandle();
4283 }
4284
4285 streamType = CAM_STREAM_TYPE_OFFLINE_PROC;
4286 reprocess_config.pp_type = CAM_OFFLINE_REPROCESS_TYPE;
4287
4288 reprocess_config.offline.input_fmt = src_config.stream_format;
4289 reprocess_config.offline.input_dim = src_config.input_stream_dim;
4290 reprocess_config.offline.input_buf_planes.plane_info =
4291 src_config.input_stream_plane_info.plane_info;
4292 reprocess_config.offline.num_of_bufs = (uint8_t)mNumBuffers;
4293 reprocess_config.offline.input_type = src_config.stream_type;
4294
4295 reprocess_config.pp_feature_config = pp_config;
4296 QCamera3Stream *pStream = new QCamera3Stream(m_camHandle,
4297 m_handle,
4298 m_camOps,
4299 mPaddingInfo,
4300 (QCamera3Channel*)this);
4301 if (pStream == NULL) {
4302 ALOGE("%s: No mem for Stream", __func__);
4303 return NO_MEMORY;
4304 }
4305
4306 rc = pStream->init(streamType, src_config.stream_format,
4307 streamDim, ROTATE_0, &reprocess_config,
4308 (uint8_t)mNumBuffers,
4309 reprocess_config.pp_feature_config.feature_mask,
4310 is_type,
4311 0,/* batchSize */
4312 QCamera3Channel::streamCbRoutine, this);
4313
4314 if (rc == 0) {
4315 mStreams[m_numStreams] = pStream;
4316 m_numStreams++;
4317 } else {
4318 ALOGE("%s: failed to create reprocess stream", __func__);
4319 delete pStream;
4320 }
4321
4322 if (rc == NO_ERROR) {
4323 m_pSrcChannel = src_config.src_channel;
4324 m_pMetaChannel = pMetaChannel;
4325 mReprocessType = src_config.reprocess_type;
4326 CDBG("%s: mReprocessType is %d", __func__, mReprocessType);
4327 }
4328 if(m_camOps->request_super_buf(m_camHandle,m_handle,1,0) < 0) {
4329 ALOGE("%s: Request for super buffer failed",__func__);
4330 }
4331 return rc;
4332 }
4333
4334 /* QCamera3SupportChannel methods */
4335
4336 cam_dimension_t QCamera3SupportChannel::kDim = {640, 480};
4337
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)4338 QCamera3SupportChannel::QCamera3SupportChannel(uint32_t cam_handle,
4339 uint32_t channel_handle,
4340 mm_camera_ops_t *cam_ops,
4341 cam_padding_info_t *paddingInfo,
4342 uint32_t postprocess_mask,
4343 cam_stream_type_t streamType,
4344 cam_dimension_t *dim,
4345 cam_format_t streamFormat,
4346 void *userData, uint32_t numBuffers) :
4347 QCamera3Channel(cam_handle, channel_handle, cam_ops,
4348 NULL, paddingInfo, postprocess_mask,
4349 userData, numBuffers),
4350 mMemory(NULL)
4351 {
4352 memcpy(&mDim, dim, sizeof(cam_dimension_t));
4353 mStreamType = streamType;
4354 mStreamFormat = streamFormat;
4355 }
4356
~QCamera3SupportChannel()4357 QCamera3SupportChannel::~QCamera3SupportChannel()
4358 {
4359 if (m_bIsActive)
4360 stop();
4361
4362 if (mMemory) {
4363 mMemory->deallocate();
4364 delete mMemory;
4365 mMemory = NULL;
4366 }
4367 }
4368
initialize(cam_is_type_t isType)4369 int32_t QCamera3SupportChannel::initialize(cam_is_type_t isType)
4370 {
4371 int32_t rc;
4372
4373 if (mMemory || m_numStreams > 0) {
4374 ALOGE("%s: metadata channel already initialized", __func__);
4375 return -EINVAL;
4376 }
4377
4378 mIsType = isType;
4379 rc = QCamera3Channel::addStream(mStreamType,
4380 mStreamFormat, mDim, ROTATE_0, MIN_STREAMING_BUFFER_NUM,
4381 mPostProcMask, mIsType);
4382 if (rc < 0) {
4383 ALOGE("%s: addStream failed", __func__);
4384 }
4385 return rc;
4386 }
4387
request(buffer_handle_t *,uint32_t)4388 int32_t QCamera3SupportChannel::request(buffer_handle_t * /*buffer*/,
4389 uint32_t /*frameNumber*/)
4390 {
4391 return NO_ERROR;
4392 }
4393
streamCbRoutine(mm_camera_super_buf_t * super_frame,QCamera3Stream *)4394 void QCamera3SupportChannel::streamCbRoutine(
4395 mm_camera_super_buf_t *super_frame,
4396 QCamera3Stream * /*stream*/)
4397 {
4398 if (super_frame == NULL || super_frame->num_bufs != 1) {
4399 ALOGE("%s: super_frame is not valid", __func__);
4400 return;
4401 }
4402 bufDone(super_frame);
4403 free(super_frame);
4404 }
4405
getStreamBufs(uint32_t len)4406 QCamera3StreamMem* QCamera3SupportChannel::getStreamBufs(uint32_t len)
4407 {
4408 int rc;
4409 mMemory = new QCamera3StreamMem(mNumBuffers);
4410 if (!mMemory) {
4411 ALOGE("%s: unable to create heap memory", __func__);
4412 return NULL;
4413 }
4414 rc = mMemory->allocateAll(len);
4415 if (rc < 0) {
4416 ALOGE("%s: unable to allocate heap memory", __func__);
4417 delete mMemory;
4418 mMemory = NULL;
4419 return NULL;
4420 }
4421 return mMemory;
4422 }
4423
putStreamBufs()4424 void QCamera3SupportChannel::putStreamBufs()
4425 {
4426 mMemory->deallocate();
4427 delete mMemory;
4428 mMemory = NULL;
4429 }
4430
4431 }; // namespace qcamera
4432