Merge "Camera: avoid copying of HalRequest"

This commit is contained in:
Yin-Chia Yeh 2018-02-21 21:53:22 +00:00 committed by Android (Google) Code Review
commit 8c76b8c465
2 changed files with 71 additions and 69 deletions

View file

@ -526,15 +526,14 @@ Status ExternalCameraDeviceSession::processOneCaptureRequest(const CaptureReques
return Status::INTERNAL_ERROR; return Status::INTERNAL_ERROR;
} }
// TODO: reduce object copy in this path std::shared_ptr<HalRequest> halReq = std::make_shared<HalRequest>();
HalRequest halReq = { halReq->frameNumber = request.frameNumber;
.frameNumber = request.frameNumber, halReq->setting = mLatestReqSetting;
.setting = mLatestReqSetting, halReq->frameIn = frameIn;
.frameIn = frameIn, halReq->shutterTs = shutterTs;
.shutterTs = shutterTs}; halReq->buffers.resize(numOutputBufs);
halReq.buffers.resize(numOutputBufs);
for (size_t i = 0; i < numOutputBufs; i++) { for (size_t i = 0; i < numOutputBufs; i++) {
HalStreamBuffer& halBuf = halReq.buffers[i]; HalStreamBuffer& halBuf = halReq->buffers[i];
int streamId = halBuf.streamId = request.outputBuffers[i].streamId; int streamId = halBuf.streamId = request.outputBuffers[i].streamId;
halBuf.bufferId = request.outputBuffers[i].bufferId; halBuf.bufferId = request.outputBuffers[i].bufferId;
const Stream& stream = mStreamMap[streamId]; const Stream& stream = mStreamMap[streamId];
@ -546,7 +545,7 @@ Status ExternalCameraDeviceSession::processOneCaptureRequest(const CaptureReques
halBuf.acquireFence = allFences[i]; halBuf.acquireFence = allFences[i];
halBuf.fenceTimeout = false; halBuf.fenceTimeout = false;
} }
mInflightFrames.insert(halReq.frameNumber); mInflightFrames.insert(halReq->frameNumber);
// Send request to OutputThread for the rest of processing // Send request to OutputThread for the rest of processing
mOutputThread->submitRequest(halReq); mOutputThread->submitRequest(halReq);
mFirstRequest = false; mFirstRequest = false;
@ -572,30 +571,31 @@ void ExternalCameraDeviceSession::notifyError(
} }
//TODO: refactor with processCaptureResult //TODO: refactor with processCaptureResult
Status ExternalCameraDeviceSession::processCaptureRequestError(const HalRequest& req) { Status ExternalCameraDeviceSession::processCaptureRequestError(
const std::shared_ptr<HalRequest>& req) {
// Return V4L2 buffer to V4L2 buffer queue // Return V4L2 buffer to V4L2 buffer queue
enqueueV4l2Frame(req.frameIn); enqueueV4l2Frame(req->frameIn);
// NotifyShutter // NotifyShutter
notifyShutter(req.frameNumber, req.shutterTs); notifyShutter(req->frameNumber, req->shutterTs);
notifyError(/*frameNum*/req.frameNumber, /*stream*/-1, ErrorCode::ERROR_REQUEST); notifyError(/*frameNum*/req->frameNumber, /*stream*/-1, ErrorCode::ERROR_REQUEST);
// Fill output buffers // Fill output buffers
hidl_vec<CaptureResult> results; hidl_vec<CaptureResult> results;
results.resize(1); results.resize(1);
CaptureResult& result = results[0]; CaptureResult& result = results[0];
result.frameNumber = req.frameNumber; result.frameNumber = req->frameNumber;
result.partialResult = 1; result.partialResult = 1;
result.inputBuffer.streamId = -1; result.inputBuffer.streamId = -1;
result.outputBuffers.resize(req.buffers.size()); result.outputBuffers.resize(req->buffers.size());
for (size_t i = 0; i < req.buffers.size(); i++) { for (size_t i = 0; i < req->buffers.size(); i++) {
result.outputBuffers[i].streamId = req.buffers[i].streamId; result.outputBuffers[i].streamId = req->buffers[i].streamId;
result.outputBuffers[i].bufferId = req.buffers[i].bufferId; result.outputBuffers[i].bufferId = req->buffers[i].bufferId;
result.outputBuffers[i].status = BufferStatus::ERROR; result.outputBuffers[i].status = BufferStatus::ERROR;
if (req.buffers[i].acquireFence >= 0) { if (req->buffers[i].acquireFence >= 0) {
native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0); native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
handle->data[0] = req.buffers[i].acquireFence; handle->data[0] = req->buffers[i].acquireFence;
result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false); result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false);
} }
} }
@ -603,7 +603,7 @@ Status ExternalCameraDeviceSession::processCaptureRequestError(const HalRequest&
// update inflight records // update inflight records
{ {
Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock);
mInflightFrames.erase(req.frameNumber); mInflightFrames.erase(req->frameNumber);
} }
// Callback into framework // Callback into framework
@ -612,51 +612,51 @@ Status ExternalCameraDeviceSession::processCaptureRequestError(const HalRequest&
return Status::OK; return Status::OK;
} }
Status ExternalCameraDeviceSession::processCaptureResult(HalRequest& req) { Status ExternalCameraDeviceSession::processCaptureResult(std::shared_ptr<HalRequest>& req) {
// Return V4L2 buffer to V4L2 buffer queue // Return V4L2 buffer to V4L2 buffer queue
enqueueV4l2Frame(req.frameIn); enqueueV4l2Frame(req->frameIn);
// NotifyShutter // NotifyShutter
notifyShutter(req.frameNumber, req.shutterTs); notifyShutter(req->frameNumber, req->shutterTs);
// Fill output buffers // Fill output buffers
hidl_vec<CaptureResult> results; hidl_vec<CaptureResult> results;
results.resize(1); results.resize(1);
CaptureResult& result = results[0]; CaptureResult& result = results[0];
result.frameNumber = req.frameNumber; result.frameNumber = req->frameNumber;
result.partialResult = 1; result.partialResult = 1;
result.inputBuffer.streamId = -1; result.inputBuffer.streamId = -1;
result.outputBuffers.resize(req.buffers.size()); result.outputBuffers.resize(req->buffers.size());
for (size_t i = 0; i < req.buffers.size(); i++) { for (size_t i = 0; i < req->buffers.size(); i++) {
result.outputBuffers[i].streamId = req.buffers[i].streamId; result.outputBuffers[i].streamId = req->buffers[i].streamId;
result.outputBuffers[i].bufferId = req.buffers[i].bufferId; result.outputBuffers[i].bufferId = req->buffers[i].bufferId;
if (req.buffers[i].fenceTimeout) { if (req->buffers[i].fenceTimeout) {
result.outputBuffers[i].status = BufferStatus::ERROR; result.outputBuffers[i].status = BufferStatus::ERROR;
native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0); native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
handle->data[0] = req.buffers[i].acquireFence; handle->data[0] = req->buffers[i].acquireFence;
result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false); result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false);
notifyError(req.frameNumber, req.buffers[i].streamId, ErrorCode::ERROR_BUFFER); notifyError(req->frameNumber, req->buffers[i].streamId, ErrorCode::ERROR_BUFFER);
} else { } else {
result.outputBuffers[i].status = BufferStatus::OK; result.outputBuffers[i].status = BufferStatus::OK;
// TODO: refactor // TODO: refactor
if (req.buffers[i].acquireFence > 0) { if (req->buffers[i].acquireFence > 0) {
native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0); native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
handle->data[0] = req.buffers[i].acquireFence; handle->data[0] = req->buffers[i].acquireFence;
result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false); result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false);
} }
} }
} }
// Fill capture result metadata // Fill capture result metadata
fillCaptureResult(req.setting, req.shutterTs); fillCaptureResult(req->setting, req->shutterTs);
const camera_metadata_t *rawResult = req.setting.getAndLock(); const camera_metadata_t *rawResult = req->setting.getAndLock();
V3_2::implementation::convertToHidl(rawResult, &result.result); V3_2::implementation::convertToHidl(rawResult, &result.result);
req.setting.unlock(rawResult); req->setting.unlock(rawResult);
// update inflight records // update inflight records
{ {
Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock);
mInflightFrames.erase(req.frameNumber); mInflightFrames.erase(req->frameNumber);
} }
// Callback into framework // Callback into framework
@ -1387,7 +1387,7 @@ ssize_t ExternalCameraDeviceSession::getJpegBufferSize(
int ExternalCameraDeviceSession::OutputThread::createJpegLocked( int ExternalCameraDeviceSession::OutputThread::createJpegLocked(
HalStreamBuffer &halBuf, HalStreamBuffer &halBuf,
HalRequest &req) const std::shared_ptr<HalRequest>& req)
{ {
int ret; int ret;
auto lfail = [&](auto... args) { auto lfail = [&](auto... args) {
@ -1414,17 +1414,17 @@ int ExternalCameraDeviceSession::OutputThread::createJpegLocked(
int jpegQuality, thumbQuality; int jpegQuality, thumbQuality;
Size thumbSize; Size thumbSize;
if (req.setting.exists(ANDROID_JPEG_QUALITY)) { if (req->setting.exists(ANDROID_JPEG_QUALITY)) {
camera_metadata_entry entry = camera_metadata_entry entry =
req.setting.find(ANDROID_JPEG_QUALITY); req->setting.find(ANDROID_JPEG_QUALITY);
jpegQuality = entry.data.u8[0]; jpegQuality = entry.data.u8[0];
} else { } else {
return lfail("%s: ANDROID_JPEG_QUALITY not set",__FUNCTION__); return lfail("%s: ANDROID_JPEG_QUALITY not set",__FUNCTION__);
} }
if (req.setting.exists(ANDROID_JPEG_THUMBNAIL_QUALITY)) { if (req->setting.exists(ANDROID_JPEG_THUMBNAIL_QUALITY)) {
camera_metadata_entry entry = camera_metadata_entry entry =
req.setting.find(ANDROID_JPEG_THUMBNAIL_QUALITY); req->setting.find(ANDROID_JPEG_THUMBNAIL_QUALITY);
thumbQuality = entry.data.u8[0]; thumbQuality = entry.data.u8[0];
} else { } else {
return lfail( return lfail(
@ -1432,9 +1432,9 @@ int ExternalCameraDeviceSession::OutputThread::createJpegLocked(
__FUNCTION__); __FUNCTION__);
} }
if (req.setting.exists(ANDROID_JPEG_THUMBNAIL_SIZE)) { if (req->setting.exists(ANDROID_JPEG_THUMBNAIL_SIZE)) {
camera_metadata_entry entry = camera_metadata_entry entry =
req.setting.find(ANDROID_JPEG_THUMBNAIL_SIZE); req->setting.find(ANDROID_JPEG_THUMBNAIL_SIZE);
thumbSize = Size { static_cast<uint32_t>(entry.data.i32[0]), thumbSize = Size { static_cast<uint32_t>(entry.data.i32[0]),
static_cast<uint32_t>(entry.data.i32[1]) static_cast<uint32_t>(entry.data.i32[1])
}; };
@ -1494,7 +1494,7 @@ int ExternalCameraDeviceSession::OutputThread::createJpegLocked(
/* Combine camera characteristics with request settings to form EXIF /* Combine camera characteristics with request settings to form EXIF
* metadata */ * metadata */
common::V1_0::helper::CameraMetadata meta(parent->mCameraCharacteristics); common::V1_0::helper::CameraMetadata meta(parent->mCameraCharacteristics);
meta.append(req.setting); meta.append(req->setting);
/* Generate EXIF object */ /* Generate EXIF object */
std::unique_ptr<ExifUtils> utils(ExifUtils::create()); std::unique_ptr<ExifUtils> utils(ExifUtils::create());
@ -1558,7 +1558,7 @@ int ExternalCameraDeviceSession::OutputThread::createJpegLocked(
} }
bool ExternalCameraDeviceSession::OutputThread::threadLoop() { bool ExternalCameraDeviceSession::OutputThread::threadLoop() {
HalRequest req; std::shared_ptr<HalRequest> req;
auto parent = mParent.promote(); auto parent = mParent.promote();
if (parent == nullptr) { if (parent == nullptr) {
ALOGE("%s: session has been disconnected!", __FUNCTION__); ALOGE("%s: session has been disconnected!", __FUNCTION__);
@ -1569,7 +1569,7 @@ bool ExternalCameraDeviceSession::OutputThread::threadLoop() {
// regularly to prevent v4l buffer queue filled with stale buffers // regularly to prevent v4l buffer queue filled with stale buffers
// when app doesn't program a preveiw request // when app doesn't program a preveiw request
waitForNextRequest(&req); waitForNextRequest(&req);
if (req.frameIn == nullptr) { if (req == nullptr) {
// No new request, wait again // No new request, wait again
return true; return true;
} }
@ -1577,17 +1577,17 @@ bool ExternalCameraDeviceSession::OutputThread::threadLoop() {
auto onDeviceError = [&](auto... args) { auto onDeviceError = [&](auto... args) {
ALOGE(args...); ALOGE(args...);
parent->notifyError( parent->notifyError(
req.frameNumber, /*stream*/-1, ErrorCode::ERROR_DEVICE); req->frameNumber, /*stream*/-1, ErrorCode::ERROR_DEVICE);
signalRequestDone(); signalRequestDone();
return false; return false;
}; };
if (req.frameIn->mFourcc != V4L2_PIX_FMT_MJPEG) { if (req->frameIn->mFourcc != V4L2_PIX_FMT_MJPEG) {
return onDeviceError("%s: do not support V4L2 format %c%c%c%c", __FUNCTION__, return onDeviceError("%s: do not support V4L2 format %c%c%c%c", __FUNCTION__,
req.frameIn->mFourcc & 0xFF, req->frameIn->mFourcc & 0xFF,
(req.frameIn->mFourcc >> 8) & 0xFF, (req->frameIn->mFourcc >> 8) & 0xFF,
(req.frameIn->mFourcc >> 16) & 0xFF, (req->frameIn->mFourcc >> 16) & 0xFF,
(req.frameIn->mFourcc >> 24) & 0xFF); (req->frameIn->mFourcc >> 24) & 0xFF);
} }
std::unique_lock<std::mutex> lk(mBufferLock); std::unique_lock<std::mutex> lk(mBufferLock);
@ -1595,7 +1595,7 @@ bool ExternalCameraDeviceSession::OutputThread::threadLoop() {
// TODO: see if we can save some computation by converting to YV12 here // TODO: see if we can save some computation by converting to YV12 here
uint8_t* inData; uint8_t* inData;
size_t inDataSize; size_t inDataSize;
req.frameIn->map(&inData, &inDataSize); req->frameIn->map(&inData, &inDataSize);
// TODO: profile // TODO: profile
// TODO: in some special case maybe we can decode jpg directly to gralloc output? // TODO: in some special case maybe we can decode jpg directly to gralloc output?
int res = libyuv::MJPGToI420( int res = libyuv::MJPGToI420(
@ -1623,7 +1623,7 @@ bool ExternalCameraDeviceSession::OutputThread::threadLoop() {
ALOGV("%s processing new request", __FUNCTION__); ALOGV("%s processing new request", __FUNCTION__);
const int kSyncWaitTimeoutMs = 500; const int kSyncWaitTimeoutMs = 500;
for (auto& halBuf : req.buffers) { for (auto& halBuf : req->buffers) {
if (halBuf.acquireFence != -1) { if (halBuf.acquireFence != -1) {
int ret = sync_wait(halBuf.acquireFence, kSyncWaitTimeoutMs); int ret = sync_wait(halBuf.acquireFence, kSyncWaitTimeoutMs);
if (ret) { if (ret) {
@ -1780,9 +1780,9 @@ Status ExternalCameraDeviceSession::OutputThread::allocateIntermediateBuffers(
return Status::OK; return Status::OK;
} }
Status ExternalCameraDeviceSession::OutputThread::submitRequest(const HalRequest& req) { Status ExternalCameraDeviceSession::OutputThread::submitRequest(
const std::shared_ptr<HalRequest>& req) {
std::unique_lock<std::mutex> lk(mRequestListLock); std::unique_lock<std::mutex> lk(mRequestListLock);
// TODO: reduce object copy in this path
mRequestList.push_back(req); mRequestList.push_back(req);
lk.unlock(); lk.unlock();
mRequestCond.notify_one(); mRequestCond.notify_one();
@ -1797,7 +1797,7 @@ void ExternalCameraDeviceSession::OutputThread::flush() {
} }
std::unique_lock<std::mutex> lk(mRequestListLock); std::unique_lock<std::mutex> lk(mRequestListLock);
std::list<HalRequest> reqs = mRequestList; std::list<std::shared_ptr<HalRequest>> reqs = std::move(mRequestList);
mRequestList.clear(); mRequestList.clear();
if (mProcessingRequest) { if (mProcessingRequest) {
std::chrono::seconds timeout = std::chrono::seconds(kFlushWaitTimeoutSec); std::chrono::seconds timeout = std::chrono::seconds(kFlushWaitTimeoutSec);
@ -1813,7 +1813,8 @@ void ExternalCameraDeviceSession::OutputThread::flush() {
} }
} }
void ExternalCameraDeviceSession::OutputThread::waitForNextRequest(HalRequest* out) { void ExternalCameraDeviceSession::OutputThread::waitForNextRequest(
std::shared_ptr<HalRequest>* out) {
if (out == nullptr) { if (out == nullptr) {
ALOGE("%s: out is null", __FUNCTION__); ALOGE("%s: out is null", __FUNCTION__);
return; return;
@ -1838,7 +1839,7 @@ void ExternalCameraDeviceSession::OutputThread::waitForNextRequest(HalRequest* o
*out = mRequestList.front(); *out = mRequestList.front();
mRequestList.pop_front(); mRequestList.pop_front();
mProcessingRequest = true; mProcessingRequest = true;
mProcessingFrameNumer = out->frameNumber; mProcessingFrameNumer = (*out)->frameNumber;
} }
void ExternalCameraDeviceSession::OutputThread::signalRequestDone() { void ExternalCameraDeviceSession::OutputThread::signalRequestDone() {
@ -1858,7 +1859,7 @@ void ExternalCameraDeviceSession::OutputThread::dump(int fd) {
} }
dprintf(fd, "OutputThread request list contains frame: "); dprintf(fd, "OutputThread request list contains frame: ");
for (const auto& req : mRequestList) { for (const auto& req : mRequestList) {
dprintf(fd, "%d, ", req.frameNumber); dprintf(fd, "%d, ", req->frameNumber);
} }
dprintf(fd, "\n"); dprintf(fd, "\n");
} }

View file

@ -199,8 +199,8 @@ protected:
Status processOneCaptureRequest(const CaptureRequest& request); Status processOneCaptureRequest(const CaptureRequest& request);
Status processCaptureResult(HalRequest&); Status processCaptureResult(std::shared_ptr<HalRequest>&);
Status processCaptureRequestError(const HalRequest&); Status processCaptureRequestError(const std::shared_ptr<HalRequest>&);
void notifyShutter(uint32_t frameNumber, nsecs_t shutterTs); void notifyShutter(uint32_t frameNumber, nsecs_t shutterTs);
void notifyError(uint32_t frameNumber, int32_t streamId, ErrorCode ec); void notifyError(uint32_t frameNumber, int32_t streamId, ErrorCode ec);
void invokeProcessCaptureResultCallback( void invokeProcessCaptureResultCallback(
@ -220,7 +220,7 @@ protected:
Status allocateIntermediateBuffers( Status allocateIntermediateBuffers(
const Size& v4lSize, const Size& thumbSize, const Size& v4lSize, const Size& thumbSize,
const hidl_vec<Stream>& streams); const hidl_vec<Stream>& streams);
Status submitRequest(const HalRequest&); Status submitRequest(const std::shared_ptr<HalRequest>&);
void flush(); void flush();
void dump(int fd); void dump(int fd);
virtual bool threadLoop() override; virtual bool threadLoop() override;
@ -238,7 +238,7 @@ protected:
static const int kReqWaitTimeoutMs = 33; // 33ms static const int kReqWaitTimeoutMs = 33; // 33ms
static const int kReqWaitTimesMax = 90; // 33ms * 90 ~= 3 sec static const int kReqWaitTimesMax = 90; // 33ms * 90 ~= 3 sec
void waitForNextRequest(HalRequest* out); void waitForNextRequest(std::shared_ptr<HalRequest>* out);
void signalRequestDone(); void signalRequestDone();
int cropAndScaleLocked( int cropAndScaleLocked(
@ -258,15 +258,16 @@ protected:
void *out, size_t maxOutSize, void *out, size_t maxOutSize,
size_t &actualCodeSize); size_t &actualCodeSize);
int createJpegLocked(HalStreamBuffer &halBuf, HalRequest &req); int createJpegLocked(HalStreamBuffer &halBuf, const std::shared_ptr<HalRequest>& req);
const wp<ExternalCameraDeviceSession> mParent; const wp<ExternalCameraDeviceSession> mParent;
const CroppingType mCroppingType; const CroppingType mCroppingType;
mutable std::mutex mRequestListLock; // Protect acccess to mRequestList mutable std::mutex mRequestListLock; // Protect acccess to mRequestList,
// mProcessingRequest and mProcessingFrameNumer
std::condition_variable mRequestCond; // signaled when a new request is submitted std::condition_variable mRequestCond; // signaled when a new request is submitted
std::condition_variable mRequestDoneCond; // signaled when a request is done processing std::condition_variable mRequestDoneCond; // signaled when a request is done processing
std::list<HalRequest> mRequestList; std::list<std::shared_ptr<HalRequest>> mRequestList;
bool mProcessingRequest = false; bool mProcessingRequest = false;
uint32_t mProcessingFrameNumer = 0; uint32_t mProcessingFrameNumer = 0;