diff options
author | Bill Yi <byi@google.com> | 2017-10-24 12:04:18 -0700 |
---|---|---|
committer | Bill Yi <byi@google.com> | 2017-10-24 12:04:18 -0700 |
commit | 2b2bfd44f1ef4ef88091bef5c7bbee843e7a1eb5 (patch) | |
tree | 8757798ec81ff5b2a0ed7693bd80d4928c5a5b2d | |
parent | a466dd692c86e4f6b1fe20c79e27fcaa54d8beb3 (diff) | |
parent | e290df27e8e561ea07aba814615c1a1de2f4c75c (diff) | |
download | easel-2b2bfd44f1ef4ef88091bef5c7bbee843e7a1eb5.tar.gz |
Merge remote-tracking branch 'goog/stage-aosp-master' into HEAD
-rw-r--r-- | camera/Android.mk | 16 | ||||
-rw-r--r-- | camera/include/HdrPlusProfiler.h | 126 | ||||
-rw-r--r-- | camera/include/HdrPlusTypes.h | 539 | ||||
-rw-r--r-- | camera/libhdrplusclient/Android.mk | 50 | ||||
-rw-r--r-- | camera/libhdrplusclient/EaselManagerClient.cpp | 37 | ||||
-rw-r--r-- | camera/libhdrplusclient/HdrPlusClientUtils.cpp | 105 | ||||
-rw-r--r-- | camera/libhdrplusclient/include/EaselManagerClient.h | 146 | ||||
-rw-r--r-- | camera/libhdrplusclient/include/HdrPlusClient.h | 153 | ||||
-rw-r--r-- | camera/libhdrplusclient/include/HdrPlusClientListener.h | 76 | ||||
-rw-r--r-- | camera/libhdrplusclient/include/HdrPlusClientUtils.h | 45 |
10 files changed, 1293 insertions, 0 deletions
diff --git a/camera/Android.mk b/camera/Android.mk new file mode 100644 index 0000000..0593872 --- /dev/null +++ b/camera/Android.mk @@ -0,0 +1,16 @@ +# Copyright 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. +ifneq ($(filter muskie walleye taimen,$(TARGET_DEVICE)),) + include $(call all-subdir-makefiles) +endif
\ No newline at end of file diff --git a/camera/include/HdrPlusProfiler.h b/camera/include/HdrPlusProfiler.h new file mode 100644 index 0000000..cc277f8 --- /dev/null +++ b/camera/include/HdrPlusProfiler.h @@ -0,0 +1,126 @@ +/* + * Copyright 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 HDR_PLUS_PROFILER_H +#define HDR_PLUS_PROFILER_H + +#ifndef ENABLE_HDRPLUS_PROFILER +#define ENABLE_HDRPLUS_PROFILER 0 +#endif + +#if !ENABLE_HDRPLUS_PROFILER + +// If profiler is not enabled, make every macro a noop +#define DECLARE_PROFILER_TIMER(_var, _description) +#define START_PROFILER_TIMER(_var) do {} while(0) +#define END_PROFILER_TIMER(_var) do {} while(0) +#define SCOPE_PROFILER_TIMER(_description) do {} while(0) + +#else + +#include <string> + +/* + * Declare a profiler timer. + * + * _var is the variable that will be declared as a timer. + * _description is the description for this timer. It will be used when logging the timer duration. + */ +#define DECLARE_PROFILER_TIMER(_var, _description) pbcamera::TimerLogger _var = {_description} + +/* + * Start a timer. + * + * _var is a timer declared with DECALRE_PROFILER_TIMER. + */ +#define START_PROFILER_TIMER(_var) ((_var).start()) + +/* + * End a timer and log the duration since last start. + * + * _var is a timer declared with DECALRE_PROFILER_TIMER. + */ +#define END_PROFILER_TIMER(_var) ((_var).end()) + +/* + * Declare a scope timer that starts now and ends when it goes out of scope. + * + * __description is the description for this timer. It will be used when logging the timer duration. + */ +#define SCOPE_PROFILER_TIMER(_description) pbcamera::ScopeTimerLogger _timer(_description) + +namespace pbcamera { + +#define TIMER_TAG "[PROFILE_TIMER]" + +/** + * TimerLogger provides a timer to log the duration between start() and end(). + */ +class TimerLogger { +public: + TimerLogger(const char *name) : mName(name), mInvalid(true) {}; + + // Start the timer. + void start() { + mInvalid = (clock_gettime(kClockId, &mStartTime) != 0); + } + + // End the timer and log the duration since last start. + void end() { + if (mInvalid) { + ALOGE("%s <%s> start time is invalid.", TIMER_TAG, mName.c_str()); + return; + } + + struct timespec endTime; + mInvalid = (clock_gettime(kClockId, &endTime) != 0); + if (mInvalid) { + ALOGE("%s <%s> end time is invalid.", TIMER_TAG, mName.c_str()); + return; + } + + int64_t startNs = static_cast<int64_t>(mStartTime.tv_sec) * kNsPerSec + mStartTime.tv_nsec; + int64_t endNs = static_cast<int64_t>(endTime.tv_sec) * kNsPerSec + endTime.tv_nsec; + ALOGI("%s <%s> took %f ms.", TIMER_TAG, mName.c_str(), + static_cast<float>(endNs - startNs) / kNsPerMs); + } + +private: + const static int64_t kNsPerSec = 1000000000; + const static int64_t kNsPerMs = 1000000; + const static clockid_t kClockId = CLOCK_BOOTTIME; + + std::string mName; + struct timespec mStartTime; + bool mInvalid; + +}; + +/** + * ScopeTimerLogger provides a timer to log the duration of the instance lifetime. + */ +class ScopeTimerLogger { +public: + ScopeTimerLogger(const char *name) : mTimerLogger(name) { mTimerLogger.start(); }; + virtual ~ScopeTimerLogger() { mTimerLogger.end(); }; +private: + TimerLogger mTimerLogger; +}; + +} // namespace pbcamera + +#endif // !ENABLE_HDRPLUS_PROFILER + +#endif // HDR_PLUS_PROFILER_H diff --git a/camera/include/HdrPlusTypes.h b/camera/include/HdrPlusTypes.h new file mode 100644 index 0000000..034ef6c --- /dev/null +++ b/camera/include/HdrPlusTypes.h @@ -0,0 +1,539 @@ +/* + * Copyright 2016 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 HDR_PLUS_TYPES_H +#define HDR_PLUS_TYPES_H + +#include <array> +#include <stdint.h> +#include <string> +#include <vector> + +namespace pbcamera { + +// This file defines the common types used in HDR+ client and HDR+ service API. + +typedef int32_t status_t; + +/* + * ImageConfiguration and PlaneConfiguration define the layout of a buffer. + * The following is an example of a NV21 buffer. + * + * <-------Y stride (in bytes)-------> + * <----width (in pixels)----> + * Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . ^ ^ + * Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | + * Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | + * Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . height Y scanline + * Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . (in lines) (in lines) + * Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | + * Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | + * Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | + * Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . | | + * Y Y Y Y Y Y Y Y Y Y Y Y Y Y . . . . v | + * . . . . . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . . . . . v + * <------V/U stride (in bytes)------> + * V U V U V U V U V U V U V U . . . . ^ + * V U V U V U V U V U V U V U . . . . | + * V U V U V U V U V U V U V U . . . . | + * V U V U V U V U V U V U V U . . . . V/U scanline + * V U V U V U V U V U V U V U . . . . (in lines) + * . . . . . . . . . . . . . . . . . . | + * . . . . . . . . . . . . . . . . . . v + * . . . . . . . . . . . . . . . . . . -> Image padding. + */ + +// PlaneConfiguration defines an image planes configuration. +struct PlaneConfiguration { + // Number of bytes in each line including padding. + uint32_t stride; + // Number of lines vertically including padding. + uint32_t scanline; + + PlaneConfiguration() : stride(0), scanline(0) {}; + + bool operator==(const PlaneConfiguration &other) const { + return stride == other.stride && + scanline == other.scanline; + } + + bool operator!=(const PlaneConfiguration &other) const { + return !(*this == other); + } +}; + +// ImageConfiguration defines an image configuration. +struct ImageConfiguration { + // Image width. + uint32_t width; + // Image height; + uint32_t height; + // Image format; + int format; + // Configuration for each planes. + std::vector<PlaneConfiguration> planes; + // Number of padded bytes after the last plane. + uint32_t padding; + + ImageConfiguration() : width(0), height(0), format(0), padding(0) {}; + + bool operator==(const ImageConfiguration &other) const { + return width == other.width && + height == other.height && + format == other.format && + planes == other.planes && + padding == other.padding; + } + + bool operator!=(const ImageConfiguration &other) const { + return !(*this == other); + } +}; + +/* + * StreamConfiguration defines a stream's configuration, such as its image buffer resolution, used + * during stream configuration. + */ +struct StreamConfiguration { + /* + * Unique ID of the stream. Each stream must have an unique ID so it can be used to identify + * the output streams of a StreamBuffer in CaptureRequest. + */ + uint32_t id; + + // Image configuration. + ImageConfiguration image; + + bool operator==(const StreamConfiguration &other) const { + return id == other.id && + image == other.image; + } + + bool operator!=(const StreamConfiguration &other) const { + return !(*this == other); + } +}; + +/* + * SensorMode contains the sensor mode information. + */ +struct SensorMode { + // Usually 0 is back camera and 1 is front camera. + uint32_t cameraId; + + // Pixel array resolution. + uint32_t pixelArrayWidth; + uint32_t pixelArrayHeight; + + // Active array resolution. + uint32_t activeArrayWidth; + uint32_t activeArrayHeight; + + // Sensor output pixel clock. + uint32_t outputPixelClkHz; + + // Sensor timestamp offset due to gyro calibration. When comparing timestamps between AP and + // Easel, this offset should be subtracted from AP timestamp. + int64_t timestampOffsetNs; + + // Sensor output format as defined in android_pixel_format. + int format; + + SensorMode() : cameraId(0), pixelArrayWidth(0), pixelArrayHeight(0), activeArrayWidth(0), + activeArrayHeight(0), outputPixelClkHz(0) {}; +}; + +/* + * InputConfiguration defines the input configuration for HDR+ service. + */ +struct InputConfiguration { + // Whether the input frames come from sensor MIPI or AP. If true, HDR+ service will get input + // frames from sensor and sensorMode contains the sensor mode information. If false, HDR+ + // service will get input frames from AP and streamConfig contains the input stream + // configuration. + bool isSensorInput; + // Sensor mode if isSensorInput is true. + SensorMode sensorMode; + // Input stream configuration if isSensorInput is false. + StreamConfiguration streamConfig; + + InputConfiguration() : isSensorInput(false) {}; +}; + +/* + * StreamBuffer defines a buffer in a stream. + */ +struct StreamBuffer { + // ID of the stream that this buffer belongs to. + uint32_t streamId; + // DMA buffer fd for this buffer if it's an ION buffer. + int32_t dmaBufFd; + // Pointer to the data of this buffer. + void* data; + // Size of the allocated data. + uint32_t dataSize; +}; + +/* + * CaptureRequest defines a capture request that HDR+ client sends to HDR+ service. + */ +struct CaptureRequest { + /* + * ID of the capture request. Each capture request must have an unique ID. When HDR+ service + * sends a CaptureResult to HDR+ client for this request, CaptureResult.requestId will be + * assigned to this ID. + */ + uint32_t id; + /* + * Output buffers of the request. The buffers will be filled with captured image when HDR+ + * service sends the output buffers in CaptureResult. + */ + std::vector<StreamBuffer> outputBuffers; +}; + +// Util functions used in StaticMetadata and FrameMetadata. +namespace metadatautils { +template<typename T> +void appendValueToString(std::string *strOut, const char* key, T value); + +template<typename T> +void appendVectorOrArrayToString(std::string *strOut, T values); + +template<typename T> +void appendVectorOrArrayToString(std::string *strOut, const char* key, T values); + +template<typename T, size_t SIZE> +void appendVectorArrayToString(std::string *strOut, const char* key, + std::vector<std::array<T, SIZE>> values); + +template<typename T, size_t SIZE> +void appendArrayArrayToString(std::string *strOut, const char* key, + std::array<T, SIZE> values); +} // namespace metadatautils + +/* + * StaticMetadata defines a camera device's characteristics. + * + * If this structure is changed, serialization in MessengerToHdrPlusService and deserialization in + * MessengerListenerFromHdrPlusClient should also be updated. + */ +struct StaticMetadata { + // The following are from Android Camera Metadata + uint8_t flashInfoAvailable; // android.flash.info.available + std::array<int32_t, 2> sensitivityRange; // android.sensor.info.sensitivityRange + int32_t maxAnalogSensitivity; // android.sensor.maxAnalogSensitivity + std::array<int32_t, 2> pixelArraySize; // android.sensor.info.pixelArraySize + std::array<int32_t, 4> activeArraySize; // android.sensor.info.activeArraySize + std::vector<std::array<int32_t, 4>> opticalBlackRegions; // android.sensor.opticalBlackRegions + // android.scaler.availableStreamConfigurations + std::vector<std::array<int32_t, 4>> availableStreamConfigurations; + uint8_t referenceIlluminant1; // android.sensor.referenceIlluminant1 + uint8_t referenceIlluminant2; // android.sensor.referenceIlluminant2 + std::array<float, 9> calibrationTransform1; // android.sensor.calibrationTransform1 + std::array<float, 9> calibrationTransform2; // android.sensor.calibrationTransform2 + std::array<float, 9> colorTransform1; // android.sensor.colorTransform1 + std::array<float, 9> colorTransform2; // android.sensor.colorTransform2 + int32_t whiteLevel; // android.sensor.info.whiteLevel + uint8_t colorFilterArrangement; // android.sensor.info.colorFilterArrangement + std::vector<float> availableApertures; // android.lens.info.availableApertures + std::vector<float> availableFocalLengths; // android.lens.info.availableFocalLengths + std::array<int32_t, 2> shadingMapSize; // android.lens.info.shadingMapSize + uint8_t focusDistanceCalibration; // android.lens.info.focusDistanceCalibration + + // Check if the contents of lhs and rhs are equal. For vector and array variables, two are + // equal if their elements are equal at the same position. + bool operator==(const StaticMetadata& rhs) const { + return flashInfoAvailable == rhs.flashInfoAvailable && + sensitivityRange == rhs.sensitivityRange && + maxAnalogSensitivity == rhs.maxAnalogSensitivity && + pixelArraySize == rhs.pixelArraySize && + activeArraySize == rhs.activeArraySize && + opticalBlackRegions == rhs.opticalBlackRegions && + availableStreamConfigurations == rhs.availableStreamConfigurations && + referenceIlluminant1 == rhs.referenceIlluminant1 && + referenceIlluminant2 == rhs.referenceIlluminant2 && + calibrationTransform1 == rhs.calibrationTransform1 && + calibrationTransform2 == rhs.calibrationTransform2 && + colorTransform1 == rhs.colorTransform1 && + colorTransform2 == rhs.colorTransform2 && + whiteLevel == rhs.whiteLevel && + colorFilterArrangement == rhs.colorFilterArrangement && + availableApertures == rhs.availableApertures && + availableFocalLengths == rhs.availableFocalLengths && + shadingMapSize == rhs.shadingMapSize && + focusDistanceCalibration == rhs.focusDistanceCalibration; + } + + // Convert this static metadata to a string and append it to the specified string. + void appendToString(std::string *strOut) const { + if (strOut == nullptr) return; + + metadatautils::appendValueToString(strOut, "flashInfoAvailable", flashInfoAvailable); + metadatautils::appendVectorOrArrayToString(strOut, "sensitivityRange", sensitivityRange); + metadatautils::appendValueToString(strOut, "maxAnalogSensitivity", maxAnalogSensitivity); + metadatautils::appendVectorOrArrayToString(strOut, "pixelArraySize", pixelArraySize); + metadatautils::appendVectorOrArrayToString(strOut, "activeArraySize", activeArraySize); + metadatautils::appendVectorArrayToString(strOut, "opticalBlackRegions", + opticalBlackRegions); + metadatautils::appendVectorArrayToString(strOut, "availableStreamConfigurations", + availableStreamConfigurations); + metadatautils::appendValueToString(strOut, "referenceIlluminant1", referenceIlluminant1); + metadatautils::appendValueToString(strOut, "referenceIlluminant2", referenceIlluminant2); + metadatautils::appendVectorOrArrayToString(strOut, "calibrationTransform1", + calibrationTransform1); + metadatautils::appendVectorOrArrayToString(strOut, "calibrationTransform2", + calibrationTransform2); + metadatautils::appendVectorOrArrayToString(strOut, "colorTransform1", colorTransform1); + metadatautils::appendVectorOrArrayToString(strOut, "colorTransform2", colorTransform2); + metadatautils::appendValueToString(strOut, "whiteLevel", whiteLevel); + metadatautils::appendValueToString(strOut, "colorFilterArrangement", + colorFilterArrangement); + metadatautils::appendVectorOrArrayToString(strOut, "availableApertures", + availableApertures); + metadatautils::appendVectorOrArrayToString(strOut, "availableFocalLengths", + availableFocalLengths); + metadatautils::appendVectorOrArrayToString(strOut, "shadingMapSize", shadingMapSize); + metadatautils::appendValueToString(strOut, "focusDistanceCalibration", + focusDistanceCalibration); + } +}; + +/* + * FrameMetadata defines properties of a frame captured on AP. + * + * If this structure is changed, serialization in MessengerToHdrPlusService and deserialization in + * MessengerListenerFromHdrPlusClient should also be updated. + */ +struct FrameMetadata { + int64_t easelTimestamp; // Easel timestamp + + // The following are from Android Camera Metadata + int64_t exposureTime; // android.sensor.exposureTime + int32_t sensitivity; // android.sensor.sensitivity + int32_t postRawSensitivityBoost; // android.control.postRawSensitivityBoost + uint8_t flashMode; // android.flash.mode + std::array<float, 4> colorCorrectionGains; // android.colorCorrection.gains + std::array<float, 9> colorCorrectionTransform; // android.colorCorrection.transform + std::array<float, 3> neutralColorPoint; // android.sensor.neutralColorPoint + int64_t timestamp; // android.sensor.timestamp + uint8_t blackLevelLock; // android.blackLevel.lock + uint8_t faceDetectMode; // android.statistics.faceDetectMode + std::vector<int32_t> faceIds; // android.statistics.faceIds + std::vector<std::array<int32_t, 6>> faceLandmarks; // android.statistics.faceLandmarks + std::vector<std::array<int32_t, 4>> faceRectangles; // android.statistics.faceRectangles + std::vector<uint8_t> faceScores; // android.statistics.faceScores + uint8_t sceneFlicker; // android.statistics.sceneFlicker + std::array<std::array<double, 2>, 4> noiseProfile; // android.sensor.noiseProfile + std::array<float, 4> dynamicBlackLevel; // android.sensor.dynamicBlackLevel + std::vector<float> lensShadingMap; // android.statistics.lensShadingMap + float focusDistance; // android.lens.focusDistance + + // Check if the contents of lhs and rhs are equal. For vector and array variables, two are + // equal if their elements are equal at the same position. + bool operator==(const FrameMetadata& rhs) const { + return easelTimestamp == rhs.easelTimestamp && + exposureTime == rhs.exposureTime && + sensitivity == rhs.sensitivity && + postRawSensitivityBoost == rhs.postRawSensitivityBoost && + flashMode == rhs.flashMode && + colorCorrectionGains == rhs.colorCorrectionGains && + colorCorrectionTransform == rhs.colorCorrectionTransform && + neutralColorPoint == rhs.neutralColorPoint && + timestamp == rhs.timestamp && + blackLevelLock == rhs.blackLevelLock && + faceDetectMode == rhs.faceDetectMode && + faceIds == rhs.faceIds && + faceLandmarks == rhs.faceLandmarks && + faceRectangles == rhs.faceRectangles && + faceScores == rhs.faceScores && + sceneFlicker == rhs.sceneFlicker && + noiseProfile == rhs.noiseProfile && + dynamicBlackLevel == rhs.dynamicBlackLevel && + lensShadingMap == rhs.lensShadingMap && + focusDistance == rhs.focusDistance; + } + + // Convert this static metadata to a string and append it to the specified string. + void appendToString(std::string *strOut) const { + if (strOut == nullptr) return; + + metadatautils::appendValueToString(strOut, "easelTimestamp", easelTimestamp); + metadatautils::appendValueToString(strOut, "exposureTime", exposureTime); + metadatautils::appendValueToString(strOut, "sensitivity", sensitivity); + metadatautils::appendValueToString(strOut, "postRawSensitivityBoost", + postRawSensitivityBoost); + metadatautils::appendValueToString(strOut, "flashMode", flashMode); + metadatautils::appendVectorOrArrayToString(strOut, "colorCorrectionGains", + colorCorrectionGains); + metadatautils::appendVectorOrArrayToString(strOut, "colorCorrectionTransform", + colorCorrectionTransform); + metadatautils::appendVectorOrArrayToString(strOut, "neutralColorPoint", neutralColorPoint); + metadatautils::appendValueToString(strOut, "timestamp", timestamp); + metadatautils::appendValueToString(strOut, "blackLevelLock", blackLevelLock); + metadatautils::appendValueToString(strOut, "faceDetectMode", faceDetectMode); + metadatautils::appendVectorOrArrayToString(strOut, "faceIds", faceIds); + metadatautils::appendVectorArrayToString(strOut, "faceLandmarks", faceLandmarks); + metadatautils::appendVectorArrayToString(strOut, "faceRectangles", faceRectangles); + metadatautils::appendVectorOrArrayToString(strOut, "faceScores", faceScores); + metadatautils::appendArrayArrayToString(strOut, "noiseProfile", noiseProfile); + metadatautils::appendValueToString(strOut, "sceneFlicker", sceneFlicker); + metadatautils::appendVectorOrArrayToString(strOut, "dynamicBlackLevel", dynamicBlackLevel); + metadatautils::appendVectorOrArrayToString(strOut, "lensShadingMap", lensShadingMap); + metadatautils::appendValueToString(strOut, "focusDistance", focusDistance); + } +}; + +/* + * ResultMetadata defines a process frame's properties that have been modified due to processing. + * + * If this structure is changed, serialization in MessengerToHdrPlusClient and deserialization in + * MessengerListenerFromHdrPlusService should also be updated. + */ +struct ResultMetadata { + int64_t easelTimestamp; // Easel timestamp of SOF of the base frame. + int64_t timestamp; // android.sensor.timestamp. AP timestamp of exposure start of the base + // frame. + + // Check if the contents of lhs and rhs are equal. For vector and array variables, two are + // equal if their elements are equal at the same position. + bool operator==(const ResultMetadata& rhs) const { + return easelTimestamp == rhs.easelTimestamp && + timestamp == rhs.timestamp; + } + + // Convert this static metadata to a string and append it to the specified string. + void appendToString(std::string *strOut) const { + if (strOut == nullptr) return; + metadatautils::appendValueToString(strOut, "easelTimestamp", easelTimestamp); + metadatautils::appendValueToString(strOut, "timestamp", timestamp); + } +}; + +/* + * CaptureResult defines a capture result that HDR+ service returns to HDR+ client. + */ +struct CaptureResult { + /* + * ID of the CaptureRequest that this capture result corresponds to. It can be used to match + * the original CaptureRequest when the HDR+ client receives this result. + */ + uint32_t requestId; + /* + * Output buffers filled with processed frame by HDR+ service. + */ + std::vector<StreamBuffer> outputBuffers; + + /* + * Result metadata including modified properties due to processing. + */ + ResultMetadata metadata; +}; + +// Util functions used in StaticMetadata and FrameMetadata. +namespace metadatautils { + +/* + * Append a key and a value to a string. + * + * strOut is the string to append a key and a value to. + * key is the name of the data. + * value is the value of the data. + */ +template<typename T> +void appendValueToString(std::string *strOut, const char* key, T value) { + if (strOut == nullptr) return; + (*strOut) += std::string(key) + ": " + std::to_string(value) + "\n"; +} + +/* + * Append a vector or an array of values to a string. + * + * strOut is the string to append a key and values to. + * values is a vector or an array containing values to append to the string. + */ +template<typename T> +void appendVectorOrArrayToString(std::string *strOut, T values) { + if (strOut == nullptr) return; + for (size_t i = 0; i < values.size(); i++) { + (*strOut) += std::to_string(values[i]); + if (i != values.size() - 1) { + (*strOut) +=", "; + } + } +} + +/* + * Append a key and a vector or an array of values to a string. + * + * strOut is the string to append a key and values to. + * key is the name of the data. + * values is a vector or an array containing values to append to the string. + */ +template<typename T> +void appendVectorOrArrayToString(std::string *strOut, const char* key, T values) { + if (strOut == nullptr) return; + (*strOut) += std::string(key) + ": "; + appendVectorOrArrayToString(strOut, values); + (*strOut) += "\n"; +} + +/* + * Append a key and a vector of arrays to a string. + * + * strOut is the string to append a key and values to. + * key is the name of the data. + * values is a vector of arrays containing values to append to the string. + */ +template<typename T, size_t SIZE> +void appendVectorArrayToString(std::string *strOut, const char* key, + std::vector<std::array<T, SIZE>> values) { + if (strOut == nullptr) return; + (*strOut) += std::string(key) + ": "; + for (size_t i = 0; i < values.size(); i++) { + appendVectorOrArrayToString(strOut, values[i]); + if (i != values.size() - 1) { + (*strOut) +=", "; + } + } + (*strOut) += "\n"; +} + +/* + * Append a key and an array of arrays to a string. + * + * strOut is the string to append a key and values to. + * key is the name of the data. + * values is an array of arrays containing values to append to the string. + */ +template<typename T, size_t SIZE> +void appendArrayArrayToString(std::string *strOut, const char* key, + std::array<T, SIZE> values) { + if (strOut == nullptr) return; + (*strOut) += std::string(key) + ": "; + for (size_t i = 0; i < values.size(); i++) { + appendVectorOrArrayToString(strOut, values[i]); + if (i != values.size() - 1) { + (*strOut) +=", "; + } + } + (*strOut) += "\n"; +} + +} // namespace metadatautils + +} // namespace pbcamera + +#endif // HDR_PLUS_TYPES_H diff --git a/camera/libhdrplusclient/Android.mk b/camera/libhdrplusclient/Android.mk new file mode 100644 index 0000000..562e02c --- /dev/null +++ b/camera/libhdrplusclient/Android.mk @@ -0,0 +1,50 @@ +# Copyright 2016 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. + +LOCAL_PATH:= $(call my-dir) + +# +# libhdrplusclient +# +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + EaselManagerClient.cpp \ + HdrPlusClientUtils.cpp + +LOCAL_SHARED_LIBRARIES := liblog + +# For AOSP builds, use dummy implementation. +ifeq ($(wildcard vendor/google_easel),) + LOCAL_CFLAGS += -DUSE_DUMMY_IMPL=1 +else + LOCAL_CFLAGS += -DUSE_DUMMY_IMPL=0 + LOCAL_SHARED_LIBRARIES += libhdrplusclientimpl +endif + +LOCAL_C_INCLUDES += \ + $(LOCAL_PATH)/include \ + hardware/google/easel/camera/include + +LOCAL_CFLAGS += -Wall -Wextra -Werror + +LOCAL_EXPORT_C_INCLUDE_DIRS += \ + $(LOCAL_PATH)/include \ + hardware/google/easel/camera/include + +LOCAL_MODULE:= libhdrplusclient +LOCAL_PROPRIETARY_MODULE := true +LOCAL_MODULE_OWNER := google + +include $(BUILD_SHARED_LIBRARY) diff --git a/camera/libhdrplusclient/EaselManagerClient.cpp b/camera/libhdrplusclient/EaselManagerClient.cpp new file mode 100644 index 0000000..83bfcf8 --- /dev/null +++ b/camera/libhdrplusclient/EaselManagerClient.cpp @@ -0,0 +1,37 @@ +/* + * Copyright 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. + */ +#define LOG_TAG "EaselManagerClient" +#include <log/log.h> + +#include <memory> + +#include "EaselManagerClient.h" + +#if !USE_DUMMY_IMPL +#include "EaselManagerClientImpl.h" +#endif + +namespace android { + +std::unique_ptr<EaselManagerClient> EaselManagerClient::create() { +#if USE_DUMMY_IMPL + return nullptr; +#else + return std::make_unique<EaselManagerClientImpl>(); +#endif +} + +} // namespace android diff --git a/camera/libhdrplusclient/HdrPlusClientUtils.cpp b/camera/libhdrplusclient/HdrPlusClientUtils.cpp new file mode 100644 index 0000000..a48210f --- /dev/null +++ b/camera/libhdrplusclient/HdrPlusClientUtils.cpp @@ -0,0 +1,105 @@ +/* + * Copyright 2016 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. + */ +//#define LOG_NDEBUG 0 +#define LOG_TAG "HdrPlusClientUtils" +#include <log/log.h> + +#include <fstream> +#include <inttypes.h> +#include <system/graphics.h> + +#include "HdrPlusClientUtils.h" + +namespace android { +namespace hdrplus_client_utils { + +// Get the RGB values of the pixel at (x, y). +static status_t getRgb(uint8_t *r, uint8_t *g, uint8_t* b, uint32_t x, uint32_t y, + const pbcamera::StreamConfiguration &streamConfig, + const pbcamera::StreamBuffer &buffer) { + switch (streamConfig.image.format) { + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + { + // Check the stream configuration has two planes. + if (streamConfig.image.planes.size() != 2) { + ALOGE("%s: NV21 should have 2 planes but it has %zu", __FUNCTION__, + streamConfig.image.planes.size()); + return BAD_VALUE; + } + + // Find the indices of Y, V, and U in the buffer. + uint32_t yIndex = y * streamConfig.image.planes[0].stride + x; + uint32_t vIndex = streamConfig.image.planes[0].scanline * + streamConfig.image.planes[0].stride + + (y / 2) * streamConfig.image.planes[1].stride + (x & ~0x1); + uint32_t uIndex = vIndex + 1; + + // Convert YUV to RGB. + int32_t yc = ((uint8_t*)buffer.data)[yIndex]; + int32_t vc = ((uint8_t*)buffer.data)[vIndex] - 128; + int32_t uc = ((uint8_t*)buffer.data)[uIndex] - 128; + *r = std::min(std::max(yc + 0.003036f * uc + 1.399457f * vc, 0.0f), 255.0f); + *g = std::min(std::max(yc - 0.344228f * uc - 0.717202f * vc, 0.0f), 255.0f); + *b = std::min(std::max(yc + 1.772431f * uc - 0.006137f * vc, 0.0f), 255.0f); + return OK; + } + default: + ALOGE("%s: Format %d is not supported.", __FUNCTION__, streamConfig.image.format); + return BAD_VALUE; + } +} + +status_t writePpm(const std::string &filename, const pbcamera::StreamConfiguration &streamConfig, + const pbcamera::StreamBuffer &buffer) { + if (streamConfig.image.format != HAL_PIXEL_FORMAT_YCrCb_420_SP) { + ALOGE("%s: format 0x%x is not supported.", __FUNCTION__, streamConfig.image.format); + return BAD_VALUE; + } + + std::ofstream outfile(filename, std::ios::binary); + if (!outfile.is_open()) { + ALOGE("%s: Opening file (%s) failed.", __FUNCTION__, filename.data()); + return NO_INIT; + } + + uint32_t width = streamConfig.image.width; + uint32_t height = streamConfig.image.height; + + // Write headers of the ppm file. + outfile << "P6"; + outfile << " " << std::to_string(width) << " " << std::to_string(height) << " 255 "; + + // Write RGB values of the image. + uint8_t r, g, b; + for (uint32_t y = 0; y < height; y++) { + for (uint32_t x = 0; x < width; x++) { + status_t res = getRgb(&r, &g, &b, x, y, streamConfig, buffer); + if (res != OK) { + ALOGE("%s: Getting RGB failed: %s (%d).", __FUNCTION__, strerror(-res), res); + return res; + } + outfile << r << g << b; + } + } + + ALOGD("%s: Saved file: %s", __FUNCTION__, filename.data()); + + outfile.close(); + return OK; +} + +} // hdrplus_client_utils +} // namespace android diff --git a/camera/libhdrplusclient/include/EaselManagerClient.h b/camera/libhdrplusclient/include/EaselManagerClient.h new file mode 100644 index 0000000..3234f34 --- /dev/null +++ b/camera/libhdrplusclient/include/EaselManagerClient.h @@ -0,0 +1,146 @@ +/* + * Copyright 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 EASEL_MANAGER_CLIENT_H +#define EASEL_MANAGER_CLIENT_H + +#include <future> + +#include <utils/Errors.h> +#include <utils/Mutex.h> + +namespace android { + +class EaselManagerClientListener; +class HdrPlusClient; +class HdrPlusClientListener; + +class EaselManagerClient { +public: + static std::unique_ptr<EaselManagerClient> create(); + + EaselManagerClient() {}; + virtual ~EaselManagerClient() {}; + + /* + * Return if Easel is present on the device. + * + * If Easel is not present, all other calls to HdrPlusClient are invalid. + */ + virtual bool isEaselPresentOnDevice() const = 0; + + /* + * Open Easel manager client. + * + * This will power on Easel and initialize Easel manager client. + */ + virtual status_t open() = 0; + + /* + * Suspend Easel. + * + * Put Easel on suspend mode. + */ + virtual status_t suspend() = 0; + + /* + * Resume Easel. + * + * Resume Easel from suspend mode. + * + * listener will be invoked for Easel status. + */ + virtual status_t resume(EaselManagerClientListener *listener) = 0; + + /* + * Start MIPI with an output pixel lock rate for a camera. + * + * Can be called when Easel is powered on or resumed, for Easel to start sending sensor data + * to AP. + * + * cameraId is the camera ID to start MIPI for. + * outputPixelClkHz is the output pixel rate. + * enableCapture is whether to enable MIPI capture on Easel. + */ + virtual status_t startMipi(uint32_t cameraId, uint32_t outputPixelClkHz, + bool enableCapture) = 0; + + /* + * Stop MIPI for a camera. + * + * cameraId is the camera is ID to stop MIPI for. + */ + virtual status_t stopMipi(uint32_t cameraId) = 0; + + /* + * Open an HDR+ client asynchronously. + * + * Open an HDR+ client asynchronouly. When an HDR+ client is opened, + * HdrPlusClientListener::onOpened() will be invoked with the created HDR+ client. If opening + * an HDR+ client failed, HdrPlusClientListener::onOpenFailed() will be invoked with the error. + * If this method returns an error, HdrPlusClientListener::onOpenFailed() will not be invoked. + * + * listener is an HDR+ client listener. + * + * Returns: + * OK: if initiating opening an HDR+ client asynchronously was successful. + * HdrPlusClientListener::onOpened() or HdrPlusClientListener::onOpenFailed() + * will be invoked when opening an HDR+ client completed. + * ALREADY_EXISTS: if there is already a pending HDR+ client being opened. + */ + virtual status_t openHdrPlusClientAsync(HdrPlusClientListener *listener) = 0; + + /* + * Open an HDR+ client synchronously and block until it completes. + * + * listener is an HDR+ client listener. + * client is an output parameter for created HDR+ client. + * + * Returns: + * OK: on success. + * -EEXIST: if an HDR+ client is already opened. + * -ENODEV: if opening an HDR+ failed due to a serious error. + */ + virtual status_t openHdrPlusClient(HdrPlusClientListener *listener, + std::unique_ptr<HdrPlusClient> *client) = 0; + + /* + * Close an HDR+ client. + * + * client is the HDR+ client to be closed. + */ + virtual void closeHdrPlusClient(std::unique_ptr<HdrPlusClient> client) = 0; + +private: + // Disallow copy and assign. + EaselManagerClient(const EaselManagerClient&) = delete; + void operator=(const EaselManagerClient&) = delete; +}; + + +/* + * EaselManagerClientListener defines callbacks that will be invoked by EaselManagerClient. + */ +class EaselManagerClientListener { +public: + virtual ~EaselManagerClientListener() {}; + + // Invoked when Easel encountered a fatal error. Client should shut down Easel. + virtual void onEaselFatalError(std::string errMsg) = 0; +}; + +} // namespace android + +#endif // EASEL_MANAGER_CLIENT_H diff --git a/camera/libhdrplusclient/include/HdrPlusClient.h b/camera/libhdrplusclient/include/HdrPlusClient.h new file mode 100644 index 0000000..962a5e8 --- /dev/null +++ b/camera/libhdrplusclient/include/HdrPlusClient.h @@ -0,0 +1,153 @@ +/* + * Copyright 2016 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 HDR_PLUS_CLIENT_H +#define HDR_PLUS_CLIENT_H + +#include "hardware/camera3.h" +#include "HdrPlusClientListener.h" +#include "HdrPlusTypes.h" + +namespace android { + +/** + * HdrPlusClient + * + * HdrPlusClient class can be used to connect to HDR+ service to perform HDR+ processing on + * Easel. + */ +class HdrPlusClient { +public: + HdrPlusClient() {}; + /* + * The recommended way to create an HdrPlusClient instance is via + * EaselManagerClient::openHdrPlusClientAsync() or EaselManagerClient::openHdrPlusClientAsync(). + * EaselManagerClient will make sure Easel is in a valid state to open an HDR+ client. To close + * an HdrPlusClient, use EaselManagerClient::closeHdrPlusClient. + */ + virtual ~HdrPlusClient() {}; + + /* + * Connect to HDR+ service. + * + * If EaselManagerClient is used to create the HdrPlusClient, it is already connected. + * + * listener is the listener to receive callbacks from HDR+ client. + * + * Returns: + * 0: on success. + * -EEXIST: if it's already connected. + * -ENODEV: if connecting failed due to a serious error. + */ + virtual status_t connect(HdrPlusClientListener *listener) = 0; + + // Disconnect from HDR+ service. + virtual void disconnect() = 0; + + /* + * Set the static metadata of current camera device. + * + * Must be called after connect() and before configuring streams. + * + * staticMetadata is the static metadata of current camera device. + * + * Returns: + * 0: on success. + * -ENODEV: if HDR+ service is not connected. + */ + virtual status_t setStaticMetadata(const camera_metadata_t &staticMetadata) = 0; + + /* + * Configure streams. + * + * Must be called when configuration changes including input (sensor) resolution and format, and + * output resolutions and formats. + * + * inputConfig contains the information about the input frames or sensor configurations. + * outputConfigs is a vector of output stream configurations. + * + * Returns: + * 0: on success. + * -EINVAL: if outputConfigs is empty or the configurations are not supported. + * -ENODEV: if HDR+ service is not connected. + */ + virtual status_t configureStreams(const pbcamera::InputConfiguration &inputConfig, + const std::vector<pbcamera::StreamConfiguration> &outputConfigs) = 0; + + /* + * Enable or disable ZSL HDR+ mode. + * + * When ZSL HDR+ mode is enabled, Easel will capture ZSL RAW buffers. ZSL HDR+ mode should be + * disabled to reduce power consumption when HDR+ processing is not necessary, e.g in video + * mode. + * + * enabled is a flag indicating whether to enable ZSL HDR+ mode. + * + * Returns: + * 0: on success. + * -ENODEV: if HDR+ service is not connected, or streams are not configured. + */ + virtual status_t setZslHdrPlusMode(bool enabled) = 0; + + /* + * Submit a capture request for HDR+ outputs. + * + * For each output buffer in CaptureRequest, it will be returned in a CaptureResult via + * HdrPlusClientListener::onCaptureResult(). HdrPlusClientListener::onCaptureResult() may be + * invoked multiple times to return all output buffers in one CaptureRequest. Each output + * buffer will be returned in CaptureResult only once. + * + * request is a CaptureRequest containing output buffers to be filled by HDR+ service. + * + * Returns: + * 0: on success. + * -EINVAL: if the request is invalid such as containing invalid stream IDs. + */ + virtual status_t submitCaptureRequest(pbcamera::CaptureRequest *request) = 0; + + /* + * Send an input buffer to HDR+ service. This is used when HDR+ service's input buffers come + * from the client rather than MIPI. + * + * inputBuffer is the input buffer to send to HDR+ service. After this method returns, the + * buffer has been copied (with DMA) to HDR+ service and the caller has the + * ownership of the buffer. + */ + virtual void notifyInputBuffer(const pbcamera::StreamBuffer &inputBuffer, + int64_t timestampNs) = 0; + + /* + * Notify about result metadata of a frame that AP captured. This may be called multiple times + * for a frame to send multiple partial metadata and lastMetadata must be false except for the + * last partial metadata. When there is only one metadata for a frame, lastMetadata must be + * true. + * + * frameNumber is a unique frame number that the metadata belong to. + * resultMetadata is the result metadata of a frame that AP captured. + * lastMetadata is a flag indicating whether this is the last metadata for the frame number. + */ + virtual void notifyFrameMetadata(uint32_t frameNumber, const camera_metadata_t &resultMetadata, + bool lastMetadata=true) = 0; + +private: + // Disallow copy and assign. + HdrPlusClient(const HdrPlusClient&) = delete; + void operator=(const HdrPlusClient&) = delete; +}; + +} // namespace android + +#endif // HDR_PLUS_CLIENT_H diff --git a/camera/libhdrplusclient/include/HdrPlusClientListener.h b/camera/libhdrplusclient/include/HdrPlusClientListener.h new file mode 100644 index 0000000..6531c9b --- /dev/null +++ b/camera/libhdrplusclient/include/HdrPlusClientListener.h @@ -0,0 +1,76 @@ +/* + * Copyright 2016 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 HDR_PLUS_CLIENT_LISTENER_H +#define HDR_PLUS_CLIENT_LISTENER_H + +#include "hardware/camera3.h" +#include "HdrPlusTypes.h" + +namespace android { + + +class HdrPlusClient; + +/* + * HdrPlusClientListener defines callbacks that will be invoked by HdrPlusClient for events like + * returning capture results. + */ +class HdrPlusClientListener { +public: + virtual ~HdrPlusClientListener() {}; + + /* + * Invoked when an HDR+ client is opened successfully via + * EaselManagerClient::openHdrPlusClientAsync. + */ + virtual void onOpened(std::unique_ptr<HdrPlusClient> client) = 0; + + /* + * Invoked when opening an HDR+ client failed via EaselManagerClient::openHdrPlusClientAsync. + * + * err is + * -EEXIST: if an HDR+ client is already opened. + * -ENODEV: if opening an HDR+ failed due to a serious error. + */ + virtual void onOpenFailed(status_t err) = 0; + + /* + * Invoked when HDR+ client is in a fatal error state. After receiving this error, calls to HDR+ + * client will not succeed and HDR+ client should be closed. + */ + virtual void onFatalError() = 0; + + /* + * Invoked when a CaptureResult, containing a subset or all output buffers for a CaptureRequest, + * is received. This may be invoked multiple times for one CaptureRequest but each CaptureResult + * will contain distinct output buffers that have not been received yet. + */ + virtual void onCaptureResult(pbcamera::CaptureResult *result, + const camera_metadata_t &resultMetadata) = 0; + + /* + * Invoked when a failed CaptureResult, containing a subset or all output buffers for a + * CaptureRequest, is received. Output buffers in a failed capture result may contain garbage + * data. This may be invoked multiple times for one CaptureRequest but each CaptureResult + * will contain distinct output buffers that have not been received yet. + */ + virtual void onFailedCaptureResult(pbcamera::CaptureResult *failedResult) = 0; +}; + +} // namespace android + +#endif // HDR_PLUS_CLIENT_LISTENER_H diff --git a/camera/libhdrplusclient/include/HdrPlusClientUtils.h b/camera/libhdrplusclient/include/HdrPlusClientUtils.h new file mode 100644 index 0000000..f56f380 --- /dev/null +++ b/camera/libhdrplusclient/include/HdrPlusClientUtils.h @@ -0,0 +1,45 @@ +/* + * Copyright 2016 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 HDR_PLUS_CLIENT_UTILS_H +#define HDR_PLUS_CLIENT_UTILS_H + +#include <utils/Errors.h> + +#include "HdrPlusTypes.h" + +namespace android { +namespace hdrplus_client_utils { + +/* + * Write the image buffer to a .ppm file. + * + * filename is the filename of the .ppm file and should include ".ppm" in the end. + * streamConfig is the stream configuration of the buffer. + * buffer is the buffer to be saved to a .ppm file. + * + * Returns + * OK: if the file is saved successfully. + * BAD_VALUE: if the format is not support or the stream configuration is invalid. + * NO_INIT: if it failed to open the file. + */ +status_t writePpm(const std::string &filename, const pbcamera::StreamConfiguration &streamConfig, + const pbcamera::StreamBuffer &buffer); + +} // hdrplus_client_utils +} // namespace android + +#endif // HDR_PLUS_CLIENT_UTILS_H |