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

Commit 026d5202 authored by Chong Zhang's avatar Chong Zhang
Browse files

stagefright: misc preliminary fixes for HEIF support

- Support 32bit RGB in ColorConverter.

- Allow dst crop to be not the entire dst frame buffer.

- Also has a minor fix in CallbackDatasource to use left over
cache first before reading from source. This helps to reduce
backward reads to the source.

bug: 64077740

Test: cts-tradefed run cts-dev --module CtsMediaTestCases --compatibility:module-arg CtsMediaTestCases:include-annotation:android.platform.test.annotations.RequiresDevice

Change-Id: Ia7bdb9a48b27a312af7cbe4a97f14382a8cb6278
parent 8b852805
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -35,7 +35,9 @@ public:
    // Get the memory that readAt writes into.
    virtual sp<IMemory> getIMemory() = 0;
    // Read up to |size| bytes into the memory returned by getIMemory(). Returns
    // the number of bytes read, or -1 on error. |size| must not be larger than
    // the number of bytes read, or negative value on error (eg.
    // ERROR_END_OF_STREAM indicating EOS. This is needed by CallbackDataSource
    // to properly handle reading of last chunk). |size| must not be larger than
    // the buffer.
    virtual ssize_t readAt(off64_t offset, size_t size) = 0;
    // Get the size, or -1 if the size is unknown.
+3 −4
Original line number Diff line number Diff line
@@ -127,10 +127,6 @@ status_t TinyCacheSource::initCheck() const {
}

ssize_t TinyCacheSource::readAt(off64_t offset, void* data, size_t size) {
    if (size >= kCacheSize) {
        return mSource->readAt(offset, data, size);
    }

    // Check if the cache satisfies the read.
    if (mCachedOffset <= offset
            && offset < (off64_t) (mCachedOffset + mCachedSize)) {
@@ -154,6 +150,9 @@ ssize_t TinyCacheSource::readAt(off64_t offset, void* data, size_t size) {
        }
    }

    if (size >= kCacheSize) {
        return mSource->readAt(offset, data, size);
    }

    // Fill the cache and copy to the caller.
    const ssize_t numRead = mSource->readAt(offset, mCache, kCacheSize);
+9 −51
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/foundation/ColorUtils.h>
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDefs.h>
@@ -285,45 +286,6 @@ status_t MPEG4DataSource::setCachedRange(off64_t offset, size_t size) {

static const bool kUseHexDump = false;

static void hexdump(const void *_data, size_t size) {
    const uint8_t *data = (const uint8_t *)_data;
    size_t offset = 0;
    while (offset < size) {
        printf("0x%04zx  ", offset);

        size_t n = size - offset;
        if (n > 16) {
            n = 16;
        }

        for (size_t i = 0; i < 16; ++i) {
            if (i == 8) {
                printf(" ");
            }

            if (offset + i < size) {
                printf("%02x ", data[offset + i]);
            } else {
                printf("   ");
            }
        }

        printf(" ");

        for (size_t i = 0; i < n; ++i) {
            if (isprint(data[offset + i])) {
                printf("%c", data[offset + i]);
            } else {
                printf(".");
            }
        }

        printf("\n");

        offset += 16;
    }
}

static const char *FourCC2MIME(uint32_t fourcc) {
    switch (fourcc) {
        case FOURCC('m', 'p', '4', 'a'):
@@ -512,14 +474,6 @@ sp<MetaData> MPEG4Extractor::getTrackMetaData(
    return track->meta;
}

static void MakeFourCCString(uint32_t x, char *s) {
    s[0] = x >> 24;
    s[1] = (x >> 16) & 0xff;
    s[2] = (x >> 8) & 0xff;
    s[3] = x & 0xff;
    s[4] = '\0';
}

status_t MPEG4Extractor::readMetaData() {
    if (mInitCheck != NO_INIT) {
        return mInitCheck;
@@ -961,8 +915,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
                    }
                }

                if (mLastTrack == NULL)
                if (mLastTrack == NULL) {
                    return ERROR_MALFORMED;
                }

                mLastTrack->sampleTable = new SampleTable(mDataSource);
            }
@@ -1134,8 +1089,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
            original_fourcc = ntohl(original_fourcc);
            ALOGV("read original format: %d", original_fourcc);

            if (mLastTrack == NULL)
            if (mLastTrack == NULL) {
                return ERROR_MALFORMED;
            }

            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc));
            uint32_t num_channels = 0;
@@ -1575,8 +1531,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
        case FOURCC('s', 't', 'c', 'o'):
        case FOURCC('c', 'o', '6', '4'):
        {
            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL)) {
                return ERROR_MALFORMED;
            }

            status_t err =
                mLastTrack->sampleTable->setChunkOffsetParams(
@@ -1612,8 +1569,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
        case FOURCC('s', 't', 's', 'z'):
        case FOURCC('s', 't', 'z', '2'):
        {
            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL))
            if ((mLastTrack == NULL) || (mLastTrack->sampleTable == NULL)) {
                return ERROR_MALFORMED;
            }

            status_t err =
                mLastTrack->sampleTable->setSampleSizeParams(
+8 −0
Original line number Diff line number Diff line
@@ -1874,5 +1874,13 @@ AString nameForFd(int fd) {
    return result;
}

void MakeFourCCString(uint32_t x, char *s) {
    s[0] = x >> 24;
    s[1] = (x >> 16) & 0xff;
    s[2] = (x >> 8) & 0xff;
    s[3] = x & 0xff;
    s[4] = '\0';
}

}  // namespace android
+137 −45
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <media/stagefright/MediaErrors.h>

#include "libyuv/convert_from.h"
#include "libyuv/video_common.h"

#define USE_LIBYUV

@@ -41,17 +42,17 @@ ColorConverter::~ColorConverter() {
}

bool ColorConverter::isValid() const {
    if (mDstFormat != OMX_COLOR_Format16bitRGB565) {
        return false;
    }

    switch (mSrcFormat) {
        case OMX_COLOR_FormatYUV420Planar:
            return mDstFormat == OMX_COLOR_Format16bitRGB565
                    || mDstFormat == OMX_COLOR_Format32BitRGBA8888
                    || mDstFormat == OMX_COLOR_Format32bitBGRA8888;

        case OMX_COLOR_FormatCbYCrY:
        case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
        case OMX_COLOR_FormatYUV420SemiPlanar:
        case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
            return true;
            return mDstFormat == OMX_COLOR_Format16bitRGB565;

        default:
            return false;
@@ -62,14 +63,43 @@ ColorConverter::BitmapParams::BitmapParams(
        void *bits,
        size_t width, size_t height,
        size_t cropLeft, size_t cropTop,
        size_t cropRight, size_t cropBottom)
        size_t cropRight, size_t cropBottom,
        OMX_COLOR_FORMATTYPE colorFromat)
    : mBits(bits),
      mColorFormat(colorFromat),
      mWidth(width),
      mHeight(height),
      mCropLeft(cropLeft),
      mCropTop(cropTop),
      mCropRight(cropRight),
      mCropBottom(cropBottom) {
    switch(mColorFormat) {
    case OMX_COLOR_Format16bitRGB565:
        mBpp = 2;
        mStride = 2 * mWidth;
        break;

    case OMX_COLOR_Format32bitBGRA8888:
    case OMX_COLOR_Format32BitRGBA8888:
        mBpp = 4;
        mStride = 4 * mWidth;
        break;

    case OMX_COLOR_FormatYUV420Planar:
    case OMX_COLOR_FormatCbYCrY:
    case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
    case OMX_COLOR_FormatYUV420SemiPlanar:
    case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
        mBpp = 1;
        mStride = mWidth;
        break;

    default:
        ALOGE("Unsupported color format %d", mColorFormat);
        mBpp = 1;
        mStride = mWidth;
        break;
    }
}

size_t ColorConverter::BitmapParams::cropWidth() const {
@@ -89,19 +119,15 @@ status_t ColorConverter::convert(
        size_t dstWidth, size_t dstHeight,
        size_t dstCropLeft, size_t dstCropTop,
        size_t dstCropRight, size_t dstCropBottom) {
    if (mDstFormat != OMX_COLOR_Format16bitRGB565) {
        return ERROR_UNSUPPORTED;
    }

    BitmapParams src(
            const_cast<void *>(srcBits),
            srcWidth, srcHeight,
            srcCropLeft, srcCropTop, srcCropRight, srcCropBottom);
            srcCropLeft, srcCropTop, srcCropRight, srcCropBottom, mSrcFormat);

    BitmapParams dst(
            dstBits,
            dstWidth, dstHeight,
            dstCropLeft, dstCropTop, dstCropRight, dstCropBottom);
            dstCropLeft, dstCropTop, dstCropRight, dstCropBottom, mDstFormat);

    status_t err;

@@ -212,26 +238,104 @@ status_t ColorConverter::convertYUV420PlanarUseLibYUV(
        return ERROR_UNSUPPORTED;
    }

    uint16_t *dst_ptr = (uint16_t *)dst.mBits
        + dst.mCropTop * dst.mWidth + dst.mCropLeft;
    uint8_t *dst_ptr = (uint8_t *)dst.mBits
        + dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp;

    const uint8_t *src_y =
        (const uint8_t *)src.mBits + src.mCropTop * src.mWidth + src.mCropLeft;
        (const uint8_t *)src.mBits + src.mCropTop * src.mStride + src.mCropLeft;

    const uint8_t *src_u =
        (const uint8_t *)src_y + src.mWidth * src.mHeight
        + src.mCropTop * (src.mWidth / 2) + src.mCropLeft / 2;
        (const uint8_t *)src.mBits + src.mStride * src.mHeight
        + (src.mCropTop / 2) * (src.mStride / 2) + (src.mCropLeft / 2);

    const uint8_t *src_v =
        src_u + (src.mWidth / 2) * (src.mHeight / 2);
        src_u + (src.mStride / 2) * (src.mHeight / 2);

    switch (mDstFormat) {
    case OMX_COLOR_Format16bitRGB565:
        libyuv::I420ToRGB565(src_y, src.mStride, src_u, src.mStride / 2, src_v, src.mStride / 2,
                (uint8 *)dst_ptr, dst.mStride, src.cropWidth(), src.cropHeight());
        break;

    case OMX_COLOR_Format32BitRGBA8888:
        libyuv::ConvertFromI420(src_y, src.mStride, src_u, src.mStride / 2, src_v, src.mStride / 2,
                (uint8 *)dst_ptr, dst.mStride, src.cropWidth(), src.cropHeight(), libyuv::FOURCC_ABGR);
        break;

    libyuv::I420ToRGB565(src_y, src.mWidth, src_u, src.mWidth / 2, src_v, src.mWidth / 2,
            (uint8 *)dst_ptr, dst.mWidth * 2, dst.mWidth, dst.mHeight);
    case OMX_COLOR_Format32bitBGRA8888:
        libyuv::ConvertFromI420(src_y, src.mStride, src_u, src.mStride / 2, src_v, src.mStride / 2,
                (uint8 *)dst_ptr, dst.mStride, src.cropWidth(), src.cropHeight(), libyuv::FOURCC_ARGB);
        break;

    default:
        return ERROR_UNSUPPORTED;
    }

    return OK;
}

void ColorConverter::writeToDst(
        void *dst_ptr, uint8_t *kAdjustedClip, bool uncropped,
        signed r1, signed g1, signed b1,
        signed r2, signed g2, signed b2) {
    switch (mDstFormat) {
    case OMX_COLOR_Format16bitRGB565:
    {
        uint32_t rgb1 =
            ((kAdjustedClip[r1] >> 3) << 11)
            | ((kAdjustedClip[g1] >> 2) << 5)
            | (kAdjustedClip[b1] >> 3);

        if (uncropped) {
            uint32_t rgb2 =
                ((kAdjustedClip[r2] >> 3) << 11)
                | ((kAdjustedClip[g2] >> 2) << 5)
                | (kAdjustedClip[b2] >> 3);

            *(uint32_t *)dst_ptr = (rgb2 << 16) | rgb1;
        } else {
            *(uint16_t *)dst_ptr = rgb1;
        }
        break;
    }
    case OMX_COLOR_Format32BitRGBA8888:
    {
        ((uint32_t *)dst_ptr)[0] =
                (kAdjustedClip[r1])
                | (kAdjustedClip[g1] << 8)
                | (kAdjustedClip[b1] << 16)
                | (0xFF << 24);

        if (uncropped) {
            ((uint32_t *)dst_ptr)[1] =
                    (kAdjustedClip[r2])
                    | (kAdjustedClip[g2] << 8)
                    | (kAdjustedClip[b2] << 16)
                    | (0xFF << 24);
        }
        break;
    }
    case OMX_COLOR_Format32bitBGRA8888:
    {
        ((uint32_t *)dst_ptr)[0] =
                (kAdjustedClip[b1])
                | (kAdjustedClip[g1] << 8)
                | (kAdjustedClip[r1] << 16)
                | (0xFF << 24);

        if (uncropped) {
            ((uint32_t *)dst_ptr)[1] =
                    (kAdjustedClip[b2])
                    | (kAdjustedClip[g2] << 8)
                    | (kAdjustedClip[r2] << 16)
                    | (0xFF << 24);
        }
        break;
    }
    default:
        break;
    }
}
status_t ColorConverter::convertYUV420Planar(
        const BitmapParams &src, const BitmapParams &dst) {
    if (!((src.mCropLeft & 1) == 0
@@ -242,18 +346,18 @@ status_t ColorConverter::convertYUV420Planar(

    uint8_t *kAdjustedClip = initClip();

    uint16_t *dst_ptr = (uint16_t *)dst.mBits
        + dst.mCropTop * dst.mWidth + dst.mCropLeft;
    uint8_t *dst_ptr = (uint8_t *)dst.mBits
        + dst.mCropTop * dst.mStride + dst.mCropLeft * dst.mBpp;

    const uint8_t *src_y =
        (const uint8_t *)src.mBits + src.mCropTop * src.mWidth + src.mCropLeft;
        (const uint8_t *)src.mBits + src.mCropTop * src.mStride + src.mCropLeft;

    const uint8_t *src_u =
        (const uint8_t *)src_y + src.mWidth * src.mHeight
        + src.mCropTop * (src.mWidth / 2) + src.mCropLeft / 2;
        (const uint8_t *)src.mBits + src.mStride * src.mHeight
        + (src.mCropTop / 2) * (src.mStride / 2) + src.mCropLeft / 2;

    const uint8_t *src_v =
        src_u + (src.mWidth / 2) * (src.mHeight / 2);
        src_u + (src.mStride / 2) * (src.mHeight / 2);

    for (size_t y = 0; y < src.cropHeight(); ++y) {
        for (size_t x = 0; x < src.cropWidth(); x += 2) {
@@ -296,31 +400,19 @@ status_t ColorConverter::convertYUV420Planar(
            signed g2 = (tmp2 + v_g + u_g) / 256;
            signed r2 = (tmp2 + v_r) / 256;

            uint32_t rgb1 =
                ((kAdjustedClip[r1] >> 3) << 11)
                | ((kAdjustedClip[g1] >> 2) << 5)
                | (kAdjustedClip[b1] >> 3);

            uint32_t rgb2 =
                ((kAdjustedClip[r2] >> 3) << 11)
                | ((kAdjustedClip[g2] >> 2) << 5)
                | (kAdjustedClip[b2] >> 3);

            if (x + 1 < src.cropWidth()) {
                *(uint32_t *)(&dst_ptr[x]) = (rgb2 << 16) | rgb1;
            } else {
                dst_ptr[x] = rgb1;
            }
            bool uncropped = x + 1 < src.cropWidth();
            (void)writeToDst(dst_ptr + x * dst.mBpp,
                    kAdjustedClip, uncropped, r1, g1, b1, r2, g2, b2);
        }

        src_y += src.mWidth;
        src_y += src.mStride;

        if (y & 1) {
            src_u += src.mWidth / 2;
            src_v += src.mWidth / 2;
            src_u += src.mStride / 2;
            src_v += src.mStride / 2;
        }

        dst_ptr += dst.mWidth;
        dst_ptr += dst.mStride;
    }

    return OK;
Loading