Merge "Camera: Try to remove inflight requests during error notifications" into oc-dev
diff --git a/media/libaaudio/examples/write_sine/src/write_sine.cpp b/media/libaaudio/examples/write_sine/src/write_sine.cpp
index 511fe94..80b6252 100644
--- a/media/libaaudio/examples/write_sine/src/write_sine.cpp
+++ b/media/libaaudio/examples/write_sine/src/write_sine.cpp
@@ -27,6 +27,7 @@
#define NUM_SECONDS 10
#define NANOS_PER_MICROSECOND ((int64_t)1000)
#define NANOS_PER_MILLISECOND (NANOS_PER_MICROSECOND * 1000)
+#define NANOS_PER_SECOND (NANOS_PER_MILLISECOND * 1000)
static const char *getSharingModeText(aaudio_sharing_mode_t mode) {
const char *modeText = "unknown";
@@ -43,6 +44,15 @@
return modeText;
}
+static int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC) {
+ struct timespec time;
+ int result = clock_gettime(clockId, &time);
+ if (result < 0) {
+ return -errno;
+ }
+ return (time.tv_sec * NANOS_PER_SECOND) + time.tv_nsec;
+}
+
int main(int argc, char **argv)
{
(void)argc; // unused
@@ -56,7 +66,8 @@
const aaudio_audio_format_t requestedDataFormat = AAUDIO_FORMAT_PCM_I16;
aaudio_audio_format_t actualDataFormat = AAUDIO_FORMAT_PCM_I16;
- const aaudio_sharing_mode_t requestedSharingMode = AAUDIO_SHARING_MODE_EXCLUSIVE;
+ //const aaudio_sharing_mode_t requestedSharingMode = AAUDIO_SHARING_MODE_EXCLUSIVE;
+ const aaudio_sharing_mode_t requestedSharingMode = AAUDIO_SHARING_MODE_SHARED;
aaudio_sharing_mode_t actualSharingMode = AAUDIO_SHARING_MODE_SHARED;
AAudioStreamBuilder *aaudioBuilder = nullptr;
@@ -172,6 +183,26 @@
goto finish;
}
framesLeft -= actual;
+
+ // Use timestamp to estimate latency.
+ {
+ int64_t presentationFrame;
+ int64_t presentationTime;
+ result = AAudioStream_getTimestamp(aaudioStream,
+ CLOCK_MONOTONIC,
+ &presentationFrame,
+ &presentationTime
+ );
+ if (result == AAUDIO_OK) {
+ int64_t elapsedNanos = getNanoseconds() - presentationTime;
+ int64_t elapsedFrames = actualSampleRate * elapsedNanos / NANOS_PER_SECOND;
+ int64_t currentFrame = presentationFrame + elapsedFrames;
+ int64_t framesWritten = AAudioStream_getFramesWritten(aaudioStream);
+ int64_t estimatedLatencyFrames = framesWritten - currentFrame;
+ int64_t estimatedLatencyMillis = estimatedLatencyFrames * 1000 / actualSampleRate;
+ printf("estimatedLatencyMillis %d\n", (int)estimatedLatencyMillis);
+ }
+ }
}
xRunCount = AAudioStream_getXRunCount(aaudioStream);
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index af0593d..6ac8554 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -50,7 +50,6 @@
virtual aaudio_result_t requestFlush() = 0;
virtual aaudio_result_t requestStop() = 0;
- // TODO use aaudio_clockid_t all the way down to AudioClock
virtual aaudio_result_t getTimestamp(clockid_t clockId,
int64_t *framePosition,
int64_t *timeNanoseconds) = 0;
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index dd040a0..d380eb8 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -25,6 +25,7 @@
#include "AudioClock.h"
#include "AudioStreamRecord.h"
+#include "utility/AAudioUtilities.h"
using namespace android;
using namespace aaudio;
@@ -224,5 +225,28 @@
return 192; // TODO add query to AudioRecord.cpp
}
-// TODO implement getTimestamp
-
+aaudio_result_t AudioStreamRecord::getTimestamp(clockid_t clockId,
+ int64_t *framePosition,
+ int64_t *timeNanoseconds) {
+ ExtendedTimestamp extendedTimestamp;
+ status_t status = mAudioRecord->getTimestamp(&extendedTimestamp);
+ if (status != NO_ERROR) {
+ return AAudioConvert_androidToAAudioResult(status);
+ }
+ // TODO Merge common code into AudioStreamLegacy after rebasing.
+ int timebase;
+ switch(clockId) {
+ case CLOCK_BOOTTIME:
+ timebase = ExtendedTimestamp::TIMEBASE_BOOTTIME;
+ break;
+ case CLOCK_MONOTONIC:
+ timebase = ExtendedTimestamp::TIMEBASE_MONOTONIC;
+ break;
+ default:
+ ALOGE("getTimestamp() - Unrecognized clock type %d", (int) clockId);
+ return AAUDIO_ERROR_UNEXPECTED_VALUE;
+ break;
+ }
+ status = extendedTimestamp.getBestTimestamp(framePosition, timeNanoseconds, timebase);
+ return AAudioConvert_androidToAAudioResult(status);
+}
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.h b/media/libaaudio/src/legacy/AudioStreamRecord.h
index c8d389b..4667f05 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.h
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.h
@@ -44,10 +44,8 @@
virtual aaudio_result_t requestStop() override;
virtual aaudio_result_t getTimestamp(clockid_t clockId,
- int64_t *framePosition,
- int64_t *timeNanoseconds) override {
- return AAUDIO_ERROR_UNIMPLEMENTED; // TODO
- }
+ int64_t *framePosition,
+ int64_t *timeNanoseconds) override;
virtual aaudio_result_t read(void *buffer,
int32_t numFrames,
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index e0a04c3..8bb6aee 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -20,11 +20,11 @@
#include <stdint.h>
#include <media/AudioTrack.h>
-
#include <aaudio/AAudio.h>
-#include "AudioClock.h"
-#include "AudioStreamTrack.h"
+#include "utility/AudioClock.h"
+#include "AudioStreamTrack.h"
+#include "utility/AAudioUtilities.h"
using namespace android;
using namespace aaudio;
@@ -292,3 +292,29 @@
}
return AudioStream::getFramesRead();
}
+
+aaudio_result_t AudioStreamTrack::getTimestamp(clockid_t clockId,
+ int64_t *framePosition,
+ int64_t *timeNanoseconds) {
+ ExtendedTimestamp extendedTimestamp;
+ status_t status = mAudioTrack->getTimestamp(&extendedTimestamp);
+ if (status != NO_ERROR) {
+ return AAudioConvert_androidToAAudioResult(status);
+ }
+ // TODO Merge common code into AudioStreamLegacy after rebasing.
+ int timebase;
+ switch(clockId) {
+ case CLOCK_BOOTTIME:
+ timebase = ExtendedTimestamp::TIMEBASE_BOOTTIME;
+ break;
+ case CLOCK_MONOTONIC:
+ timebase = ExtendedTimestamp::TIMEBASE_MONOTONIC;
+ break;
+ default:
+ ALOGE("getTimestamp() - Unrecognized clock type %d", (int) clockId);
+ return AAUDIO_ERROR_UNEXPECTED_VALUE;
+ break;
+ }
+ status = extendedTimestamp.getBestTimestamp(framePosition, timeNanoseconds, timebase);
+ return AAudioConvert_androidToAAudioResult(status);
+}
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.h b/media/libaaudio/src/legacy/AudioStreamTrack.h
index 1de07ce..7a53022 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.h
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.h
@@ -47,9 +47,7 @@
virtual aaudio_result_t getTimestamp(clockid_t clockId,
int64_t *framePosition,
- int64_t *timeNanoseconds) override {
- return AAUDIO_ERROR_UNIMPLEMENTED; // TODO call getTimestamp(ExtendedTimestamp *timestamp);
- }
+ int64_t *timeNanoseconds) override;
virtual aaudio_result_t write(const void *buffer,
int32_t numFrames,
diff --git a/media/ndk/Android.mk b/media/ndk/Android.mk
index 0984ca4..2c070af 100644
--- a/media/ndk/Android.mk
+++ b/media/ndk/Android.mk
@@ -47,6 +47,9 @@
LOCAL_CFLAGS += -Werror -Wall
+LOCAL_STATIC_LIBRARIES := \
+ libgrallocusage \
+
LOCAL_SHARED_LIBRARIES := \
libbinder \
libmedia \
diff --git a/media/ndk/NdkImageReader.cpp b/media/ndk/NdkImageReader.cpp
index c0aee90..c449611 100644
--- a/media/ndk/NdkImageReader.cpp
+++ b/media/ndk/NdkImageReader.cpp
@@ -27,6 +27,7 @@
#include <android_media_Utils.h>
#include <android_runtime/android_view_Surface.h>
#include <android_runtime/android_hardware_HardwareBuffer.h>
+#include <grallocusage/GrallocUsageConversion.h>
using namespace android;
@@ -260,7 +261,8 @@
uint64_t consumerUsage;
android_hardware_HardwareBuffer_convertToGrallocUsageBits(
&producerUsage, &consumerUsage, mUsage0, mUsage1);
- mHalUsage = consumerUsage;
+ // Strip out producerUsage here.
+ mHalUsage = android_convertGralloc1To0Usage(0, consumerUsage);
sp<IGraphicBufferProducer> gbProducer;
sp<IGraphicBufferConsumer> gbConsumer;
@@ -411,11 +413,9 @@
}
// Check if the producer buffer configurations match what ImageReader configured.
- if ((bufferFmt != HAL_PIXEL_FORMAT_BLOB) && (readerFmt != HAL_PIXEL_FORMAT_BLOB) &&
- (readerWidth != bufferWidth || readerHeight != bufferHeight)) {
- ALOGW("%s: Buffer size: %dx%d, doesn't match AImageReader configured size: %dx%d",
- __FUNCTION__, bufferWidth, bufferHeight, readerWidth, readerHeight);
- }
+ ALOGV_IF(readerWidth != bufferWidth || readerHeight != bufferHeight,
+ "%s: Buffer size: %dx%d, doesn't match AImageReader configured size: %dx%d",
+ __FUNCTION__, bufferWidth, bufferHeight, readerWidth, readerHeight);
// Check if the buffer usage is a super set of reader's usage bits, aka all usage bits that
// ImageReader requested has been supported from the producer side.
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index 2be9362..8a7bb86 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -57,6 +57,9 @@
utils/AutoConditionLock.cpp \
utils/TagMonitor.cpp
+LOCAL_STATIC_LIBRARIES:= \
+ libgrallocusage
+
LOCAL_SHARED_LIBRARIES:= \
libui \
liblog \
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
index e03ec66..bfae9e9 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
@@ -304,7 +304,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer);
- mProducer = new RingBufferConsumer(consumer, GRALLOC_USAGE_HW_CAMERA_ZSL,
+ mProducer = new RingBufferConsumer(consumer, GRALLOC_USAGE_HW_CAMERA_READ,
mBufferQueueDepth);
mProducer->setName(String8("Camera2-ZslRingBufferConsumer"));
sp<Surface> outSurface = new Surface(producer);
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index f9b062a..4f788ae 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -145,12 +145,6 @@
int32_t format, /*out*/ int32_t *id) = 0;
/**
- * Create an input reprocess stream that uses buffers from an existing
- * output stream.
- */
- virtual status_t createReprocessStreamFromStream(int outputId, int *id) = 0;
-
- /**
* Get information about a given stream.
*/
virtual status_t getStreamInfo(int id,
@@ -169,12 +163,6 @@
virtual status_t deleteStream(int id) = 0;
/**
- * Delete reprocess stream. Must not be called if there are requests in
- * flight which reference that stream.
- */
- virtual status_t deleteReprocessStream(int id) = 0;
-
- /**
* Take the currently-defined set of streams and configure the HAL to use
* them. This is a long-running operation (may be several hundered ms).
*
@@ -289,21 +277,6 @@
virtual status_t triggerPrecaptureMetering(uint32_t id) = 0;
/**
- * Abstract interface for clients that want to listen to reprocess buffer
- * release events
- */
- struct BufferReleasedListener : public virtual RefBase {
- virtual void onBufferReleased(buffer_handle_t *handle) = 0;
- };
-
- /**
- * Push a buffer to be reprocessed into a reprocessing stream, and
- * provide a listener to call once the buffer is returned by the HAL
- */
- virtual status_t pushReprocessBuffer(int reprocessStreamId,
- buffer_handle_t *buffer, wp<BufferReleasedListener> listener) = 0;
-
- /**
* Flush all pending and in-flight requests. Blocks until flush is
* complete.
* Output lastFrameNumber is the last frame number of the previous streaming request.
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp b/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
index 9c058bc..0b57c50 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.cpp
@@ -17,6 +17,8 @@
//#define LOG_NDEBUG 0
#include <inttypes.h>
+#include <grallocusage/GrallocUsageConversion.h>
+
#include "CameraHardwareInterface.h"
namespace android {
@@ -395,14 +397,14 @@
}
hardware::Return<Status>
-CameraHardwareInterface::setUsage(hardware::graphics::allocator::V2_0::ProducerUsage usage) {
+CameraHardwareInterface::setUsage(hardware::camera::device::V1_0::ProducerUsageFlags usage) {
Status s = Status::INTERNAL_ERROR;
ANativeWindow *a = mPreviewWindow.get();
if (a == nullptr) {
ALOGE("%s: preview window is null", __FUNCTION__);
return s;
}
- mPreviewUsage = (int) usage;
+ mPreviewUsage = ::android_convertGralloc1To0Usage(usage, /*consumerUsage*/ 0);
int rc = native_window_set_usage(a, mPreviewUsage);
if (rc == OK) {
cleanupCirculatingBuffers();
diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.h b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
index c2b0e9c..caeacef 100644
--- a/services/camera/libcameraservice/device1/CameraHardwareInterface.h
+++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.h
@@ -461,7 +461,7 @@
hardware::Return<hardware::camera::common::V1_0::Status>
setCrop(int32_t left, int32_t top, int32_t right, int32_t bottom) override;
hardware::Return<hardware::camera::common::V1_0::Status>
- setUsage(hardware::graphics::allocator::V2_0::ProducerUsage usage) override;
+ setUsage(hardware::camera::device::V1_0::ProducerUsageFlags usage) override;
hardware::Return<hardware::camera::common::V1_0::Status>
setSwapInterval(int32_t interval) override;
hardware::Return<void> getMinUndequeuedBufferCount(
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 93d3d7f..980ba39 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -44,6 +44,8 @@
#include <utils/Timers.h>
#include <cutils/properties.h>
+#include <grallocusage/GrallocUsageConversion.h>
+
#include <android/hardware/camera2/ICameraDeviceUser.h>
#include "utils/CameraTraces.h"
@@ -495,11 +497,6 @@
return dataSpace;
}
-ConsumerUsageFlags Camera3Device::mapToConsumerUsage(
- uint32_t usage) {
- return usage;
-}
-
StreamRotation Camera3Device::mapToStreamRotation(camera3_stream_rotation_t rotation) {
switch (rotation) {
case CAMERA3_STREAM_ROTATION_0:
@@ -549,16 +546,6 @@
return static_cast<uint32_t>(pixelFormat);
}
-uint32_t Camera3Device::mapConsumerToFrameworkUsage(
- ConsumerUsageFlags usage) {
- return usage;
-}
-
-uint32_t Camera3Device::mapProducerToFrameworkUsage(
- ProducerUsageFlags usage) {
- return usage;
-}
-
ssize_t Camera3Device::getJpegBufferSize(uint32_t width, uint32_t height) const {
// Get max jpeg size (area-wise).
Size maxJpegResolution = getMaxJpegResolution();
@@ -1399,15 +1386,6 @@
return OK;
}
-status_t Camera3Device::createReprocessStreamFromStream(int outputId, int *id) {
- ATRACE_CALL();
- (void)outputId; (void)id;
-
- CLOGE("Unimplemented");
- return INVALID_OPERATION;
-}
-
-
status_t Camera3Device::getStreamInfo(int id,
uint32_t *width, uint32_t *height,
uint32_t *format, android_dataspace *dataSpace) {
@@ -1523,14 +1501,6 @@
return res;
}
-status_t Camera3Device::deleteReprocessStream(int id) {
- ATRACE_CALL();
- (void)id;
-
- CLOGE("Unimplemented");
- return INVALID_OPERATION;
-}
-
status_t Camera3Device::configureStreams(int operatingMode) {
ATRACE_CALL();
ALOGV("%s: E", __FUNCTION__);
@@ -1856,15 +1826,6 @@
sizeof(trigger)/sizeof(trigger[0]));
}
-status_t Camera3Device::pushReprocessBuffer(int reprocessStreamId,
- buffer_handle_t *buffer, wp<BufferReleasedListener> listener) {
- ATRACE_CALL();
- (void)reprocessStreamId; (void)buffer; (void)listener;
-
- CLOGE("Unimplemented");
- return INVALID_OPERATION;
-}
-
status_t Camera3Device::flush(int64_t *frameNumber) {
ATRACE_CALL();
ALOGV("%s: Camera %s: Flushing all requests", __FUNCTION__, mId.string());
@@ -3161,7 +3122,9 @@
Stream &dst = requestedConfiguration.streams[i];
camera3_stream_t *src = config->streams[i];
- int streamId = Camera3Stream::cast(src)->getId();
+ Camera3Stream* cam3stream = Camera3Stream::cast(src);
+ cam3stream->setBufferFreedListener(this);
+ int streamId = cam3stream->getId();
StreamType streamType;
switch (src->stream_type) {
case CAMERA3_STREAM_OUTPUT:
@@ -3180,7 +3143,9 @@
dst.width = src->width;
dst.height = src->height;
dst.format = mapToPixelFormat(src->format);
- dst.usage = mapToConsumerUsage(src->usage);
+ uint64_t consumerUsage, producerUsage;
+ ::android_convertGralloc0To1Usage(src->usage, &producerUsage, &consumerUsage);
+ dst.usage = consumerUsage;
dst.dataSpace = mapToHidlDataspace(src->data_space);
dst.rotation = mapToStreamRotation((camera3_stream_rotation_t) src->rotation);
@@ -3262,7 +3227,6 @@
__FUNCTION__, streamId);
return INVALID_OPERATION;
}
- dst->usage = mapConsumerToFrameworkUsage(src.consumerUsage);
} else {
// OUTPUT
if (src.consumerUsage != 0) {
@@ -3270,8 +3234,8 @@
__FUNCTION__, streamId);
return INVALID_OPERATION;
}
- dst->usage = mapProducerToFrameworkUsage(src.producerUsage);
}
+ dst->usage = ::android_convertGralloc1To0Usage(src.producerUsage, src.consumerUsage);
dst->max_buffers = src.maxBuffers;
}
}
@@ -3366,9 +3330,21 @@
wrapAsHidlRequest(requests[i], /*out*/&captureRequests[i], /*out*/&handlesCreated);
}
+ std::vector<device::V3_2::BufferCache> cachesToRemove;
+ {
+ std::lock_guard<std::mutex> lock(mBufferIdMapLock);
+ for (auto& pair : mFreedBuffers) {
+ // The stream might have been removed since onBufferFreed
+ if (mBufferIdMaps.find(pair.first) != mBufferIdMaps.end()) {
+ cachesToRemove.push_back({pair.first, pair.second});
+ }
+ }
+ mFreedBuffers.clear();
+ }
+
common::V1_0::Status status = common::V1_0::Status::INTERNAL_ERROR;
*numRequestProcessed = 0;
- mHidlSession->processCaptureRequest(captureRequests,
+ mHidlSession->processCaptureRequest(captureRequests, cachesToRemove,
[&status, &numRequestProcessed] (auto s, uint32_t n) {
status = s;
*numRequestProcessed = n;
@@ -3476,12 +3452,40 @@
auto it = bIdMap.find(buf);
if (it == bIdMap.end()) {
bIdMap[buf] = mNextBufferId++;
+ ALOGV("stream %d now have %zu buffer caches, buf %p",
+ streamId, bIdMap.size(), buf);
return std::make_pair(true, mNextBufferId - 1);
} else {
return std::make_pair(false, it->second);
}
}
+void Camera3Device::HalInterface::onBufferFreed(
+ int streamId, const native_handle_t* handle) {
+ std::lock_guard<std::mutex> lock(mBufferIdMapLock);
+ uint64_t bufferId = BUFFER_ID_NO_BUFFER;
+ auto mapIt = mBufferIdMaps.find(streamId);
+ if (mapIt == mBufferIdMaps.end()) {
+ // streamId might be from a deleted stream here
+ ALOGI("%s: stream %d has been removed",
+ __FUNCTION__, streamId);
+ return;
+ }
+ BufferIdMap& bIdMap = mapIt->second;
+ auto it = bIdMap.find(handle);
+ if (it == bIdMap.end()) {
+ ALOGW("%s: cannot find buffer %p in stream %d",
+ __FUNCTION__, handle, streamId);
+ return;
+ } else {
+ bufferId = it->second;
+ bIdMap.erase(it);
+ ALOGV("%s: stream %d now have %zu buffer caches after removing buf %p",
+ __FUNCTION__, streamId, bIdMap.size(), handle);
+ }
+ mFreedBuffers.push_back(std::make_pair(streamId, bufferId));
+}
+
/**
* RequestThread inner class methods
*/
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index d873b27..d4b92cf 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -125,7 +125,6 @@
status_t createInputStream(
uint32_t width, uint32_t height, int format,
int *id) override;
- status_t createReprocessStreamFromStream(int outputId, int *id) override;
status_t getStreamInfo(int id,
uint32_t *width, uint32_t *height,
@@ -133,7 +132,6 @@
status_t setStreamTransform(int id, int transform) override;
status_t deleteStream(int id) override;
- status_t deleteReprocessStream(int id) override;
status_t configureStreams(int operatingMode =
static_cast<int>(hardware::camera::device::V3_2::StreamConfigurationMode::NORMAL_MODE))
@@ -155,9 +153,6 @@
status_t triggerCancelAutofocus(uint32_t id) override;
status_t triggerPrecaptureMetering(uint32_t id) override;
- status_t pushReprocessBuffer(int reprocessStreamId,
- buffer_handle_t *buffer, wp<BufferReleasedListener> listener) override;
-
status_t flush(int64_t *lastFrameNumber = NULL) override;
status_t prepare(int streamId) override;
@@ -228,7 +223,7 @@
* Adapter for legacy HAL / HIDL HAL interface calls; calls either into legacy HALv3 or the
* HIDL HALv3 interfaces.
*/
- class HalInterface {
+ class HalInterface : public camera3::Camera3StreamBufferFreedListener {
public:
HalInterface(camera3_device_t *device);
HalInterface(sp<hardware::camera::device::V3_2::ICameraDeviceSession> &session);
@@ -326,6 +321,10 @@
// buffer_handle_t's FD won't change.
// return pair of (newlySeenBuffer?, bufferId)
std::pair<bool, uint64_t> getBufferId(const buffer_handle_t& buf, int streamId);
+
+ virtual void onBufferFreed(int streamId, const native_handle_t* handle) override;
+
+ std::vector<std::pair<int, uint64_t>> mFreedBuffers;
};
std::unique_ptr<HalInterface> mInterface;
@@ -598,7 +597,6 @@
static hardware::graphics::common::V1_0::PixelFormat mapToPixelFormat(int frameworkFormat);
static hardware::camera::device::V3_2::DataspaceFlags mapToHidlDataspace(
android_dataspace dataSpace);
- static hardware::camera::device::V3_2::ConsumerUsageFlags mapToConsumerUsage(uint32_t usage);
static hardware::camera::device::V3_2::StreamRotation mapToStreamRotation(
camera3_stream_rotation_t rotation);
// Returns a negative error code if the passed-in operation mode is not valid.
@@ -606,10 +604,6 @@
/*out*/ hardware::camera::device::V3_2::StreamConfigurationMode *mode);
static camera3_buffer_status_t mapHidlBufferStatus(hardware::camera::device::V3_2::BufferStatus status);
static int mapToFrameworkFormat(hardware::graphics::common::V1_0::PixelFormat pixelFormat);
- static uint32_t mapConsumerToFrameworkUsage(
- hardware::camera::device::V3_2::ConsumerUsageFlags usage);
- static uint32_t mapProducerToFrameworkUsage(
- hardware::camera::device::V3_2::ProducerUsageFlags usage);
struct RequestTrigger {
// Metadata tag number, e.g. android.control.aePrecaptureTrigger
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.cpp b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
index 1469b74..4eb15ad 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
@@ -263,6 +263,8 @@
mConsumer->setName(String8::format("Camera3-InputStream-%d", mId));
mProducer = producer;
+
+ mConsumer->setBufferFreedListener(this);
}
res = mConsumer->setDefaultBufferSize(camera3_stream::width,
@@ -288,6 +290,17 @@
return OK;
}
+void Camera3InputStream::onBufferFreed(const wp<GraphicBuffer>& gb) {
+ const sp<GraphicBuffer> buffer = gb.promote();
+ if (buffer != nullptr) {
+ if (mBufferFreedListener != nullptr) {
+ mBufferFreedListener->onBufferFreed(mId, buffer->handle);
+ }
+ } else {
+ ALOGE("%s: GraphicBuffer is freed before onBufferFreed callback finishes!", __FUNCTION__);
+ }
+}
+
}; // namespace camera3
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.h b/services/camera/libcameraservice/device3/Camera3InputStream.h
index 9f3de10..8f5b431 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.h
@@ -34,7 +34,8 @@
* buffers by feeding them into the HAL, as well as releasing the buffers back
* the buffers once the HAL is done with them.
*/
-class Camera3InputStream : public Camera3IOStreamBase {
+class Camera3InputStream : public Camera3IOStreamBase,
+ public BufferItemConsumer::BufferFreedListener {
public:
/**
* Set up a stream for formats that have fixed size, such as RAW and YUV.
@@ -77,6 +78,11 @@
virtual status_t getEndpointUsage(uint32_t *usage) const;
+ /**
+ * BufferItemConsumer::BufferFreedListener interface
+ */
+ virtual void onBufferFreed(const wp<GraphicBuffer>&) override;
+
}; // class Camera3InputStream
}; // namespace camera3
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 51dc20a..c60a68c 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -347,7 +347,9 @@
// Configure consumer-side ANativeWindow interface. The listener may be used
// to notify buffer manager (if it is used) of the returned buffers.
- res = mConsumer->connect(NATIVE_WINDOW_API_CAMERA, /*listener*/mBufferReleasedListener);
+ res = mConsumer->connect(NATIVE_WINDOW_API_CAMERA,
+ /*listener*/mBufferReleasedListener,
+ /*reportBufferRemoval*/true);
if (res != OK) {
ALOGE("%s: Unable to connect to native window for stream %d",
__FUNCTION__, mId);
@@ -543,6 +545,14 @@
}
}
+ if (res == OK) {
+ std::vector<sp<GraphicBuffer>> removedBuffers;
+ res = mConsumer->getAndFlushRemovedBuffers(&removedBuffers);
+ if (res == OK) {
+ onBuffersRemovedLocked(removedBuffers);
+ }
+ }
+
return res;
}
@@ -624,7 +634,7 @@
NATIVE_WINDOW_CONSUMER_USAGE_BITS, &u);
// If an opaque output stream's endpoint is ImageReader, add
- // GRALLOC_USAGE_HW_CAMERA_ZSL to the usage so HAL knows it will be used
+ // GRALLOC_USAGE_HW_CAMERA_READ to the usage so HAL knows it will be used
// for the ZSL use case.
// Assume it's for ImageReader if the consumer usage doesn't have any of these bits set:
// 1. GRALLOC_USAGE_HW_TEXTURE
@@ -634,7 +644,7 @@
if (camera3_stream::format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
(u & (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER |
GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_VIDEO_ENCODER)) == 0) {
- u |= GRALLOC_USAGE_HW_CAMERA_ZSL;
+ u |= GRALLOC_USAGE_HW_CAMERA_READ;
}
*usage = u;
@@ -686,6 +696,16 @@
}
}
+void Camera3OutputStream::onBuffersRemovedLocked(
+ const std::vector<sp<GraphicBuffer>>& removedBuffers) {
+ Camera3StreamBufferFreedListener* callback = mBufferFreedListener;
+ if (callback != nullptr) {
+ for (auto gb : removedBuffers) {
+ callback->onBufferFreed(mId, gb->handle);
+ }
+ }
+}
+
status_t Camera3OutputStream::detachBuffer(sp<GraphicBuffer>* buffer, int* fenceFd) {
Mutex::Autolock l(mLock);
@@ -718,7 +738,12 @@
}
}
- return OK;
+ std::vector<sp<GraphicBuffer>> removedBuffers;
+ res = mConsumer->getAndFlushRemovedBuffers(&removedBuffers);
+ if (res == OK) {
+ onBuffersRemovedLocked(removedBuffers);
+ }
+ return res;
}
status_t Camera3OutputStream::notifyBufferReleased(ANativeWindowBuffer* /*anwBuffer*/) {
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index 24e4e05..86676e4 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -263,6 +263,8 @@
virtual status_t getEndpointUsage(uint32_t *usage) const;
+ void onBuffersRemovedLocked(const std::vector<sp<GraphicBuffer>>&);
+
}; // class Camera3OutputStream
} // namespace camera3
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 53a3168..2b1a899 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -812,6 +812,18 @@
}
}
+void Camera3Stream::setBufferFreedListener(
+ Camera3StreamBufferFreedListener* listener) {
+ Mutex::Autolock l(mLock);
+ // Only allow set listener during stream configuration because stream is guaranteed to be IDLE
+ // at this state, so setBufferFreedListener won't collide with onBufferFreed callbacks
+ if (mState != STATE_IN_CONFIG && mState != STATE_IN_RECONFIG) {
+ ALOGE("%s: listener must be set during stream configuration!",__FUNCTION__);
+ return;
+ }
+ mBufferFreedListener = listener;
+}
+
}; // namespace camera3
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index 56cb827..27ef86d 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -365,6 +365,11 @@
void removeBufferListener(
const sp<Camera3StreamBufferListener>& listener);
+
+ // Setting listener will remove previous listener (if exists)
+ virtual void setBufferFreedListener(
+ Camera3StreamBufferFreedListener* listener) override;
+
/**
* Return if the buffer queue of the stream is abandoned.
*/
@@ -408,6 +413,8 @@
android_dataspace dataSpace, camera3_stream_rotation_t rotation,
int setId);
+ Camera3StreamBufferFreedListener* mBufferFreedListener;
+
/**
* Interface to be implemented by derived classes
*/
diff --git a/services/camera/libcameraservice/device3/Camera3StreamBufferFreedListener.h b/services/camera/libcameraservice/device3/Camera3StreamBufferFreedListener.h
new file mode 100644
index 0000000..478a752
--- /dev/null
+++ b/services/camera/libcameraservice/device3/Camera3StreamBufferFreedListener.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SERVERS_CAMERA3_STREAMBUFFERFREEDLISTENER_H
+#define ANDROID_SERVERS_CAMERA3_STREAMBUFFERFREEDLISTENER_H
+
+#include <gui/Surface.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+namespace camera3 {
+
+class Camera3StreamBufferFreedListener {
+public:
+ // onBufferFreed is called when a buffer is no longer being managed
+ // by this stream. This will not be called in events when all
+ // buffers are freed due to stream disconnection.
+ //
+ // The input handle may be deleted after this callback ends, so attempting
+ // to dereference handle post this callback is illegal and might lead to
+ // crash.
+ //
+ // This callback will be called while holding Camera3Stream's lock, so
+ // calling into other Camera3Stream APIs within this callback will
+ // lead to deadlock.
+ virtual void onBufferFreed(int streamId, const native_handle_t* handle) = 0;
+
+ virtual ~Camera3StreamBufferFreedListener() {}
+};
+
+}; //namespace camera3
+}; //namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/device3/Camera3StreamInterface.h b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
index f7b092f..37b7c36 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
@@ -19,6 +19,7 @@
#include <utils/RefBase.h>
#include "Camera3StreamBufferListener.h"
+#include "Camera3StreamBufferFreedListener.h"
struct camera3_stream_buffer;
@@ -287,6 +288,15 @@
wp<Camera3StreamBufferListener> listener) = 0;
virtual void removeBufferListener(
const sp<Camera3StreamBufferListener>& listener) = 0;
+
+ /**
+ * Setting listner will remove previous listener (if exists)
+ * Only allow set listener during stream configuration because stream is guaranteed to be IDLE
+ * at this state, so setBufferFreedListener won't collide with onBufferFreed callbacks.
+ * Client is responsible to keep the listener object alive throughout the lifecycle of this
+ * Camera3Stream.
+ */
+ virtual void setBufferFreedListener(Camera3StreamBufferFreedListener* listener) = 0;
};
} // namespace camera3