heif: Implement support for image cropping
HEIF supports specifying image cropping by using the CleanAperture box.
This CL adds support for parsing the 'clap' box and setting the viewport
of the image to the cropped bounds (if valid).
This CL contains files that are not in mainline.
Bug: 289227447
Test: atest HeifCleanApertureUnitTest CtsMediaMiscTestCases:MediaMetadataRetrieverTest. AVIF files with clap box are displayed correctly (only the cropped part) in the Files app.
Change-Id: I139298409f8517507c54094cf72fb7f7b64e1635
diff --git a/media/libheif/HeifDecoderImpl.cpp b/media/libheif/HeifDecoderImpl.cpp
index 6834b7d..085a7e4 100644
--- a/media/libheif/HeifDecoderImpl.cpp
+++ b/media/libheif/HeifDecoderImpl.cpp
@@ -41,8 +41,8 @@
namespace android {
void initFrameInfo(HeifFrameInfo *info, const VideoFrame *videoFrame) {
- info->mWidth = videoFrame->mWidth;
- info->mHeight = videoFrame->mHeight;
+ info->mWidth = videoFrame->mDisplayWidth;
+ info->mHeight = videoFrame->mDisplayHeight;
info->mRotationAngle = videoFrame->mRotationAngle;
info->mBytesPerPixel = videoFrame->mBytesPerPixel;
info->mDurationUs = videoFrame->mDurationUs;
@@ -742,8 +742,11 @@
// Either document why it is safe in this case or address the
// issue (e.g. by copying).
VideoFrame* videoFrame = static_cast<VideoFrame*>(mFrameMemory->unsecurePointer());
- uint8_t* src = videoFrame->getFlattenedData() + videoFrame->mRowBytes * mCurScanline++;
- memcpy(dst, src, videoFrame->mBytesPerPixel * videoFrame->mWidth);
+ uint8_t* src = videoFrame->getFlattenedData() +
+ (videoFrame->mRowBytes * (mCurScanline + videoFrame->mDisplayTop)) +
+ (videoFrame->mBytesPerPixel * videoFrame->mDisplayLeft);
+ mCurScanline++;
+ memcpy(dst, src, videoFrame->mBytesPerPixel * videoFrame->mDisplayWidth);
return true;
}
diff --git a/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
index db979d7..90c52dc 100644
--- a/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
+++ b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
@@ -672,6 +672,18 @@
if (trackMeta->findInt32(kKeyWidth, &imageWidth)
&& trackMeta->findInt32(kKeyHeight, &imageHeight)) {
imagePrimary = imageCount;
+ int32_t displayLeft;
+ int32_t displayTop;
+ int32_t displayRight;
+ int32_t displayBottom;
+ if (trackMeta->findRect(kKeyCropRect, &displayLeft, &displayTop,
+ &displayRight, &displayBottom)
+ && displayLeft >= 0 && displayTop >= 0 && displayRight < imageWidth
+ && displayBottom < imageHeight && displayLeft <= displayRight
+ && displayTop <= displayBottom) {
+ imageWidth = displayRight - displayLeft + 1;
+ imageHeight = displayBottom - displayTop + 1;
+ }
} else {
ALOGE("primary image track ignored for missing dimensions");
}
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index 57937f9..1a0bb7f 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -86,6 +86,22 @@
displayWidth = width;
displayHeight = height;
}
+ int32_t displayLeft = 0;
+ int32_t displayTop = 0;
+ int32_t displayRight;
+ int32_t displayBottom;
+ if (trackMeta->findRect(kKeyCropRect, &displayLeft, &displayTop, &displayRight,
+ &displayBottom)) {
+ if (displayLeft >= 0 && displayTop >= 0 && displayRight < width && displayBottom < height &&
+ displayLeft <= displayRight && displayTop <= displayBottom) {
+ displayWidth = displayRight - displayLeft + 1;
+ displayHeight = displayBottom - displayTop + 1;
+ } else {
+ // Crop rectangle is invalid, use the whole frame.
+ displayLeft = 0;
+ displayTop = 0;
+ }
+ }
if (allocRotated) {
if (rotationAngle == 90 || rotationAngle == 270) {
@@ -108,8 +124,8 @@
}
}
- VideoFrame frame(width, height, displayWidth, displayHeight,
- tileWidth, tileHeight, rotationAngle, dstBpp, bitDepth, !metaOnly, iccSize);
+ VideoFrame frame(width, height, displayWidth, displayHeight, displayLeft, displayTop, tileWidth,
+ tileHeight, rotationAngle, dstBpp, bitDepth, !metaOnly, iccSize);
size_t size = frame.getFlattenedSize();
sp<MemoryHeapBase> heap = new MemoryHeapBase(size, 0, "MetadataRetrieverClient");