Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 49d4aa0a authored by Chong Zhang's avatar Chong Zhang
Browse files

heif: use width and height for decoder -- DO NOT MERGE

The display dimensions from MPEG4Extractor is applied on top
of width and height for scaling, it's not for cropping. For
bitmap uses we have to use width and height, the frame from
media server is not scaled.

This required porting over some fixes from master to fix the
display size vs. image size reporting, otherwise images with
grids may show a black border at the bottom or right.

bug: 73172046
Test: test app in bug; open folders with heif files in Photos
and Downloads; CTS MediaMetadataRetrieverTest.
Change-Id: I3d7f1492d08d48876836ccc05b6eb4de0d0c0f9a
parent 291daf45
Loading
Loading
Loading
Loading
+8 −8
Original line number Diff line number Diff line
@@ -321,8 +321,8 @@ bool HeifDecoderImpl::init(HeifStream* stream, HeifFrameInfo* frameInfo) {

    if (frameInfo != nullptr) {
        frameInfo->set(
                videoFrame->mDisplayWidth,
                videoFrame->mDisplayHeight,
                videoFrame->mWidth,
                videoFrame->mHeight,
                videoFrame->mRotationAngle,
                videoFrame->mBytesPerPixel,
                videoFrame->mIccSize,
@@ -393,8 +393,8 @@ bool HeifDecoderImpl::decode(HeifFrameInfo* frameInfo) {

    if (frameInfo != nullptr) {
        frameInfo->set(
                videoFrame->mDisplayWidth,
                videoFrame->mDisplayHeight,
                videoFrame->mWidth,
                videoFrame->mHeight,
                videoFrame->mRotationAngle,
                videoFrame->mBytesPerPixel,
                videoFrame->mIccSize,
@@ -413,12 +413,12 @@ bool HeifDecoderImpl::getScanline(uint8_t* dst) {
        return false;
    }
    VideoFrame* videoFrame = static_cast<VideoFrame*>(mFrameMemory->pointer());
    if (mCurScanline >= videoFrame->mDisplayHeight) {
    if (mCurScanline >= videoFrame->mHeight) {
        ALOGE("no more scanline available");
        return false;
    }
    uint8_t* src = videoFrame->getFlattenedData() + videoFrame->mRowBytes * mCurScanline++;
    memcpy(dst, src, videoFrame->mBytesPerPixel * videoFrame->mDisplayWidth);
    memcpy(dst, src, videoFrame->mBytesPerPixel * videoFrame->mWidth);
    return true;
}

@@ -430,8 +430,8 @@ size_t HeifDecoderImpl::skipScanlines(size_t count) {

    uint32_t oldScanline = mCurScanline;
    mCurScanline += count;
    if (mCurScanline > videoFrame->mDisplayHeight) {
        mCurScanline = videoFrame->mDisplayHeight;
    if (mCurScanline > videoFrame->mHeight) {
        mCurScanline = videoFrame->mHeight;
    }
    return (mCurScanline > oldScanline) ? (mCurScanline - oldScanline) : 0;
}
+2 −7
Original line number Diff line number Diff line
@@ -1441,16 +1441,11 @@ sp<MetaData> ItemTable::getImageMeta() {
        if (tileIndex < 0) {
            return NULL;
        }
        // when there are tiles, (kKeyWidth, kKeyHeight) is the full tiled area,
        // and (kKeyDisplayWidth, kKeyDisplayHeight) may be smaller than that.
        meta->setInt32(kKeyDisplayWidth, image->width);
        meta->setInt32(kKeyDisplayHeight, image->height);
        int32_t gridRows = image->rows, gridCols = image->columns;
        meta->setInt32(kKeyGridRows, image->rows);
        meta->setInt32(kKeyGridCols, image->columns);

        // point image to the first tile for grid size and HVCC
        image = &mItemIdToImageMap.editValueAt(tileIndex);
        meta->setInt32(kKeyWidth, image->width * gridCols);
        meta->setInt32(kKeyHeight, image->height * gridRows);
        meta->setInt32(kKeyGridWidth, image->width);
        meta->setInt32(kKeyGridHeight, image->height);
        meta->setInt32(kKeyMaxInputSize, image->width * image->height * 1.5);
+34 −34
Original line number Diff line number Diff line
@@ -276,30 +276,27 @@ static VideoFrame *extractVideoFrame(
    int32_t gridRows = 1, gridCols = 1;
    if (overrideMeta == NULL) {
        // check if we're dealing with a tiled heif
        int32_t gridWidth, gridHeight;
        int32_t gridWidth, gridHeight, tmpRows, tmpCols;
        if (trackMeta->findInt32(kKeyGridWidth, &gridWidth) && gridWidth > 0
         && trackMeta->findInt32(kKeyGridHeight, &gridHeight) && gridHeight > 0) {
            int32_t width, height, displayWidth, displayHeight;
         && trackMeta->findInt32(kKeyGridHeight, &gridHeight) && gridHeight > 0
         && trackMeta->findInt32(kKeyGridRows, &tmpRows) && tmpRows > 0
         && trackMeta->findInt32(kKeyGridCols, &tmpCols) && tmpCols > 0) {
            int32_t width, height;
            CHECK(trackMeta->findInt32(kKeyWidth, &width));
            CHECK(trackMeta->findInt32(kKeyHeight, &height));
            CHECK(trackMeta->findInt32(kKeyDisplayWidth, &displayWidth));
            CHECK(trackMeta->findInt32(kKeyDisplayHeight, &displayHeight));

            if (width >= displayWidth && height >= displayHeight
                    && (width % gridWidth == 0) && (height % gridHeight == 0)) {
                ALOGV("grid config: %dx%d, display %dx%d, grid %dx%d",
                        width, height, displayWidth, displayHeight, gridWidth, gridHeight);
            if (width <= gridWidth * tmpCols && height <= gridHeight * tmpRows) {
                ALOGV("grid: %dx%d, size: %dx%d, picture size: %dx%d",
                        tmpCols, tmpRows, gridWidth, gridHeight, width, height);

                overrideMeta = new MetaData(*trackMeta);
                overrideMeta->remove(kKeyDisplayWidth);
                overrideMeta->remove(kKeyDisplayHeight);
                overrideMeta->setInt32(kKeyWidth, gridWidth);
                overrideMeta->setInt32(kKeyHeight, gridHeight);
                gridCols = width / gridWidth;
                gridRows = height / gridHeight;
                gridCols = tmpCols;
                gridRows = tmpRows;
            } else {
                ALOGE("Bad grid config: %dx%d, display %dx%d, grid %dx%d",
                        width, height, displayWidth, displayHeight, gridWidth, gridHeight);
                ALOGE("bad grid: %dx%d, size: %dx%d, picture size: %dx%d",
                        tmpCols, tmpRows, gridWidth, gridHeight, width, height);
            }
        }
        if (overrideMeta == NULL) {
@@ -541,6 +538,9 @@ static VideoFrame *extractVideoFrame(
                        dstBottom = dstTop + height - 1;
                    }

                    done = (targetTimeUs < 0ll) || (timeUs >= targetTimeUs);

                    if (done) {
                        if (converter.isValid()) {
                            err = converter.convert(
                                    (const uint8_t *)videoFrameBuffer->data(),
@@ -556,13 +556,13 @@ static VideoFrame *extractVideoFrame(

                            err = ERROR_UNSUPPORTED;
                        }

                    done = (targetTimeUs < 0ll) || (timeUs >= targetTimeUs);
                        if (numTiles > 1) {
                            tilesDecoded++;
                            done &= (tilesDecoded >= numTiles);
                        }
                    err = decoder->releaseOutputBuffer(index);
                    }

                    decoder->releaseOutputBuffer(index);
                } else {
                    ALOGW("Received error %d (%s) instead of output", err, asString(err));
                    done = true;
+2 −0
Original line number Diff line number Diff line
@@ -215,6 +215,8 @@ enum {

    kKeyGridWidth        = 'grdW', // int32_t, HEIF grid width
    kKeyGridHeight       = 'grdH', // int32_t, HEIF grid height
    kKeyGridRows         = 'grdR', // int32_t, HEIF grid rows
    kKeyGridCols         = 'grdC', // int32_t, HEIF grid columns
    kKeyIccProfile       = 'prof', // raw data, ICC prifile data
};