- Derive HEIC capabilities from camera HAL and media framework. - Add HeicCompositeStream to encode camera buffers to HEIC buffers. - Add ExifUtils to overwrite JPEG APP segments and send to media codec. - Add NDK enums and corresponding format support. Test: Camera CTS Bug: 79465976 Change-Id: I0a885e76335f3eba4be0fd42241edb0b7349f284gugelfrei
parent
627cb60a9f
commit
68ac7ada1f
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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_CAMERA_CAMERA3_HEIC_COMPOSITE_STREAM_H
|
||||
#define ANDROID_SERVERS_CAMERA_CAMERA3_HEIC_COMPOSITE_STREAM_H
|
||||
|
||||
#include <queue>
|
||||
|
||||
#include <gui/IProducerListener.h>
|
||||
#include <gui/CpuConsumer.h>
|
||||
|
||||
#include <media/hardware/VideoAPI.h>
|
||||
#include <media/MediaCodecBuffer.h>
|
||||
#include <media/stagefright/foundation/ALooper.h>
|
||||
#include <media/stagefright/MediaCodec.h>
|
||||
#include <media/stagefright/MediaMuxer.h>
|
||||
|
||||
#include "CompositeStream.h"
|
||||
|
||||
namespace android {
|
||||
namespace camera3 {
|
||||
|
||||
class HeicCompositeStream : public CompositeStream, public Thread,
|
||||
public CpuConsumer::FrameAvailableListener {
|
||||
public:
|
||||
HeicCompositeStream(wp<CameraDeviceBase> device,
|
||||
wp<hardware::camera2::ICameraDeviceCallbacks> cb);
|
||||
~HeicCompositeStream() override;
|
||||
|
||||
static bool isHeicCompositeStream(const sp<Surface> &surface);
|
||||
|
||||
status_t createInternalStreams(const std::vector<sp<Surface>>& consumers,
|
||||
bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
|
||||
camera3_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
|
||||
std::vector<int> *surfaceIds, int streamSetId, bool isShared) override;
|
||||
|
||||
status_t deleteInternalStreams() override;
|
||||
|
||||
status_t configureStream() override;
|
||||
|
||||
status_t insertGbp(SurfaceMap* /*out*/outSurfaceMap, Vector<int32_t>* /*out*/outputStreamIds,
|
||||
int32_t* /*out*/currentStreamId) override;
|
||||
|
||||
void onShutter(const CaptureResultExtras& resultExtras, nsecs_t timestamp) override;
|
||||
|
||||
int getStreamId() override { return mMainImageStreamId; }
|
||||
|
||||
// Use onShutter to keep track of frame number <-> timestamp mapping.
|
||||
void onBufferReleased(const BufferInfo& bufferInfo) override;
|
||||
void onBufferRequestForFrameNumber(uint64_t frameNumber, int streamId,
|
||||
const CameraMetadata& settings) override;
|
||||
|
||||
// CpuConsumer listener implementation
|
||||
void onFrameAvailable(const BufferItem& item) override;
|
||||
|
||||
// Return stream information about the internal camera streams
|
||||
static status_t getCompositeStreamInfo(const OutputStreamInfo &streamInfo,
|
||||
const CameraMetadata& ch, std::vector<OutputStreamInfo>* compositeOutput /*out*/);
|
||||
|
||||
static bool isSizeSupportedByHeifEncoder(int32_t width, int32_t height,
|
||||
bool* useHeic, bool* useGrid, int64_t* stall);
|
||||
static bool isInMemoryTempFileSupported();
|
||||
protected:
|
||||
|
||||
bool threadLoop() override;
|
||||
bool onStreamBufferError(const CaptureResultExtras& resultExtras) override;
|
||||
void onResultError(const CaptureResultExtras& /*resultExtras*/) override {}
|
||||
|
||||
private:
|
||||
//
|
||||
// HEIC/HEVC Codec related structures, utility functions, and callbacks
|
||||
//
|
||||
struct CodecOutputBufferInfo {
|
||||
int32_t index;
|
||||
int32_t offset;
|
||||
int32_t size;
|
||||
int64_t timeUs;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct CodecInputBufferInfo {
|
||||
int32_t index;
|
||||
int64_t timeUs;
|
||||
size_t tileIndex;
|
||||
};
|
||||
|
||||
class CodecCallbackHandler : public AHandler {
|
||||
public:
|
||||
explicit CodecCallbackHandler(wp<HeicCompositeStream> parent) {
|
||||
mParent = parent;
|
||||
}
|
||||
virtual void onMessageReceived(const sp<AMessage> &msg);
|
||||
private:
|
||||
wp<HeicCompositeStream> mParent;
|
||||
};
|
||||
|
||||
enum {
|
||||
kWhatCallbackNotify,
|
||||
};
|
||||
|
||||
bool mUseHeic;
|
||||
sp<MediaCodec> mCodec;
|
||||
sp<ALooper> mCodecLooper, mCallbackLooper;
|
||||
sp<CodecCallbackHandler> mCodecCallbackHandler;
|
||||
sp<AMessage> mAsyncNotify;
|
||||
sp<AMessage> mFormat;
|
||||
size_t mNumOutputTiles;
|
||||
|
||||
int32_t mOutputWidth, mOutputHeight;
|
||||
size_t mMaxHeicBufferSize;
|
||||
int32_t mGridWidth, mGridHeight;
|
||||
size_t mGridRows, mGridCols;
|
||||
bool mUseGrid; // Whether to use framework YUV frame tiling.
|
||||
|
||||
static const int64_t kNoFrameDropMaxPtsGap = -1000000;
|
||||
static const int32_t kNoGridOpRate = 30;
|
||||
static const int32_t kGridOpRate = 120;
|
||||
|
||||
void onHeicOutputFrameAvailable(const CodecOutputBufferInfo& bufferInfo);
|
||||
void onHeicInputFrameAvailable(int32_t index); // Only called for YUV input mode.
|
||||
void onHeicFormatChanged(sp<AMessage>& newFormat);
|
||||
void onHeicCodecError();
|
||||
|
||||
status_t initializeCodec(uint32_t width, uint32_t height,
|
||||
const sp<CameraDeviceBase>& cameraDevice);
|
||||
void deinitCodec();
|
||||
|
||||
//
|
||||
// Composite stream related structures, utility functions and callbacks.
|
||||
//
|
||||
struct InputFrame {
|
||||
int32_t orientation;
|
||||
int32_t quality;
|
||||
|
||||
CpuConsumer::LockedBuffer appSegmentBuffer;
|
||||
std::vector<CodecOutputBufferInfo> codecOutputBuffers;
|
||||
|
||||
// Fields that are only applicable to HEVC tiling.
|
||||
CpuConsumer::LockedBuffer yuvBuffer;
|
||||
std::vector<CodecInputBufferInfo> codecInputBuffers;
|
||||
|
||||
bool error;
|
||||
bool errorNotified;
|
||||
int64_t frameNumber;
|
||||
|
||||
sp<MediaMuxer> muxer;
|
||||
int fenceFd;
|
||||
int fileFd;
|
||||
ssize_t trackIndex;
|
||||
ANativeWindowBuffer *anb;
|
||||
|
||||
bool appSegmentWritten;
|
||||
size_t pendingOutputTiles;
|
||||
size_t codecInputCounter;
|
||||
|
||||
InputFrame() : orientation(0), quality(kDefaultJpegQuality), error(false),
|
||||
errorNotified(false), frameNumber(-1), fenceFd(-1), fileFd(-1),
|
||||
trackIndex(-1), anb(nullptr), appSegmentWritten(false),
|
||||
pendingOutputTiles(0), codecInputCounter(0) { }
|
||||
};
|
||||
|
||||
void compilePendingInputLocked();
|
||||
// Find first complete and valid frame with smallest timestamp
|
||||
bool getNextReadyInputLocked(int64_t *currentTs /*out*/);
|
||||
// Find next failing frame number with smallest timestamp and return respective frame number
|
||||
int64_t getNextFailingInputLocked(int64_t *currentTs /*out*/);
|
||||
|
||||
status_t processInputFrame(nsecs_t timestamp, InputFrame &inputFrame);
|
||||
status_t processCodecInputFrame(InputFrame &inputFrame);
|
||||
status_t startMuxerForInputFrame(nsecs_t timestamp, InputFrame &inputFrame);
|
||||
status_t processAppSegment(nsecs_t timestamp, InputFrame &inputFrame);
|
||||
status_t processOneCodecOutputFrame(nsecs_t timestamp, InputFrame &inputFrame);
|
||||
status_t processCompletedInputFrame(nsecs_t timestamp, InputFrame &inputFrame);
|
||||
|
||||
void releaseInputFrameLocked(InputFrame *inputFrame /*out*/);
|
||||
void releaseInputFramesLocked(int64_t currentTs);
|
||||
|
||||
size_t findAppSegmentsSize(const uint8_t* appSegmentBuffer, size_t maxSize,
|
||||
size_t* app1SegmentSize);
|
||||
int64_t findTimestampInNsLocked(int64_t timeInUs);
|
||||
status_t copyOneYuvTile(sp<MediaCodecBuffer>& codecBuffer,
|
||||
const CpuConsumer::LockedBuffer& yuvBuffer,
|
||||
size_t top, size_t left, size_t width, size_t height);
|
||||
static size_t calcAppSegmentMaxSize(const CameraMetadata& info);
|
||||
|
||||
static const nsecs_t kWaitDuration = 10000000; // 10 ms
|
||||
static const int32_t kDefaultJpegQuality = 99;
|
||||
static const auto kJpegDataSpace = HAL_DATASPACE_V0_JFIF;
|
||||
static const android_dataspace kAppSegmentDataSpace =
|
||||
static_cast<android_dataspace>(HAL_DATASPACE_JPEG_APP_SEGMENTS);
|
||||
static const android_dataspace kHeifDataSpace =
|
||||
static_cast<android_dataspace>(HAL_DATASPACE_HEIF);
|
||||
|
||||
int mAppSegmentStreamId, mAppSegmentSurfaceId;
|
||||
sp<CpuConsumer> mAppSegmentConsumer;
|
||||
sp<Surface> mAppSegmentSurface;
|
||||
bool mAppSegmentBufferAcquired;
|
||||
size_t mAppSegmentMaxSize;
|
||||
|
||||
int mMainImageStreamId, mMainImageSurfaceId;
|
||||
sp<Surface> mMainImageSurface;
|
||||
sp<CpuConsumer> mMainImageConsumer; // Only applicable for HEVC codec.
|
||||
bool mYuvBufferAcquired; // Only applicable to HEVC codec
|
||||
|
||||
sp<Surface> mOutputSurface;
|
||||
sp<ProducerListener> mProducerListener;
|
||||
|
||||
|
||||
// Map from frame number to JPEG setting of orientation+quality
|
||||
std::map<int64_t, std::pair<int32_t, int32_t>> mSettingsByFrameNumber;
|
||||
// Map from timestamp to JPEG setting of orientation+quality
|
||||
std::map<int64_t, std::pair<int32_t, int32_t>> mSettingsByTimestamp;
|
||||
|
||||
// Keep all incoming APP segment Blob buffer pending further processing.
|
||||
std::vector<int64_t> mInputAppSegmentBuffers;
|
||||
|
||||
// Keep all incoming HEIC blob buffer pending further processing.
|
||||
std::vector<CodecOutputBufferInfo> mCodecOutputBuffers;
|
||||
std::queue<int64_t> mCodecOutputBufferTimestamps;
|
||||
size_t mOutputBufferCounter;
|
||||
|
||||
// Keep all incoming Yuv buffer pending tiling and encoding (for HEVC YUV tiling only)
|
||||
std::vector<int64_t> mInputYuvBuffers;
|
||||
// Keep all codec input buffers ready to be filled out (for HEVC YUV tiling only)
|
||||
std::vector<int32_t> mCodecInputBuffers;
|
||||
|
||||
// Artificial strictly incremental YUV grid timestamp to make encoder happy.
|
||||
int64_t mGridTimestampUs;
|
||||
|
||||
// In most common use case, entries are accessed in order.
|
||||
std::map<int64_t, InputFrame> mPendingInputFrames;
|
||||
};
|
||||
|
||||
}; // namespace camera3
|
||||
}; // namespace android
|
||||
|
||||
#endif //ANDROID_SERVERS_CAMERA_CAMERA3_HEIC_COMPOSITE_STREAM_H
|
@ -0,0 +1,294 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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 "HeicEncoderInfoManager"
|
||||
//#define LOG_NDEBUG 0
|
||||
|
||||
#include <cstdint>
|
||||
#include <regex>
|
||||
|
||||
#include <cutils/properties.h>
|
||||
#include <log/log_main.h>
|
||||
#include <system/graphics.h>
|
||||
|
||||
#include <media/stagefright/MediaCodecList.h>
|
||||
#include <media/stagefright/foundation/MediaDefs.h>
|
||||
#include <media/stagefright/foundation/ABuffer.h>
|
||||
|
||||
#include "HeicEncoderInfoManager.h"
|
||||
|
||||
namespace android {
|
||||
namespace camera3 {
|
||||
|
||||
HeicEncoderInfoManager::HeicEncoderInfoManager() :
|
||||
mIsInited(false),
|
||||
mMinSizeHeic(0, 0),
|
||||
mMaxSizeHeic(INT32_MAX, INT32_MAX),
|
||||
mHasHEVC(false),
|
||||
mHasHEIC(false),
|
||||
mDisableGrid(false) {
|
||||
if (initialize() == OK) {
|
||||
mIsInited = true;
|
||||
}
|
||||
}
|
||||
|
||||
HeicEncoderInfoManager::~HeicEncoderInfoManager() {
|
||||
}
|
||||
|
||||
bool HeicEncoderInfoManager::isSizeSupported(int32_t width, int32_t height, bool* useHeic,
|
||||
bool* useGrid, int64_t* stall) const {
|
||||
if (useHeic == nullptr || useGrid == nullptr) {
|
||||
ALOGE("%s: invalid parameters: useHeic %p, useGrid %p",
|
||||
__FUNCTION__, useHeic, useGrid);
|
||||
return false;
|
||||
}
|
||||
if (!mIsInited) return false;
|
||||
|
||||
bool chooseHeic = false, enableGrid = true;
|
||||
if (mHasHEIC && width >= mMinSizeHeic.first &&
|
||||
height >= mMinSizeHeic.second && width <= mMaxSizeHeic.first &&
|
||||
height <= mMaxSizeHeic.second) {
|
||||
chooseHeic = true;
|
||||
enableGrid = false;
|
||||
} else if (mHasHEVC) {
|
||||
bool fullSizeSupportedByHevc = (width >= mMinSizeHevc.first &&
|
||||
height >= mMinSizeHevc.second &&
|
||||
width <= mMaxSizeHevc.first &&
|
||||
height <= mMaxSizeHevc.second);
|
||||
if (fullSizeSupportedByHevc && (mDisableGrid ||
|
||||
(width <= 1920 && height <= 1080))) {
|
||||
enableGrid = false;
|
||||
}
|
||||
} else {
|
||||
// No encoder available for the requested size.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (stall != nullptr) {
|
||||
// Find preferred encoder which advertise
|
||||
// "measured-frame-rate-WIDTHxHEIGHT-range" key.
|
||||
const FrameRateMaps& maps =
|
||||
(chooseHeic && mHeicFrameRateMaps.size() > 0) ?
|
||||
mHeicFrameRateMaps : mHevcFrameRateMaps;
|
||||
const auto& closestSize = findClosestSize(maps, width, height);
|
||||
if (closestSize == maps.end()) {
|
||||
// The "measured-frame-rate-WIDTHxHEIGHT-range" key is optional.
|
||||
// Hardcode to some default value (3.33ms * tile count) based on resolution.
|
||||
*stall = 3333333LL * width * height / (kGridWidth * kGridHeight);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Derive stall durations based on average fps of the closest size.
|
||||
constexpr int64_t NSEC_PER_SEC = 1000000000LL;
|
||||
int32_t avgFps = (closestSize->second.first + closestSize->second.second)/2;
|
||||
float ratio = 1.0f * width * height /
|
||||
(closestSize->first.first * closestSize->first.second);
|
||||
*stall = ratio * NSEC_PER_SEC / avgFps;
|
||||
}
|
||||
|
||||
*useHeic = chooseHeic;
|
||||
*useGrid = enableGrid;
|
||||
return true;
|
||||
}
|
||||
|
||||
status_t HeicEncoderInfoManager::initialize() {
|
||||
mDisableGrid = property_get_bool("camera.heic.disable_grid", false);
|
||||
sp<IMediaCodecList> codecsList = MediaCodecList::getInstance();
|
||||
if (codecsList == nullptr) {
|
||||
// No media codec available.
|
||||
return OK;
|
||||
}
|
||||
|
||||
sp<AMessage> heicDetails = getCodecDetails(codecsList, MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC);
|
||||
sp<AMessage> hevcDetails = getCodecDetails(codecsList, MEDIA_MIMETYPE_VIDEO_HEVC);
|
||||
|
||||
if (hevcDetails == nullptr) {
|
||||
if (heicDetails != nullptr) {
|
||||
ALOGE("%s: Device must support HEVC codec if HEIC codec is available!",
|
||||
__FUNCTION__);
|
||||
return BAD_VALUE;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
// Check CQ mode for HEVC codec
|
||||
{
|
||||
AString bitrateModes;
|
||||
auto hasItem = hevcDetails->findString("feature-bitrate-modes", &bitrateModes);
|
||||
if (!hasItem) {
|
||||
ALOGE("%s: Failed to query bitrate modes for HEVC codec", __FUNCTION__);
|
||||
return BAD_VALUE;
|
||||
}
|
||||
ALOGV("%s: HEVC codec's feature-bitrate-modes value is %d, %s",
|
||||
__FUNCTION__, hasItem, bitrateModes.c_str());
|
||||
std::regex pattern("(^|,)CQ($|,)", std::regex_constants::icase);
|
||||
if (!std::regex_search(bitrateModes.c_str(), pattern)) {
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
// HEIC size range
|
||||
if (heicDetails != nullptr) {
|
||||
auto res = getCodecSizeRange(MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC,
|
||||
heicDetails, &mMinSizeHeic, &mMaxSizeHeic, &mHeicFrameRateMaps);
|
||||
if (res != OK) {
|
||||
ALOGE("%s: Failed to get HEIC codec size range: %s (%d)", __FUNCTION__,
|
||||
strerror(-res), res);
|
||||
return BAD_VALUE;
|
||||
}
|
||||
mHasHEIC = true;
|
||||
}
|
||||
|
||||
// HEVC size range
|
||||
{
|
||||
auto res = getCodecSizeRange(MEDIA_MIMETYPE_VIDEO_HEVC,
|
||||
hevcDetails, &mMinSizeHevc, &mMaxSizeHevc, &mHevcFrameRateMaps);
|
||||
if (res != OK) {
|
||||
ALOGE("%s: Failed to get HEVC codec size range: %s (%d)", __FUNCTION__,
|
||||
strerror(-res), res);
|
||||
return BAD_VALUE;
|
||||
}
|
||||
|
||||
mHasHEVC = true;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
status_t HeicEncoderInfoManager::getFrameRateMaps(sp<AMessage> details, FrameRateMaps* maps) {
|
||||
if (details == nullptr || maps == nullptr) {
|
||||
ALOGE("%s: Invalid input: details: %p, maps: %p", __FUNCTION__, details.get(), maps);
|
||||
return BAD_VALUE;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < details->countEntries(); i++) {
|
||||
AMessage::Type type;
|
||||
const char* entryName = details->getEntryNameAt(i, &type);
|
||||
if (type != AMessage::kTypeString) continue;
|
||||
std::regex frameRateNamePattern("measured-frame-rate-([0-9]+)[*x]([0-9]+)-range",
|
||||
std::regex_constants::icase);
|
||||
std::cmatch sizeMatch;
|
||||
if (std::regex_match(entryName, sizeMatch, frameRateNamePattern) &&
|
||||
sizeMatch.size() == 3) {
|
||||
AMessage::ItemData item = details->getEntryAt(i);
|
||||
AString fpsRangeStr;
|
||||
if (item.find(&fpsRangeStr)) {
|
||||
ALOGV("%s: %s", entryName, fpsRangeStr.c_str());
|
||||
std::regex frameRatePattern("([0-9]+)-([0-9]+)");
|
||||
std::cmatch fpsMatch;
|
||||
if (std::regex_match(fpsRangeStr.c_str(), fpsMatch, frameRatePattern) &&
|
||||
fpsMatch.size() == 3) {
|
||||
maps->emplace(
|
||||
std::make_pair(stoi(sizeMatch[1]), stoi(sizeMatch[2])),
|
||||
std::make_pair(stoi(fpsMatch[1]), stoi(fpsMatch[2])));
|
||||
} else {
|
||||
return BAD_VALUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
status_t HeicEncoderInfoManager::getCodecSizeRange(
|
||||
const char* codecName,
|
||||
sp<AMessage> details,
|
||||
std::pair<int32_t, int32_t>* minSize,
|
||||
std::pair<int32_t, int32_t>* maxSize,
|
||||
FrameRateMaps* frameRateMaps) {
|
||||
if (codecName == nullptr || minSize == nullptr || maxSize == nullptr ||
|
||||
details == nullptr || frameRateMaps == nullptr) {
|
||||
return BAD_VALUE;
|
||||
}
|
||||
|
||||
AString sizeRange;
|
||||
auto hasItem = details->findString("size-range", &sizeRange);
|
||||
if (!hasItem) {
|
||||
ALOGE("%s: Failed to query size range for codec %s", __FUNCTION__, codecName);
|
||||
return BAD_VALUE;
|
||||
}
|
||||
ALOGV("%s: %s codec's size range is %s", __FUNCTION__, codecName, sizeRange.c_str());
|
||||
std::regex pattern("([0-9]+)[*x]([0-9]+)-([0-9]+)[*x]([0-9]+)");
|
||||
std::cmatch match;
|
||||
if (std::regex_match(sizeRange.c_str(), match, pattern)) {
|
||||
if (match.size() == 5) {
|
||||
minSize->first = stoi(match[1]);
|
||||
minSize->second = stoi(match[2]);
|
||||
maxSize->first = stoi(match[3]);
|
||||
maxSize->second = stoi(match[4]);
|
||||
if (minSize->first > maxSize->first ||
|
||||
minSize->second > maxSize->second) {
|
||||
ALOGE("%s: Invalid %s code size range: %s",
|
||||
__FUNCTION__, codecName, sizeRange.c_str());
|
||||
return BAD_VALUE;
|
||||
}
|
||||
} else {
|
||||
return BAD_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
auto res = getFrameRateMaps(details, frameRateMaps);
|
||||
if (res != OK) {
|
||||
return res;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
HeicEncoderInfoManager::FrameRateMaps::const_iterator HeicEncoderInfoManager::findClosestSize(
|
||||
const FrameRateMaps& maps, int32_t width, int32_t height) const {
|
||||
int32_t minDiff = INT32_MAX;
|
||||
FrameRateMaps::const_iterator closestIter = maps.begin();
|
||||
for (auto iter = maps.begin(); iter != maps.end(); iter++) {
|
||||
// Use area difference between the sizes to approximate size
|
||||
// difference.
|
||||
int32_t diff = abs(iter->first.first * iter->first.second - width * height);
|
||||
if (diff < minDiff) {
|
||||
closestIter = iter;
|
||||
minDiff = diff;
|
||||
}
|
||||
}
|
||||
return closestIter;
|
||||
}
|
||||
|
||||
sp<AMessage> HeicEncoderInfoManager::getCodecDetails(
|
||||
sp<IMediaCodecList> codecsList, const char* name) {
|
||||
ssize_t idx = codecsList->findCodecByType(name, true /*encoder*/);
|
||||
if (idx < 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const sp<MediaCodecInfo> info = codecsList->getCodecInfo(idx);
|
||||
if (info == nullptr) {
|
||||
ALOGE("%s: Failed to get codec info for %s", __FUNCTION__, name);
|
||||
return nullptr;
|
||||
}
|
||||
const sp<MediaCodecInfo::Capabilities> caps =
|
||||
info->getCapabilitiesFor(name);
|
||||
if (caps == nullptr) {
|
||||
ALOGE("%s: Failed to get capabilities for codec %s", __FUNCTION__, name);
|
||||
return nullptr;
|
||||
}
|
||||
const sp<AMessage> details = caps->getDetails();
|
||||
if (details == nullptr) {
|
||||
ALOGE("%s: Failed to get details for codec %s", __FUNCTION__, name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return details;
|
||||
}
|
||||
} //namespace camera3
|
||||
} // namespace android
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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_CAMERA_HEICENCODER_INFO_MANAGER_H
|
||||
#define ANDROID_SERVERS_CAMERA_HEICENCODER_INFO_MANAGER_H
|
||||
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/StrongPointer.h>
|
||||
|
||||
#include <media/IMediaCodecList.h>
|
||||
#include <media/stagefright/foundation/AMessage.h>
|
||||
|
||||
namespace android {
|
||||
namespace camera3 {
|
||||
|
||||
class HeicEncoderInfoManager {
|
||||
public:
|
||||
static HeicEncoderInfoManager& getInstance() {
|
||||
static HeicEncoderInfoManager instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
bool isSizeSupported(int32_t width, int32_t height,
|
||||
bool* useHeic, bool* useGrid, int64_t* stall) const;
|
||||
|
||||
static const auto kGridWidth = 512;
|
||||
static const auto kGridHeight = 512;
|
||||
private:
|
||||
struct SizePairHash {
|
||||
std::size_t operator () (const std::pair<int32_t,int32_t> &p) const {
|
||||
return p.first * 31 + p.second;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::unordered_map<std::pair<int32_t, int32_t>,
|
||||
std::pair<int32_t, int32_t>, SizePairHash> FrameRateMaps;
|
||||
|
||||
HeicEncoderInfoManager();
|
||||
virtual ~HeicEncoderInfoManager();
|
||||
|
||||
status_t initialize();
|
||||
status_t getFrameRateMaps(sp<AMessage> details, FrameRateMaps* maps);
|
||||
status_t getCodecSizeRange(const char* codecName, sp<AMessage> details,
|
||||
std::pair<int32_t, int32_t>* minSize, std::pair<int32_t, int32_t>* maxSize,
|
||||
FrameRateMaps* frameRateMaps);
|
||||
FrameRateMaps::const_iterator findClosestSize(const FrameRateMaps& maps,
|
||||
int32_t width, int32_t height) const;
|
||||
sp<AMessage> getCodecDetails(sp<IMediaCodecList> codecsList, const char* name);
|
||||
|
||||
bool mIsInited;
|
||||
std::pair<int32_t, int32_t> mMinSizeHeic, mMaxSizeHeic;
|
||||
std::pair<int32_t, int32_t> mMinSizeHevc, mMaxSizeHevc;
|
||||
bool mHasHEVC, mHasHEIC;
|
||||
FrameRateMaps mHeicFrameRateMaps, mHevcFrameRateMaps;
|
||||
bool mDisableGrid;
|
||||
|
||||
};
|
||||
|
||||
} // namespace camera3
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_SERVERS_CAMERA_HEICENCODER_INFO_MANAGER_H
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,245 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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_CAMERA_EXIF_UTILS_H
|
||||
#define ANDROID_SERVERS_CAMERA_EXIF_UTILS_H
|
||||
|
||||
#include "CameraMetadata.h"
|
||||
|
||||
namespace android {
|
||||
namespace camera3 {
|
||||
|
||||
// This is based on the camera HIDL shim implementation, which was in turned
|
||||
// based on original ChromeOS ARC implementation of a V4L2 HAL
|
||||
|
||||
// ExifUtils can override APP1 segment with tags which caller set. ExifUtils can
|
||||
// also add a thumbnail in the APP1 segment if thumbnail size is specified.
|
||||
// ExifUtils can be reused with different images by calling initialize().
|
||||
//
|
||||
// Example of using this class :
|
||||
// std::unique_ptr<ExifUtils> utils(ExifUtils::Create());
|
||||
// utils->initialize(const unsigned char* app1Segment, size_t app1SegmentSize);
|
||||
// ...
|
||||
// // Call ExifUtils functions to set Exif tags.
|
||||
// ...
|
||||
// utils->GenerateApp1();
|
||||
// unsigned int app1Length = utils->GetApp1Length();
|
||||
// uint8_t* app1Buffer = new uint8_t[app1Length];
|
||||
// memcpy(app1Buffer, utils->GetApp1Buffer(), app1Length);
|
||||
class ExifUtils {
|
||||
|
||||
public:
|
||||
virtual ~ExifUtils();
|
||||
|
||||
static ExifUtils* create();
|
||||
|
||||
// Initialize() can be called multiple times. The setting of Exif tags will be
|
||||
// cleared.
|
||||
virtual bool initialize(const unsigned char *app1Segment, size_t app1SegmentSize) = 0;
|
||||
|
||||
// Set all known fields from a metadata structure
|
||||
virtual bool setFromMetadata(const CameraMetadata& metadata,
|
||||
const size_t imageWidth, const size_t imageHeight) = 0;
|
||||
|
||||
// Sets the len aperture.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setAperture(uint32_t numerator, uint32_t denominator) = 0;
|
||||
|
||||
// Sets the value of brightness.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setBrightness(int32_t numerator, int32_t denominator) = 0;
|
||||
|
||||
// Sets the color space.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setColorSpace(uint16_t color_space) = 0;
|
||||
|
||||
// Sets the information to compressed data.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setComponentsConfiguration(const std::string& components_configuration) = 0;
|
||||
|
||||
// Sets the compression scheme used for the image data.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setCompression(uint16_t compression) = 0;
|
||||
|
||||
// Sets image contrast.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setContrast(uint16_t contrast) = 0;
|
||||
|
||||
// Sets the date and time of image last modified. It takes local time. The
|
||||
// name of the tag is DateTime in IFD0.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setDateTime(const struct tm& t) = 0;
|
||||
|
||||
// Sets the image description.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setDescription(const std::string& description) = 0;
|
||||
|
||||
// Sets the digital zoom ratio. If the numerator is 0, it means digital zoom
|
||||
// was not used.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setDigitalZoomRatio(uint32_t numerator, uint32_t denominator) = 0;
|
||||
|
||||
// Sets the exposure bias.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setExposureBias(int32_t numerator, int32_t denominator) = 0;
|
||||
|
||||
// Sets the exposure mode set when the image was shot.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setExposureMode(uint16_t exposure_mode) = 0;
|
||||
|
||||
// Sets the program used by the camera to set exposure when the picture is
|
||||
// taken.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setExposureProgram(uint16_t exposure_program) = 0;
|
||||
|
||||
// Sets the exposure time, given in seconds.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setExposureTime(uint32_t numerator, uint32_t denominator) = 0;
|
||||
|
||||
// Sets the status of flash.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setFlash(uint16_t flash) = 0;
|
||||
|
||||
// Sets the F number.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setFNumber(uint32_t numerator, uint32_t denominator) = 0;
|
||||
|
||||
// Sets the focal length of lens used to take the image in millimeters.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setFocalLength(uint32_t numerator, uint32_t denominator) = 0;
|
||||
|
||||
// Sets the degree of overall image gain adjustment.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setGainControl(uint16_t gain_control) = 0;
|
||||
|
||||
// Sets the altitude in meters.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setGpsAltitude(double altitude) = 0;
|
||||
|
||||
// Sets the latitude with degrees minutes seconds format.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setGpsLatitude(double latitude) = 0;
|
||||
|
||||
// Sets the longitude with degrees minutes seconds format.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setGpsLongitude(double longitude) = 0;
|
||||
|
||||
// Sets GPS processing method.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setGpsProcessingMethod(const std::string& method) = 0;
|
||||
|
||||
// Sets GPS date stamp and time stamp (atomic clock). It takes UTC time.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setGpsTimestamp(const struct tm& t) = 0;
|
||||
|
||||
// Sets the height (number of rows) of main image.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setImageHeight(uint32_t length) = 0;
|
||||
|
||||
// Sets the width (number of columns) of main image.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setImageWidth(uint32_t width) = 0;
|
||||
|
||||
// Sets the ISO speed.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setIsoSpeedRating(uint16_t iso_speed_ratings) = 0;
|
||||
|
||||
// Sets the kind of light source.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setLightSource(uint16_t light_source) = 0;
|
||||
|
||||
// Sets the smallest F number of the lens.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setMaxAperture(uint32_t numerator, uint32_t denominator) = 0;
|
||||
|
||||
// Sets the metering mode.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setMeteringMode(uint16_t metering_mode) = 0;
|
||||
|
||||
// Sets image orientation.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setOrientation(uint16_t orientation) = 0;
|
||||
|
||||
// Sets the unit for measuring XResolution and YResolution.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setResolutionUnit(uint16_t resolution_unit) = 0;
|
||||
|
||||
// Sets image saturation.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setSaturation(uint16_t saturation) = 0;
|
||||
|
||||
// Sets the type of scene that was shot.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setSceneCaptureType(uint16_t type) = 0;
|
||||
|
||||
// Sets image sharpness.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setSharpness(uint16_t sharpness) = 0;
|
||||
|
||||
// Sets the shutter speed.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setShutterSpeed(int32_t numerator, int32_t denominator) = 0;
|
||||
|
||||
// Sets the distance to the subject, given in meters.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setSubjectDistance(uint32_t numerator, uint32_t denominator) = 0;
|
||||
|
||||
// Sets the fractions of seconds for the <DateTime> tag.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setSubsecTime(const std::string& subsec_time) = 0;
|
||||
|
||||
// Sets the white balance mode set when the image was shot.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setWhiteBalance(uint16_t white_balance) = 0;
|
||||
|
||||
// Sets the number of pixels per resolution unit in the image width.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setXResolution(uint32_t numerator, uint32_t denominator) = 0;
|
||||
|
||||
// Sets the position of chrominance components in relation to the luminance
|
||||
// component.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setYCbCrPositioning(uint16_t ycbcr_positioning) = 0;
|
||||
|
||||
// Sets the number of pixels per resolution unit in the image length.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setYResolution(uint32_t numerator, uint32_t denominator) = 0;
|
||||
|
||||
// Sets the manufacturer of camera.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setMake(const std::string& make) = 0;
|
||||
|
||||
// Sets the model number of camera.
|
||||
// Returns false if memory allocation fails.
|
||||
virtual bool setModel(const std::string& model) = 0;
|
||||
|
||||
// Generates APP1 segment.
|
||||
// Returns false if generating APP1 segment fails.
|
||||
virtual bool generateApp1() = 0;
|
||||
|
||||
// Gets buffer of APP1 segment. This method must be called only after calling
|
||||
// GenerateAPP1().
|
||||
virtual const uint8_t* getApp1Buffer() = 0;
|
||||
|
||||
// Gets length of APP1 segment. This method must be called only after calling
|
||||
// GenerateAPP1().
|
||||
virtual unsigned int getApp1Length() = 0;
|
||||
};
|
||||
|
||||
} // namespace camera3
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_SERVERS_CAMERA_EXIF_UTILS_H
|
Loading…
Reference in new issue