Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e081c59a authored by Yin-Chia Yeh's avatar Yin-Chia Yeh
Browse files

CameraNdk: add onBufferLost capture callback

Bug: 27102995
Change-Id: Ic54d1950da54c09eb2fea1eea5fccd3141c626d4
parent 309d05d0
Loading
Loading
Loading
Loading
+93 −32
Original line number Diff line number Diff line
@@ -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::kCaptureResultKey = "CaptureResult";
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 @@ CameraDevice::waitUntilIdleLocked() {
}

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 @@ CameraDevice::configureStreamsLocked(const ACaptureSessionOutputContainer* outpu
        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 @@ CameraDevice::configureStreamsLocked(const ACaptureSessionOutputContainer* outpu
    }

    // 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,18 +683,15 @@ CameraDevice::onCaptureErrorLocked(
    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)",
@@ -702,6 +700,34 @@ CameraDevice::onCaptureErrorLocked(
        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;
        }
        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,12 +743,13 @@ CameraDevice::onCaptureErrorLocked(
        msg->setObject(kCaptureRequestKey, request);
        msg->setObject(kCaptureFailureKey, failure);
        msg->post();
    }

        // Update tracker
        mFrameNumberTracker.updateTracker(frameNumber, /*isError*/true);
        checkAndFireSequenceCompleteLocked();
    }
    return;
}

void CameraDevice::CallbackHandler::onMessageReceived(
        const sp<AMessage> &msg) {
@@ -735,6 +762,7 @@ void CameraDevice::CallbackHandler::onMessageReceived(
        case kWhatCaptureFail:
        case kWhatCaptureSeqEnd:
        case kWhatCaptureSeqAbort:
        case kWhatCaptureBufferLost:
            ALOGV("%s: Received msg %d", __FUNCTION__, msg->what());
            break;
        default:
@@ -801,6 +829,7 @@ void CameraDevice::CallbackHandler::onMessageReceived(
        case kWhatCaptureFail:
        case kWhatCaptureSeqEnd:
        case kWhatCaptureSeqAbort:
        case kWhatCaptureBufferLost:
        {
            sp<RefBase> obj;
            found = msg->findObject(kSessionSpKey, &obj);
@@ -814,6 +843,7 @@ void CameraDevice::CallbackHandler::onMessageReceived(
                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 @@ void CameraDevice::CallbackHandler::onMessageReceived(
                    (*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;
        }
+16 −13
Original line number Diff line number Diff line
@@ -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 @@ class CameraDevice final : public RefBase {

    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 @@ class CameraDevice final : public RefBase {
    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;
@@ -180,7 +181,8 @@ class CameraDevice final : public RefBase {
        kWhatCaptureResult,    // onCaptureProgressed, onCaptureCompleted
        kWhatCaptureFail,      // onCaptureFailed
        kWhatCaptureSeqEnd,    // onCaptureSequenceCompleted
        kWhatCaptureSeqAbort // onCaptureSequenceAborted
        kWhatCaptureSeqAbort,  // onCaptureSequenceAborted
        kWhatCaptureBufferLost // onCaptureBufferLost
    };
    static const char* kContextKey;
    static const char* kDeviceKey;
@@ -193,6 +195,7 @@ class CameraDevice final : public RefBase {
    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 @@ class CameraDevice final : public RefBase {
            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;
+6 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
 * Do not reference types that are not part of the NDK.
 * Do not #include files that aren't part of the NDK.
 */
#include <android/native_window.h>
#include "NdkCameraError.h"
#include "NdkCameraMetadata.h"

@@ -78,6 +79,10 @@ typedef void (*ACameraCaptureSession_captureCallback_sequenceAbort)(
        void* context, ACameraCaptureSession* session,
        int sequenceId);

typedef void (*ACameraCaptureSession_captureCallback_bufferLost)(
        void* context, ACameraCaptureSession* session,
        ACaptureRequest* request, ANativeWindow* window, int64_t frameNumber);

typedef struct ACameraCaptureSession_captureCallbacks {
    void*                                             context;
    ACameraCaptureSession_captureCallback_start         onCaptureStarted;
@@ -86,6 +91,7 @@ typedef struct ACameraCaptureSession_captureCallbacks {
    ACameraCaptureSession_captureCallback_failed        onCaptureFailed;
    ACameraCaptureSession_captureCallback_sequenceEnd   onCaptureSequenceCompleted;
    ACameraCaptureSession_captureCallback_sequenceAbort onCaptureSequenceAborted;
    ACameraCaptureSession_captureCallback_bufferLost    onCaptureBufferLost;
} ACameraCaptureSession_captureCallbacks;

enum {