CameraNdk: add onBufferLost capture callback
Bug: 27102995
Change-Id: Ic54d1950da54c09eb2fea1eea5fccd3141c626d4
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 8f1115a..fa69727 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -18,7 +18,6 @@
#define LOG_TAG "ACameraDevice"
#include <vector>
-#include <utility>
#include <inttypes.h>
#include <android/hardware/ICameraService.h>
#include <camera2/SubmitInfo.h>
@@ -43,6 +42,7 @@
const char* CameraDevice::kCaptureFailureKey = "CaptureFailure";
const char* CameraDevice::kSequenceIdKey = "SequenceId";
const char* CameraDevice::kFrameNumberKey = "FrameNumber";
+const char* CameraDevice::kAnwKey = "Anw";
/**
* CameraDevice Implementation
@@ -465,10 +465,9 @@
}
camera_status_t
-CameraDevice::getIGBPfromSessionOutput(
- const ACaptureSessionOutput& config,
+CameraDevice::getIGBPfromAnw(
+ ANativeWindow* anw,
sp<IGraphicBufferProducer>& out) {
- ANativeWindow* anw = config.mWindow;
if (anw == nullptr) {
ALOGE("Error: output ANativeWindow is null");
return ACAMERA_ERROR_INVALID_PARAMETER;
@@ -514,26 +513,28 @@
return ret;
}
- std::set<OutputConfiguration> outputSet;
+ std::set<std::pair<ANativeWindow*, OutputConfiguration>> outputSet;
for (auto outConfig : outputs->mOutputs) {
+ ANativeWindow* anw = outConfig.mWindow;
sp<IGraphicBufferProducer> iGBP(nullptr);
- ret = getIGBPfromSessionOutput(outConfig, iGBP);
+ ret = getIGBPfromAnw(anw, iGBP);
if (ret != ACAMERA_OK) {
return ret;
}
- outputSet.insert(OutputConfiguration(iGBP, outConfig.mRotation));
+ outputSet.insert(std::make_pair(
+ anw, OutputConfiguration(iGBP, outConfig.mRotation)));
}
- std::set<OutputConfiguration> addSet = outputSet;
+ auto addSet = outputSet;
std::vector<int> deleteList;
// Determine which streams need to be created, which to be deleted
for (auto& kvPair : mConfiguredOutputs) {
int streamId = kvPair.first;
- OutputConfiguration& outConfig = kvPair.second;
- if (outputSet.count(outConfig) == 0) {
+ auto& outputPair = kvPair.second;
+ if (outputSet.count(outputPair) == 0) {
deleteList.push_back(streamId); // Need to delete a no longer needed stream
} else {
- addSet.erase(outConfig); // No need to add already existing stream
+ addSet.erase(outputPair); // No need to add already existing stream
}
}
@@ -585,15 +586,15 @@
}
// add new streams
- for (auto outConfig : addSet) {
+ for (auto outputPair : addSet) {
int streamId;
- remoteRet = mRemote->createStream(outConfig, &streamId);
+ remoteRet = mRemote->createStream(outputPair.second, &streamId);
if (!remoteRet.isOk()) {
ALOGE("Camera device %s failed to create stream: %s", getId(),
remoteRet.toString8().string());
return ACAMERA_ERROR_UNKNOWN;
}
- mConfiguredOutputs.insert(std::make_pair(streamId, outConfig));
+ mConfiguredOutputs.insert(std::make_pair(streamId, outputPair));
}
remoteRet = mRemote->endConfigure(/*isConstrainedHighSpeed*/ false);
@@ -682,26 +683,51 @@
int sequenceId = resultExtras.requestId;
int64_t frameNumber = resultExtras.frameNumber;
int32_t burstId = resultExtras.burstId;
-
- // No way to report buffer error now
- if (errorCode == hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER) {
- ALOGE("Camera %s Lost output buffer for frame %" PRId64,
- getId(), frameNumber);
+ auto it = mSequenceCallbackMap.find(sequenceId);
+ if (it == mSequenceCallbackMap.end()) {
+ ALOGE("%s: Error: capture sequence index %d not found!",
+ __FUNCTION__, sequenceId);
+ setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_SERVICE);
return;
}
- // Fire capture failure callback if there is one registered
- auto it = mSequenceCallbackMap.find(sequenceId);
- if (it != mSequenceCallbackMap.end()) {
- CallbackHolder cbh = (*it).second;
- ACameraCaptureSession_captureCallback_failed onError = cbh.mCallbacks.onCaptureFailed;
- sp<ACameraCaptureSession> session = cbh.mSession;
- if ((size_t) burstId >= cbh.mRequests.size()) {
- ALOGE("%s: Error: request index %d out of bound (size %zu)",
- __FUNCTION__, burstId, cbh.mRequests.size());
+
+ CallbackHolder cbh = (*it).second;
+ sp<ACameraCaptureSession> session = cbh.mSession;
+ if ((size_t) burstId >= cbh.mRequests.size()) {
+ ALOGE("%s: Error: request index %d out of bound (size %zu)",
+ __FUNCTION__, burstId, cbh.mRequests.size());
+ setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_SERVICE);
+ return;
+ }
+ sp<CaptureRequest> request = cbh.mRequests[burstId];
+
+ // Handle buffer error
+ if (errorCode == hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER) {
+ int32_t streamId = resultExtras.errorStreamId;
+ ACameraCaptureSession_captureCallback_bufferLost onBufferLost =
+ cbh.mCallbacks.onCaptureBufferLost;
+ auto outputPairIt = mConfiguredOutputs.find(streamId);
+ if (outputPairIt == mConfiguredOutputs.end()) {
+ ALOGE("%s: Error: stream id %d does not exist", __FUNCTION__, streamId);
setCameraDeviceErrorLocked(ACAMERA_ERROR_CAMERA_SERVICE);
return;
}
- sp<CaptureRequest> request = cbh.mRequests[burstId];
+ ANativeWindow* anw = outputPairIt->second.first;
+
+ ALOGV("Camera %s Lost output buffer for ANW %p frame %" PRId64,
+ getId(), anw, frameNumber);
+
+ sp<AMessage> msg = new AMessage(kWhatCaptureBufferLost, mHandler);
+ msg->setPointer(kContextKey, cbh.mCallbacks.context);
+ msg->setObject(kSessionSpKey, session);
+ msg->setPointer(kCallbackFpKey, (void*) onBufferLost);
+ msg->setObject(kCaptureRequestKey, request);
+ msg->setPointer(kAnwKey, (void*) anw);
+ msg->setInt64(kFrameNumberKey, frameNumber);
+ msg->post();
+ } else { // Handle other capture failures
+ // Fire capture failure callback if there is one registered
+ ACameraCaptureSession_captureCallback_failed onError = cbh.mCallbacks.onCaptureFailed;
sp<CameraCaptureFailure> failure(new CameraCaptureFailure());
failure->frameNumber = frameNumber;
// TODO: refine this when implementing flush
@@ -717,11 +743,12 @@
msg->setObject(kCaptureRequestKey, request);
msg->setObject(kCaptureFailureKey, failure);
msg->post();
- }
- // Update tracker
- mFrameNumberTracker.updateTracker(frameNumber, /*isError*/true);
- checkAndFireSequenceCompleteLocked();
+ // Update tracker
+ mFrameNumberTracker.updateTracker(frameNumber, /*isError*/true);
+ checkAndFireSequenceCompleteLocked();
+ }
+ return;
}
void CameraDevice::CallbackHandler::onMessageReceived(
@@ -735,6 +762,7 @@
case kWhatCaptureFail:
case kWhatCaptureSeqEnd:
case kWhatCaptureSeqAbort:
+ case kWhatCaptureBufferLost:
ALOGV("%s: Received msg %d", __FUNCTION__, msg->what());
break;
default:
@@ -801,6 +829,7 @@
case kWhatCaptureFail:
case kWhatCaptureSeqEnd:
case kWhatCaptureSeqAbort:
+ case kWhatCaptureBufferLost:
{
sp<RefBase> obj;
found = msg->findObject(kSessionSpKey, &obj);
@@ -814,6 +843,7 @@
case kWhatCaptureStart:
case kWhatCaptureResult:
case kWhatCaptureFail:
+ case kWhatCaptureBufferLost:
found = msg->findObject(kCaptureRequestKey, &obj);
if (!found) {
ALOGE("%s: Cannot find capture request!", __FUNCTION__);
@@ -956,6 +986,37 @@
(*onSeqAbort)(context, session.get(), seqId);
break;
}
+ case kWhatCaptureBufferLost:
+ {
+ ACameraCaptureSession_captureCallback_bufferLost onBufferLost;
+ found = msg->findPointer(kCallbackFpKey, (void**) &onBufferLost);
+ if (!found) {
+ ALOGE("%s: Cannot find buffer lost callback!", __FUNCTION__);
+ return;
+ }
+ if (onBufferLost == nullptr) {
+ return;
+ }
+
+ ANativeWindow* anw;
+ found = msg->findPointer(kAnwKey, (void**) &anw);
+ if (!found) {
+ ALOGE("%s: Cannot find ANativeWindow!", __FUNCTION__);
+ return;
+ }
+
+ int64_t frameNumber;
+ found = msg->findInt64(kFrameNumberKey, &frameNumber);
+ if (!found) {
+ ALOGE("%s: Cannot find frame number!", __FUNCTION__);
+ return;
+ }
+
+ ACaptureRequest* request = allocateACaptureRequest(requestSp);
+ (*onBufferLost)(context, session.get(), request, anw, frameNumber);
+ freeACaptureRequest(request);
+ break;
+ }
}
break;
}
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index fd51a81..3ccf95a 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -20,6 +20,7 @@
#include <map>
#include <set>
#include <atomic>
+#include <utility>
#include <utils/StrongPointer.h>
#include <utils/Mutex.h>
#include <utils/String8.h>
@@ -134,8 +135,8 @@
camera_status_t configureStreamsLocked(const ACaptureSessionOutputContainer* outputs);
- static camera_status_t getIGBPfromSessionOutput(
- const ACaptureSessionOutput& config, sp<IGraphicBufferProducer>& out);
+ static camera_status_t getIGBPfromAnw(
+ ANativeWindow* anw, sp<IGraphicBufferProducer>& out);
static camera_status_t getSurfaceFromANativeWindow(
ANativeWindow* anw, sp<Surface>& out);
@@ -147,8 +148,8 @@
const sp<ServiceCallback> mServiceCallback;
ACameraDevice* mWrapper;
- // stream id -> OutputConfiguration map
- std::map<int, OutputConfiguration> mConfiguredOutputs;
+ // stream id -> pair of (ANW* from application, OutputConfiguration used for camera service)
+ std::map<int, std::pair<ANativeWindow*, OutputConfiguration>> mConfiguredOutputs;
// TODO: maybe a bool will suffice for synchronous implementation?
std::atomic_bool mClosing;
@@ -171,16 +172,17 @@
// definition of handler and message
enum {
// Device state callbacks
- kWhatOnDisconnected, // onDisconnected
- kWhatOnError, // onError
+ kWhatOnDisconnected, // onDisconnected
+ kWhatOnError, // onError
// Session state callbacks
- kWhatSessionStateCb, // onReady, onActive
+ kWhatSessionStateCb, // onReady, onActive
// Capture callbacks
- kWhatCaptureStart, // onCaptureStarted
- kWhatCaptureResult, // onCaptureProgressed, onCaptureCompleted
- kWhatCaptureFail, // onCaptureFailed
- kWhatCaptureSeqEnd, // onCaptureSequenceCompleted
- kWhatCaptureSeqAbort // onCaptureSequenceAborted
+ kWhatCaptureStart, // onCaptureStarted
+ kWhatCaptureResult, // onCaptureProgressed, onCaptureCompleted
+ kWhatCaptureFail, // onCaptureFailed
+ kWhatCaptureSeqEnd, // onCaptureSequenceCompleted
+ kWhatCaptureSeqAbort, // onCaptureSequenceAborted
+ kWhatCaptureBufferLost // onCaptureBufferLost
};
static const char* kContextKey;
static const char* kDeviceKey;
@@ -193,6 +195,7 @@
static const char* kCaptureFailureKey;
static const char* kSequenceIdKey;
static const char* kFrameNumberKey;
+ static const char* kAnwKey;
class CallbackHandler : public AHandler {
public:
CallbackHandler() {}
@@ -227,7 +230,7 @@
if (cbs != nullptr) {
return *cbs;
}
- return { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
+ return { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
}
sp<ACameraCaptureSession> mSession;