diff options
| author | Shuzhen Wang <shuzhenw@codeaurora.org> | 2013-10-03 18:30:44 -0700 |
|---|---|---|
| committer | Ali B <abittin@gmail.com> | 2018-06-17 19:19:51 +0300 |
| commit | 4afd38feea8b940fc5e3bac806ab8604a3ba3081 (patch) | |
| tree | 127c4454fa9be095b62dfe67955eef8de9d5c2a7 | |
| parent | 4284a5140c0cc2199982454df5e373c6cb49f75f (diff) | |
Camera3: Implement flush call for version 3.1
When flush is called, HAL drops all inflight requests
and buffers as soon as possible.
HAL implements this feature by:
1. Streams off all active streams,
2. Calls process_capture_result with ERROR_BUFFER for
pending requests for which metadata is generated, but
not all buffers are filled, and
3. Calls process_capture_result with ERROR_RESULT for
pending requests for which metadata is not generated
yet.
This change also fixes a bug in mm-camera-interface so
that queued_buffer_count is reset during reg_buf.
Bug: 9758581
Change-Id: Ibcb5dc52faf8d50f781ef514e4c79185311dafce
Signed-off-by: Daniel Jarai <jaraidaniel@gmail.com>
| -rwxr-xr-x | camera/QCamera2/HAL3/QCamera3HWI.cpp | 235 | ||||
| -rwxr-xr-x | camera/QCamera2/HAL3/QCamera3HWI.h | 19 | ||||
| -rwxr-xr-x | camera/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c | 3 |
3 files changed, 235 insertions, 22 deletions
diff --git a/camera/QCamera2/HAL3/QCamera3HWI.cpp b/camera/QCamera2/HAL3/QCamera3HWI.cpp index 7da7891..5349837 100755 --- a/camera/QCamera2/HAL3/QCamera3HWI.cpp +++ b/camera/QCamera2/HAL3/QCamera3HWI.cpp @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2013, 2015, The Linux Foundataion. All rights reserved. +/* Copyright (c) 2012-2015, The Linux Foundataion. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -210,7 +210,7 @@ QCamera3HardwareInterface::~QCamera3HardwareInterface() /*flush the metadata list*/ if (!mStoredMetadataList.empty()) { for (List<MetadataBufferInfo>::iterator m = mStoredMetadataList.begin(); - m != mStoredMetadataList.end(); m++) { + m != mStoredMetadataList.end(); ) { mMetadataChannel->bufDone(m->meta_buf); free(m->meta_buf); m = mStoredMetadataList.erase(m); @@ -258,6 +258,9 @@ QCamera3HardwareInterface::~QCamera3HardwareInterface() if (mCameraOpened) closeCamera(); + mPendingBuffersMap.mPendingBufferList.clear(); + mPendingRequestsList.clear(); + for (size_t i = 0; i < CAMERA3_TEMPLATE_COUNT; i++) if (mDefaultMetadata[i]) free_camera_metadata(mDefaultMetadata[i]); @@ -637,7 +640,6 @@ int QCamera3HardwareInterface::configureStreams( } } - mPendingBuffersMap.clear(); /*For the streams to be reconfigured we need to register the buffers since the framework wont*/ for (List<stream_info_t *>::iterator it = mStreamInfo.begin(); @@ -657,12 +659,13 @@ int QCamera3HardwareInterface::configureStreams( __func__, channel, (*it)->buffer_set.num_buffers); } } - - mPendingBuffersMap.add((*it)->stream, 0); } /* Initialize mPendingRequestInfo and mPendnigBuffersMap */ mPendingRequestsList.clear(); + // Initialize/Reset the pending buffers list + mPendingBuffersMap.num_buffers = 0; + mPendingBuffersMap.mPendingBufferList.clear(); /*flush the metadata list*/ if (!mStoredMetadataList.empty()) { @@ -923,10 +926,22 @@ void QCamera3HardwareInterface::handleMetadataWithLock( for (List<RequestedBufferInfo>::iterator j = i->buffers.begin(); j != i->buffers.end(); j++) { if (j->buffer) { + for (List<PendingBufferInfo>::iterator k = + mPendingBuffersMap.mPendingBufferList.begin(); + k != mPendingBuffersMap.mPendingBufferList.end(); k++) { + if (k->buffer == j->buffer->buffer) { + ALOGV("%s: Found buffer %p in pending buffer List " + "for frame %d, Take it out!!", __func__, + k->buffer, k->frame_number); + mPendingBuffersMap.num_buffers--; + k = mPendingBuffersMap.mPendingBufferList.erase(k); + break; + } + } + result_buffers[result_buffers_idx++] = *(j->buffer); free(j->buffer); j->buffer = NULL; - mPendingBuffersMap.editValueFor(j->stream)--; } } result.output_buffers = result_buffers; @@ -996,8 +1011,23 @@ void QCamera3HardwareInterface::handleBufferWithLock( result.output_buffers = buffer; result.input_buffer = NULL; ALOGV("%s: result frame_number = %d, buffer = %p", - __func__, frame_number, buffer); - mPendingBuffersMap.editValueFor(buffer->stream)--; + __func__, frame_number, buffer->buffer); + + for (List<PendingBufferInfo>::iterator k = + mPendingBuffersMap.mPendingBufferList.begin(); + k != mPendingBuffersMap.mPendingBufferList.end(); k++ ) { + if (k->buffer == buffer->buffer) { + ALOGV("%s: Found Frame buffer, take it out from list", + __func__); + + mPendingBuffersMap.num_buffers--; + k = mPendingBuffersMap.mPendingBufferList.erase(k); + break; + } + } + ALOGV("%s: mPendingBuffersMap.num_buffers = %d", + __func__, mPendingBuffersMap.num_buffers); + if (buffer->stream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL) { int found = 0; for (List<MetadataBufferInfo>::iterator k = mStoredMetadataList.begin(); @@ -1049,14 +1079,27 @@ void QCamera3HardwareInterface::handleBufferWithLock( void QCamera3HardwareInterface::unblockRequestIfNecessary() { bool max_buffers_dequeued = false; - for (size_t i = 0; i < mPendingBuffersMap.size(); i++) { - const camera3_stream_t *stream = mPendingBuffersMap.keyAt(i); - uint32_t queued_buffers = mPendingBuffersMap.valueAt(i); - if (queued_buffers == stream->max_buffers) { - max_buffers_dequeued = true; - break; + + uint32_t queued_buffers = 0; + for(List<stream_info_t*>::iterator it=mStreamInfo.begin(); + it != mStreamInfo.end(); it++) { + queued_buffers = 0; + for (List<PendingBufferInfo>::iterator k = + mPendingBuffersMap.mPendingBufferList.begin(); + k != mPendingBuffersMap.mPendingBufferList.end(); k++ ) { + if (k->stream == (*it)->stream) + queued_buffers++; + + ALOGV("%s: Dequeued %d buffers for stream %p", __func__, + queued_buffers, (*it)->stream); + if (queued_buffers >=(* it)->stream->max_buffers) { + ALOGV("%s: Wait!!! Max buffers Dequed", __func__); + max_buffers_dequeued = true; + break; + } } } + if (!max_buffers_dequeued) { // Unblock process_capture_request mPendingRequest = 0; @@ -1237,8 +1280,19 @@ int QCamera3HardwareInterface::processCaptureRequest( requestedBuf.buffer = NULL; pendingRequest.buffers.push_back(requestedBuf); - mPendingBuffersMap.editValueFor(requestedBuf.stream)++; - } + // Add to buffer handle the pending buffers list + PendingBufferInfo bufferInfo; + bufferInfo.frame_number = frameNumber; + bufferInfo.buffer = request->output_buffers[i].buffer; + bufferInfo.stream = request->output_buffers[i].stream; + mPendingBuffersMap.mPendingBufferList.push_back(bufferInfo); + mPendingBuffersMap.num_buffers++; + ALOGV("%s: frame = %d, buffer = %p, stream = %p, stream format = %d", + __func__, frameNumber, bufferInfo.buffer, bufferInfo.stream, + bufferInfo.stream->format); + } + ALOGV("%s: mPendingBuffersMap.num_buffers = %d", + __func__, mPendingBuffersMap.num_buffers); mPendingRequestsList.push_back(pendingRequest); // Notify metadata channel we receive a request @@ -1378,12 +1432,155 @@ void QCamera3HardwareInterface::dump(int /*fd*/) *==========================================================================*/ int QCamera3HardwareInterface::flush() { - /*Enable lock when we implement this function*/ - /* + + unsigned int frameNum = 0; + camera3_notify_msg_t notify_msg; + camera3_capture_result_t result; + camera3_stream_buffer_t pStream_Buf; + + ALOGV("%s: Unblocking Process Capture Request", __func__); + + // Stop the Streams/Channels + for (List<stream_info_t *>::iterator it = mStreamInfo.begin(); + it != mStreamInfo.end(); it++) { + QCamera3Channel *channel = (QCamera3Channel *)(*it)->stream->priv; + channel->stop(); + (*it)->status = INVALID; + } + + if (mMetadataChannel) { + /* If content of mStreamInfo is not 0, there is metadata stream */ + mMetadataChannel->stop(); + } + + // Mutex Lock pthread_mutex_lock(&mMutex); + // Unblock process_capture_request + mPendingRequest = 0; + pthread_cond_signal(&mRequestCond); + + List<PendingRequestInfo>::iterator i = mPendingRequestsList.begin(); + frameNum = i->frame_number; + ALOGV("%s: Latest frame num on mPendingRequestsList = %d", + __func__, frameNum); + + // Go through the pending buffers and send buffer errors + for (List<PendingBufferInfo>::iterator k = + mPendingBuffersMap.mPendingBufferList.begin(); + k != mPendingBuffersMap.mPendingBufferList.end(); ) { + ALOGV("%s: frame = %d, buffer = %p, stream = %p, stream format = %d", + __func__, k->frame_number, k->buffer, k->stream, + k->stream->format); + + if (k->frame_number < frameNum) { + // Send Error notify to frameworks for each buffer for which + // metadata buffer is already sent + ALOGV("%s: Sending ERROR BUFFER for frame %d, buffer %p", + __func__, k->frame_number, k->buffer); + + notify_msg.type = CAMERA3_MSG_ERROR; + notify_msg.message.error.error_code = CAMERA3_MSG_ERROR_BUFFER; + notify_msg.message.error.error_stream = k->stream; + notify_msg.message.error.frame_number = k->frame_number; + mCallbackOps->notify(mCallbackOps, ¬ify_msg); + ALOGV("%s: notify frame_number = %d", __func__, + i->frame_number); + + pStream_Buf.acquire_fence = -1; + pStream_Buf.release_fence = -1; + pStream_Buf.buffer = k->buffer; + pStream_Buf.status = CAMERA3_BUFFER_STATUS_ERROR; + pStream_Buf.stream = k->stream; + + result.result = NULL; + result.frame_number = k->frame_number; + result.num_output_buffers = 1; + result.output_buffers = &pStream_Buf ; + mCallbackOps->process_capture_result(mCallbackOps, &result); + + mPendingBuffersMap.num_buffers--; + k = mPendingBuffersMap.mPendingBufferList.erase(k); + } + else { + k++; + } + } + + ALOGV("%s:Sending ERROR REQUEST for all pending requests", __func__); + + // Go through the pending requests info and send error request to framework + for (i = mPendingRequestsList.begin(); i != mPendingRequestsList.end(); ) { + int numBuffers = 0; + ALOGV("%s:Sending ERROR REQUEST for frame %d", + __func__, i->frame_number); + + // Send shutter notify to frameworks + notify_msg.type = CAMERA3_MSG_ERROR; + notify_msg.message.error.error_code = CAMERA3_MSG_ERROR_REQUEST; + notify_msg.message.error.error_stream = NULL; + notify_msg.message.error.frame_number = i->frame_number; + mCallbackOps->notify(mCallbackOps, ¬ify_msg); + + result.frame_number = i->frame_number; + result.num_output_buffers = 0; + result.output_buffers = NULL; + numBuffers = 0; + + for (List<PendingBufferInfo>::iterator k = + mPendingBuffersMap.mPendingBufferList.begin(); + k != mPendingBuffersMap.mPendingBufferList.end(); ) { + if (k->frame_number == i->frame_number) { + ALOGV("%s: Sending Error for frame = %d, buffer = %p," + " stream = %p, stream format = %d",__func__, + k->frame_number, k->buffer, k->stream, k->stream->format); + + pStream_Buf.acquire_fence = -1; + pStream_Buf.release_fence = -1; + pStream_Buf.buffer = k->buffer; + pStream_Buf.status = CAMERA3_BUFFER_STATUS_ERROR; + pStream_Buf.stream = k->stream; + + result.num_output_buffers = 1; + result.output_buffers = &pStream_Buf; + result.result = NULL; + result.frame_number = i->frame_number; + + mCallbackOps->process_capture_result(mCallbackOps, &result); + mPendingBuffersMap.num_buffers--; + k = mPendingBuffersMap.mPendingBufferList.erase(k); + numBuffers++; + } + else { + k++; + } + } + ALOGV("%s: mPendingBuffersMap.num_buffers = %d", + __func__, mPendingBuffersMap.num_buffers); + + i = mPendingRequestsList.erase(i); + } + + /* Reset pending buffer list and requests list */ + mPendingRequestsList.clear(); + + mPendingBuffersMap.num_buffers = 0; + mPendingBuffersMap.mPendingBufferList.clear(); + ALOGV("%s: Cleared all the pending buffers ", __func__); + + /*flush the metadata list*/ + if (!mStoredMetadataList.empty()) { + for (List<MetadataBufferInfo>::iterator m = mStoredMetadataList.begin(); + m != mStoredMetadataList.end(); ) { + mMetadataChannel->bufDone(m->meta_buf); + free(m->meta_buf); + m = mStoredMetadataList.erase(m); + } + } + ALOGV("%s: Flushing the metadata list done!! ", __func__); + + mFirstRequest = true; pthread_mutex_unlock(&mMutex); - */ return 0; } diff --git a/camera/QCamera2/HAL3/QCamera3HWI.h b/camera/QCamera2/HAL3/QCamera3HWI.h index 593df08..4294432 100755 --- a/camera/QCamera2/HAL3/QCamera3HWI.h +++ b/camera/QCamera2/HAL3/QCamera3HWI.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2013, 2015, The Linux Foundataion. All rights reserved. +/* Copyright (c) 2012-2015, The Linux Foundataion. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -209,7 +209,6 @@ private: int input_buffer_present; cam_trigger_t ae_trigger; } PendingRequestInfo; - typedef KeyedVector<camera3_stream_t *, uint32_t> PendingBuffersMap; /*Data structure to store metadata information*/ typedef struct { mm_camera_super_buf_t* meta_buf; @@ -217,6 +216,22 @@ private: uint32_t frame_number; }MetadataBufferInfo; + // Store the Pending buffers for Flushing + typedef struct { + // Frame number pertaining to the buffer + uint32_t frame_number; + camera3_stream_t *stream; + // Buffer handle + buffer_handle_t *buffer; + } PendingBufferInfo; + + typedef struct { + // Total number of buffer requests pending + uint32_t num_buffers; + // List of pending buffers + List<PendingBufferInfo> mPendingBufferList; + } PendingBuffersMap; + List<MetadataBufferInfo> mStoredMetadataList; List<PendingRequestInfo> mPendingRequestsList; PendingBuffersMap mPendingBuffersMap; diff --git a/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c b/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c index 228970d..14b93e1 100755 --- a/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c +++ b/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -1529,6 +1529,7 @@ int32_t mm_stream_reg_buf(mm_stream_t * my_obj) } pthread_mutex_lock(&my_obj->buf_lock); + my_obj->queued_buffer_count = 0; for(i = 0; i < my_obj->buf_num; i++){ /* check if need to qbuf initially */ if (my_obj->buf_status[i].initial_reg_flag) { |
