HEIF: Re-decode the image when changing color type

Bug: 135133301
Test: I902de3410c45a21cf27b48a02cdc5d514b7ada60

AImageDecoder allows decoding an image multiple times, using different
settings (e.g. color type) each time, using the same underlying SkCodec.
After finishing decoding the image, HeifDecoderImpl discards its
MediaMetadataRetriever in order to clean up resources. Hang onto the
input data, so that if a client attempts to decode again, the Impl can
recreate its MediaMetadataRetriever to perform a second decode.

If the client is using the same output color, no new
MediaMetadataRetriever is needed, since it can continue to use the
original video frame output.

When called from Java, the HeifDecoderImpl will be quickly discarded
anyway, so holding on to the input data until that discard should not be
a problem.

Change-Id: I2ca01a006215c1e6f6472c5e6a4df4e2155a3b11
gugelfrei
Leon Scroggins III 4 years ago
parent 0bc6f60e1f
commit 7ca678b41b

@ -334,6 +334,13 @@ bool HeifDecoderImpl::init(HeifStream* stream, HeifFrameInfo* frameInfo) {
}
mDataSource = dataSource;
return reinit(frameInfo);
}
bool HeifDecoderImpl::reinit(HeifFrameInfo* frameInfo) {
mFrameDecoded = false;
mFrameMemory.clear();
mRetriever = new MediaMetadataRetriever();
status_t err = mRetriever->setDataSource(mDataSource, "image/heif");
if (err != OK) {
@ -457,27 +464,35 @@ bool HeifDecoderImpl::getEncodedColor(HeifEncodedColor* /*outColor*/) const {
}
bool HeifDecoderImpl::setOutputColor(HeifColorFormat heifColor) {
if (heifColor == mOutputColor) {
return true;
}
switch(heifColor) {
case kHeifColorFormat_RGB565:
{
mOutputColor = HAL_PIXEL_FORMAT_RGB_565;
return true;
break;
}
case kHeifColorFormat_RGBA_8888:
{
mOutputColor = HAL_PIXEL_FORMAT_RGBA_8888;
return true;
break;
}
case kHeifColorFormat_BGRA_8888:
{
mOutputColor = HAL_PIXEL_FORMAT_BGRA_8888;
return true;
break;
}
default:
break;
ALOGE("Unsupported output color format %d", heifColor);
return false;
}
ALOGE("Unsupported output color format %d", heifColor);
return false;
if (mFrameDecoded) {
return reinit(nullptr);
}
return true;
}
bool HeifDecoderImpl::decodeAsync() {
@ -506,7 +521,8 @@ bool HeifDecoderImpl::decodeAsync() {
}
// Aggressive clear to avoid holding on to resources
mRetriever.clear();
mDataSource.clear();
// Hold on to mDataSource in case the client wants to redecode.
return false;
}
@ -606,7 +622,8 @@ bool HeifDecoderImpl::decode(HeifFrameInfo* frameInfo) {
// Aggressively clear to avoid holding on to resources
mRetriever.clear();
mDataSource.clear();
// Hold on to mDataSource in case the client wants to redecode.
return true;
}

@ -81,6 +81,7 @@ private:
bool decodeAsync();
bool getScanlineInner(uint8_t* dst);
bool reinit(HeifFrameInfo* frameInfo);
};
} // namespace android

Loading…
Cancel
Save