mirror of
https://gitee.com/openharmony/multimedia_image_framework
synced 2024-11-23 15:10:26 +00:00
Jpeg Decode Performance Optimization
Issue: https://gitee.com/openharmony/multimedia_image_framework/issues/IAZ2X5 Signed-off-by: caochuan <caochuan@huawei.com> Change-Id: If79d805d7057116e371bcd038f976457e1e7f927
This commit is contained in:
parent
ea69e9f32d
commit
5a7b2f22ba
@ -158,6 +158,7 @@ static const uint32_t MAX_SOURCE_SIZE = 300 * 1024 * 1024;
|
||||
constexpr uint8_t ASTC_EXTEND_INFO_TLV_NUM = 1; // curren only one group TLV
|
||||
constexpr uint32_t ASTC_EXTEND_INFO_SIZE_DEFINITION_LENGTH = 4; // 4 bytes to discripte for extend info summary bytes
|
||||
constexpr uint32_t ASTC_EXTEND_INFO_LENGTH_LENGTH = 4; // 4 bytes to discripte the content bytes for every TLV group
|
||||
static constexpr uint32_t SINGLE_FRAME_SIZE = 1;
|
||||
|
||||
struct AstcExtendInfo {
|
||||
uint32_t extendBufferSumBytes = 0;
|
||||
@ -4442,31 +4443,57 @@ void ImageSource::DecodeHeifAuxiliaryPictures(
|
||||
}
|
||||
}
|
||||
|
||||
void ImageSource::DecodeJpegAuxiliaryPicture(
|
||||
std::set<AuxiliaryPictureType> &auxTypes, std::unique_ptr<Picture> &picture, uint32_t &errorCode)
|
||||
static bool OnlyDecodeGainmap(std::set<AuxiliaryPictureType> &auxTypes)
|
||||
{
|
||||
uint8_t *streamBuffer = sourceStreamPtr_->GetDataPtr();
|
||||
uint32_t streamSize = sourceStreamPtr_->GetStreamSize();
|
||||
auto jpegMpfParser = std::make_unique<JpegMpfParser>();
|
||||
if (!jpegMpfParser->ParsingAuxiliaryPictures(streamBuffer, streamSize, false)) {
|
||||
IMAGE_LOGE("Jpeg parse auxiliary pictures failed!");
|
||||
errorCode = ERR_IMAGE_DATA_ABNORMAL;
|
||||
return;
|
||||
return auxTypes.size() == SINGLE_FRAME_SIZE && auxTypes.find(AuxiliaryPictureType::GAINMAP) != auxTypes.end();
|
||||
}
|
||||
|
||||
static std::vector<SingleJpegImage> ParsingJpegAuxiliaryPictures(uint8_t *stream, uint32_t streamSize,
|
||||
std::set<AuxiliaryPictureType> &auxTypes, ImageHdrType hdrType)
|
||||
{
|
||||
ImageTrace imageTrace("%s", __func__);
|
||||
if (stream == nullptr || streamSize == 0) {
|
||||
IMAGE_LOGE("No source stream when parsing auxiliary pictures");
|
||||
return {};
|
||||
}
|
||||
if (sourceHdrType_ > ImageHdrType::SDR) {
|
||||
auto jpegMpfParser = std::make_unique<JpegMpfParser>();
|
||||
if (!OnlyDecodeGainmap(auxTypes) && !jpegMpfParser->ParsingAuxiliaryPictures(stream, streamSize, false)) {
|
||||
IMAGE_LOGE("JpegMpfParser parse auxiliary pictures failed!");
|
||||
jpegMpfParser->images_.clear();
|
||||
}
|
||||
if (hdrType > ImageHdrType::SDR) {
|
||||
uint32_t gainmapStreamSize = streamSize;
|
||||
for (auto &image : jpegMpfParser->images_) {
|
||||
gainmapStreamSize = std::min(gainmapStreamSize, image.offset);
|
||||
}
|
||||
SingleJpegImage gainmapImage = {
|
||||
.offset = mainDecoder_->GetGainMapOffset(),
|
||||
.size = streamSize - mainDecoder_->GetGainMapOffset(),
|
||||
.offset = 0,
|
||||
.size = gainmapStreamSize,
|
||||
.auxType = AuxiliaryPictureType::GAINMAP,
|
||||
.auxTagName = AUXILIARY_TAG_GAINMAP,
|
||||
};
|
||||
jpegMpfParser->images_.push_back(gainmapImage);
|
||||
}
|
||||
return jpegMpfParser->images_;
|
||||
}
|
||||
|
||||
void ImageSource::DecodeJpegAuxiliaryPicture(
|
||||
std::set<AuxiliaryPictureType> &auxTypes, std::unique_ptr<Picture> &picture, uint32_t &errorCode)
|
||||
{
|
||||
uint8_t *streamBuffer = sourceStreamPtr_->GetDataPtr();
|
||||
uint32_t streamSize = sourceStreamPtr_->GetStreamSize();
|
||||
if (streamBuffer == nullptr || streamSize == 0) {
|
||||
IMAGE_LOGE("Jpeg source stream is invalid!");
|
||||
errorCode = ERR_IMAGE_DATA_ABNORMAL;
|
||||
return;
|
||||
}
|
||||
streamBuffer += mainDecoder_->GetGainMapOffset();
|
||||
streamSize -= mainDecoder_->GetGainMapOffset();
|
||||
auto auxInfos = ParsingJpegAuxiliaryPictures(streamBuffer, streamSize, auxTypes, sourceHdrType_);
|
||||
MainPictureInfo mainInfo;
|
||||
mainInfo.hdrType = sourceHdrType_;
|
||||
picture->GetMainPixel()->GetImageInfo(mainInfo.imageInfo);
|
||||
for (auto &auxInfo : jpegMpfParser->images_) {
|
||||
for (auto &auxInfo : auxInfos) {
|
||||
if (auxTypes.find(auxInfo.auxType) == auxTypes.end()) {
|
||||
continue;
|
||||
}
|
||||
|
@ -71,7 +71,6 @@ public:
|
||||
static void FloatToBytes(float data, std::vector<uint8_t>& bytes, uint32_t& offset, bool isBigEndian = true);
|
||||
static void Int32ToBytes(int32_t data, std::vector<uint8_t>& bytes, uint32_t& offset, bool isBigEndian = true);
|
||||
static void ArrayToBytes(const uint8_t* data, uint32_t length, std::vector<uint8_t>& bytes, uint32_t& offset);
|
||||
static int32_t KMPFind(const uint8_t* target, uint32_t targetLen, const uint8_t* pattern, uint32_t patternLen);
|
||||
static void FlushSurfaceBuffer(PixelMap* pixelMap);
|
||||
static void FlushContextSurfaceBuffer(ImagePlugin::DecodeContext& context);
|
||||
static void InvalidateContextSurfaceBuffer(ImagePlugin::DecodeContext& context);
|
||||
|
@ -726,53 +726,6 @@ void ImageUtils::ArrayToBytes(const uint8_t* data, uint32_t length, vector<uint8
|
||||
}
|
||||
}
|
||||
|
||||
static void GetNextArray(const uint8_t* pattern, uint32_t patternLen, std::vector<uint32_t>& next)
|
||||
{
|
||||
uint32_t prefixEnd = 0;
|
||||
next[0] = prefixEnd;
|
||||
for (uint32_t i = 1; i < patternLen; ++i) {
|
||||
// if not match, move prefixEnd to next position
|
||||
while (prefixEnd > 0 && pattern[prefixEnd] != pattern[i]) {
|
||||
prefixEnd = next[prefixEnd - 1];
|
||||
}
|
||||
// if match, update prefixEnd
|
||||
if (pattern[prefixEnd] == pattern[i]) {
|
||||
prefixEnd++;
|
||||
}
|
||||
//update next array
|
||||
next[i] = prefixEnd;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t ImageUtils::KMPFind(const uint8_t* target, uint32_t targetLen,
|
||||
const uint8_t* pattern, uint32_t patternLen)
|
||||
{
|
||||
if (target == nullptr || pattern == nullptr || patternLen == 0) {
|
||||
IMAGE_LOGE("ImageUtils FindFirstMatchingStringByKMP failed, patternLen is zero");
|
||||
return ERR_MEDIA_INVALID_VALUE;
|
||||
}
|
||||
|
||||
std::vector<uint32_t> next(patternLen, 0);
|
||||
GetNextArray(pattern, patternLen, next);
|
||||
uint32_t targetIndex = 0;
|
||||
uint32_t patternIndex = 0;
|
||||
for (; targetIndex < targetLen; ++targetIndex) {
|
||||
// if not match, move patternIndex to next position
|
||||
while (patternIndex > 0 && target[targetIndex] != pattern[patternIndex]) {
|
||||
patternIndex = next[patternIndex - 1];
|
||||
}
|
||||
// if match, update patternIndex
|
||||
if (target[targetIndex] == pattern[patternIndex]) {
|
||||
++patternIndex;
|
||||
}
|
||||
// find the first matching string success
|
||||
if (patternIndex == patternLen) {
|
||||
return static_cast<int32_t>(targetIndex) - static_cast<int32_t>(patternLen) + static_cast<int32_t>(NUM_1);
|
||||
}
|
||||
}
|
||||
return ERR_MEDIA_INVALID_VALUE;
|
||||
}
|
||||
|
||||
void ImageUtils::FlushSurfaceBuffer(PixelMap* pixelMap)
|
||||
{
|
||||
#if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
|
||||
|
@ -188,30 +188,77 @@ bool JpegMpfParser::ParsingMpEntry(uint8_t* data, uint32_t size, bool isBigEndia
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool FindAuxiliaryTags(const uint8_t* data, uint32_t size, std::string& foundTag)
|
||||
{
|
||||
if (data == nullptr || size < AUXILIARY_TAG_NAME_LENGTH) {
|
||||
return false;
|
||||
}
|
||||
for (const auto &[tagName, _] : AUXILIARY_TAG_TYPE_MAP) {
|
||||
if (memcmp(data, tagName.c_str(), tagName.size()) == 0) {
|
||||
foundTag = tagName;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// |<------------------ Auxiliary picture structure ----------------->|
|
||||
// |<- Image data ->|<- Image size(4 Bytes) ->|<- Tag name(8 Bytes) ->|
|
||||
static int32_t GetLastAuxiliaryTagOffset(const uint8_t* data, uint32_t size, std::string& foundTag)
|
||||
{
|
||||
if (data == nullptr || size < AUXILIARY_TAG_NAME_LENGTH) {
|
||||
return ERR_MEDIA_INVALID_VALUE;
|
||||
}
|
||||
uint32_t offset = size - AUXILIARY_TAG_NAME_LENGTH;
|
||||
while (offset > 0) {
|
||||
if (FindAuxiliaryTags(data + offset, size - offset, foundTag)) {
|
||||
return static_cast<int32_t>(offset);
|
||||
}
|
||||
--offset;
|
||||
}
|
||||
return ERR_MEDIA_INVALID_VALUE;
|
||||
}
|
||||
|
||||
// Parse the following types of auxiliary pictures: DEPTH_MAP, UNREFOCUS_MAP, LINEAR_MAP, FRAGMENT_MAP
|
||||
bool JpegMpfParser::ParsingAuxiliaryPictures(uint8_t* data, uint32_t dataSize, bool isBigEndian)
|
||||
{
|
||||
if (data == nullptr || dataSize == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
images_.clear();
|
||||
for (const auto& it : AUXILIARY_TAG_TYPE_MAP) {
|
||||
int32_t matchedPos = ImageUtils::KMPFind(data, dataSize,
|
||||
reinterpret_cast<const uint8_t*>(it.first.c_str()), it.first.size());
|
||||
uint32_t offset = dataSize;
|
||||
while (offset > 0) {
|
||||
std::string foundTag("");
|
||||
int32_t matchedPos = GetLastAuxiliaryTagOffset(data, offset, foundTag);
|
||||
if (matchedPos == ERR_MEDIA_INVALID_VALUE) {
|
||||
IMAGE_LOGI("%{public}s no more auxiliary pictures", __func__);
|
||||
break;
|
||||
}
|
||||
offset = static_cast<uint32_t>(matchedPos);
|
||||
auto it = AUXILIARY_TAG_TYPE_MAP.find(foundTag);
|
||||
if (it == AUXILIARY_TAG_TYPE_MAP.end()) {
|
||||
IMAGE_LOGW("%{public}s unknown auxiliary tag: %{public}s", __func__, foundTag.c_str());
|
||||
continue;
|
||||
}
|
||||
uint32_t offset = static_cast<uint32_t>(matchedPos);
|
||||
if (offset > dataSize) {
|
||||
|
||||
if (offset < UINT32_BYTE_SIZE) {
|
||||
IMAGE_LOGW("%{public}s invalid offset: %{public}u, auxiliary tag: %{public}s",
|
||||
__func__, offset, foundTag.c_str());
|
||||
continue;
|
||||
}
|
||||
offset -= UINT32_BYTE_SIZE;
|
||||
uint32_t imageSize = ImageUtils::BytesToUint32(data, offset, isBigEndian);
|
||||
if (offset < imageSize + UINT32_BYTE_SIZE) {
|
||||
IMAGE_LOGW("%{public}s invalid image size: %{public}u, offset: %{public}u, auxiliary tag: %{public}s",
|
||||
__func__, imageSize, offset, foundTag.c_str());
|
||||
continue;
|
||||
}
|
||||
offset = offset - imageSize - UINT32_BYTE_SIZE;
|
||||
SingleJpegImage auxImage = {
|
||||
.offset = offset - UINT32_BYTE_SIZE - imageSize,
|
||||
.offset = offset,
|
||||
.size = imageSize,
|
||||
.auxType = it.second,
|
||||
.auxTagName = it.first,
|
||||
.auxType = it->second,
|
||||
.auxTagName = it->first,
|
||||
};
|
||||
images_.push_back(auxImage);
|
||||
IMAGE_LOGD("[%{public}s] auxType=%{public}d, offset=%{public}u, size=%{public}u, tagName=%{public}s",
|
||||
|
Loading…
Reference in New Issue
Block a user