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

Commit 77228a7b authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 4770446 from d9ed870e to pi-release

Change-Id: I8f6c25db9da5e424b9dc00e5ec11435e3aa61fc4
parents 7ef19d19 d9ed870e
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -68,10 +68,12 @@ constexpr char kEqualsSign[] = "=";

template<typename T>
std::string toBase64StringNoPad(const T* data, size_t size) {
    if (size == 0) {
    // Note that the base 64 conversion only works with arrays of single-byte
    // values. If the source is empty or is not an array of single-byte values,
    // return empty string.
    if (size == 0 || sizeof(data[0]) != 1) {
      return "";
    }
    CHECK(sizeof(data[0] == 1));

    android::AString outputString;
    encodeBase64(data, size, &outputString);
+4 −0
Original line number Diff line number Diff line
@@ -37,9 +37,11 @@ public:
    // will calculate frame buffer size if |hasData| is set to true.
    VideoFrame(uint32_t width, uint32_t height,
            uint32_t displayWidth, uint32_t displayHeight,
            uint32_t tileWidth, uint32_t tileHeight,
            uint32_t angle, uint32_t bpp, bool hasData, size_t iccSize):
        mWidth(width), mHeight(height),
        mDisplayWidth(displayWidth), mDisplayHeight(displayHeight),
        mTileWidth(tileWidth), mTileHeight(tileHeight),
        mRotationAngle(angle), mBytesPerPixel(bpp), mRowBytes(bpp * width),
        mSize(hasData ? (bpp * width * height) : 0),
        mIccSize(iccSize), mReserved(0) {
@@ -74,6 +76,8 @@ public:
    uint32_t mHeight;          // Decoded image height before rotation
    uint32_t mDisplayWidth;    // Display width before rotation
    uint32_t mDisplayHeight;   // Display height before rotation
    uint32_t mTileWidth;       // Tile width (0 if image doesn't have grid)
    uint32_t mTileHeight;      // Tile height (0 if image doesn't have grid)
    int32_t  mRotationAngle;   // Rotation angle, clockwise, should be multiple of 90
    uint32_t mBytesPerPixel;   // Number of bytes per pixel
    uint32_t mRowBytes;        // Number of bytes per row before rotation
+1 −14
Original line number Diff line number Diff line
@@ -895,20 +895,7 @@ status_t BnAudioPolicyService::onTransact(
            break;
    }

    // FIXME: extend timeout for SET_DEVICE_CONNECTION_STATE and HANDLE_DEVICE_CONFIG_CHANGE
    // while we investigate why BT A2DP device connection/disconnection can sometimes
    // take more than 5 seconds
    uint32_t timeoutMs = TimeCheck::kDefaultTimeOutMs;
    switch (code) {
        case SET_DEVICE_CONNECTION_STATE:
        case HANDLE_DEVICE_CONFIG_CHANGE:
            timeoutMs *= 2;
            break;
        default:
            break;
    }

    TimeCheck check("IAudioPolicyService", timeoutMs);
    TimeCheck check("IAudioPolicyService");

    switch (code) {
        case SET_DEVICE_CONNECTION_STATE: {
+3 −4
Original line number Diff line number Diff line
@@ -204,15 +204,14 @@ bool AudioMixer::setChannelMasks(int name,

    // channel masks have changed, does this track need a downmixer?
    // update to try using our desired format (if we aren't already using it)
    const audio_format_t prevDownmixerFormat = track->mDownmixRequiresFormat;
    const status_t status = track->prepareForDownmix();
    ALOGE_IF(status != OK,
            "prepareForDownmix error %d, track channel mask %#x, mixer channel mask %#x",
            status, track->channelMask, track->mMixerChannelMask);

    if (prevDownmixerFormat != track->mDownmixRequiresFormat) {
        track->prepareForReformat(); // because of downmixer, track format may change!
    }
    // always do reformat since channel mask changed,
    // do it after downmix since track format may change!
    track->prepareForReformat();

    if (track->mResampler.get() != nullptr && mixerChannelCountChanged) {
        // resampler channels may have changed.
+134 −19
Original line number Diff line number Diff line
@@ -271,17 +271,43 @@ status_t HeifDataSource::getSize(off64_t* size) {

/////////////////////////////////////////////////////////////////////////

struct HeifDecoderImpl::DecodeThread : public Thread {
    explicit DecodeThread(HeifDecoderImpl *decoder) : mDecoder(decoder) {}

private:
    HeifDecoderImpl* mDecoder;

    bool threadLoop();

    DISALLOW_EVIL_CONSTRUCTORS(DecodeThread);
};

bool HeifDecoderImpl::DecodeThread::threadLoop() {
    return mDecoder->decodeAsync();
}

/////////////////////////////////////////////////////////////////////////

HeifDecoderImpl::HeifDecoderImpl() :
    // output color format should always be set via setOutputColor(), in case
    // it's not, default to HAL_PIXEL_FORMAT_RGB_565.
    mOutputColor(HAL_PIXEL_FORMAT_RGB_565),
    mCurScanline(0),
    mWidth(0),
    mHeight(0),
    mFrameDecoded(false),
    mHasImage(false),
    mHasVideo(false) {
    mHasVideo(false),
    mAvailableLines(0),
    mNumSlices(1),
    mSliceHeight(0),
    mAsyncDecodeDone(false) {
}

HeifDecoderImpl::~HeifDecoderImpl() {
    if (mThread != nullptr) {
        mThread->join();
    }
}

bool HeifDecoderImpl::init(HeifStream* stream, HeifFrameInfo* frameInfo) {
@@ -310,22 +336,23 @@ bool HeifDecoderImpl::init(HeifStream* stream, HeifFrameInfo* frameInfo) {

    mHasImage = hasImage && !strcasecmp(hasImage, "yes");
    mHasVideo = hasVideo && !strcasecmp(hasVideo, "yes");
    sp<IMemory> sharedMem;
    if (mHasImage) {
        // image index < 0 to retrieve primary image
        mFrameMemory = mRetriever->getImageAtIndex(
        sharedMem = mRetriever->getImageAtIndex(
                -1, mOutputColor, true /*metaOnly*/);
    } else if (mHasVideo) {
        mFrameMemory = mRetriever->getFrameAtTime(0,
        sharedMem = mRetriever->getFrameAtTime(0,
                MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC,
                mOutputColor, true /*metaOnly*/);
    }

    if (mFrameMemory == nullptr || mFrameMemory->pointer() == nullptr) {
    if (sharedMem == nullptr || sharedMem->pointer() == nullptr) {
        ALOGE("getFrameAtTime: videoFrame is a nullptr");
        return false;
    }

    VideoFrame* videoFrame = static_cast<VideoFrame*>(mFrameMemory->pointer());
    VideoFrame* videoFrame = static_cast<VideoFrame*>(sharedMem->pointer());

    ALOGV("Meta dimension %dx%d, display %dx%d, angle %d, iccSize %d",
            videoFrame->mWidth,
@@ -344,6 +371,14 @@ bool HeifDecoderImpl::init(HeifStream* stream, HeifFrameInfo* frameInfo) {
                videoFrame->mIccSize,
                videoFrame->getFlattenedIccData());
    }
    mWidth = videoFrame->mWidth;
    mHeight = videoFrame->mHeight;
    if (mHasImage && videoFrame->mTileHeight >= 512 && mWidth >= 3000 && mHeight >= 2000 ) {
        // Try decoding in slices only if the image has tiles and is big enough.
        mSliceHeight = videoFrame->mTileHeight;
        mNumSlices = (videoFrame->mHeight + mSliceHeight - 1) / mSliceHeight;
        ALOGV("mSliceHeight %u, mNumSlices %zu", mSliceHeight, mNumSlices);
    }
    return true;
}

@@ -376,6 +411,36 @@ bool HeifDecoderImpl::setOutputColor(HeifColorFormat heifColor) {
    return false;
}

bool HeifDecoderImpl::decodeAsync() {
    for (size_t i = 1; i < mNumSlices; i++) {
        ALOGV("decodeAsync(): decoding slice %zu", i);
        size_t top = i * mSliceHeight;
        size_t bottom = (i + 1) * mSliceHeight;
        if (bottom > mHeight) {
            bottom = mHeight;
        }
        sp<IMemory> frameMemory = mRetriever->getImageRectAtIndex(
                -1, mOutputColor, 0, top, mWidth, bottom);
        {
            Mutex::Autolock autolock(mLock);

            if (frameMemory == nullptr || frameMemory->pointer() == nullptr) {
                mAsyncDecodeDone = true;
                mScanlineReady.signal();
                break;
            }
            mFrameMemory = frameMemory;
            mAvailableLines = bottom;
            ALOGV("decodeAsync(): available lines %zu", mAvailableLines);
            mScanlineReady.signal();
        }
    }
    // Aggressive clear to avoid holding on to resources
    mRetriever.clear();
    mDataSource.clear();
    return false;
}

bool HeifDecoderImpl::decode(HeifFrameInfo* frameInfo) {
    // reset scanline pointer
    mCurScanline = 0;
@@ -384,6 +449,47 @@ bool HeifDecoderImpl::decode(HeifFrameInfo* frameInfo) {
        return true;
    }

    // See if we want to decode in slices to allow client to start
    // scanline processing in parallel with decode. If this fails
    // we fallback to decoding the full frame.
    if (mHasImage && mNumSlices > 1) {
        // get first slice and metadata
        sp<IMemory> frameMemory = mRetriever->getImageRectAtIndex(
                -1, mOutputColor, 0, 0, mWidth, mSliceHeight);

        if (frameMemory == nullptr || frameMemory->pointer() == nullptr) {
            ALOGE("decode: metadata is a nullptr");
            return false;
        }

        VideoFrame* videoFrame = static_cast<VideoFrame*>(frameMemory->pointer());

        if (frameInfo != nullptr) {
            frameInfo->set(
                    videoFrame->mWidth,
                    videoFrame->mHeight,
                    videoFrame->mRotationAngle,
                    videoFrame->mBytesPerPixel,
                    videoFrame->mIccSize,
                    videoFrame->getFlattenedIccData());
        }

        mFrameMemory = frameMemory;
        mAvailableLines = mSliceHeight;
        mThread = new DecodeThread(this);
        if (mThread->run("HeifDecode", ANDROID_PRIORITY_FOREGROUND) == OK) {
            mFrameDecoded = true;
            return true;
        }

        // Fallback to decode without slicing
        mThread.clear();
        mNumSlices = 1;
        mSliceHeight = 0;
        mAvailableLines = 0;
        mFrameMemory.clear();
    }

    if (mHasImage) {
        // image index < 0 to retrieve primary image
        mFrameMemory = mRetriever->getImageAtIndex(-1, mOutputColor);
@@ -393,14 +499,14 @@ bool HeifDecoderImpl::decode(HeifFrameInfo* frameInfo) {
    }

    if (mFrameMemory == nullptr || mFrameMemory->pointer() == nullptr) {
        ALOGE("getFrameAtTime: videoFrame is a nullptr");
        ALOGE("decode: videoFrame is a nullptr");
        return false;
    }

    VideoFrame* videoFrame = static_cast<VideoFrame*>(mFrameMemory->pointer());
    if (videoFrame->mSize == 0 ||
            mFrameMemory->size() < videoFrame->getFlattenedSize()) {
        ALOGE("getFrameAtTime: videoFrame size is invalid");
        ALOGE("decode: videoFrame size is invalid");
        return false;
    }

@@ -424,36 +530,45 @@ bool HeifDecoderImpl::decode(HeifFrameInfo* frameInfo) {
    }
    mFrameDecoded = true;

    // Aggressive clear to avoid holding on to resources
    // Aggressively clear to avoid holding on to resources
    mRetriever.clear();
    mDataSource.clear();
    return true;
}

bool HeifDecoderImpl::getScanline(uint8_t* dst) {
bool HeifDecoderImpl::getScanlineInner(uint8_t* dst) {
    if (mFrameMemory == nullptr || mFrameMemory->pointer() == nullptr) {
        return false;
    }
    VideoFrame* videoFrame = static_cast<VideoFrame*>(mFrameMemory->pointer());
    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->mWidth);
    return true;
}

size_t HeifDecoderImpl::skipScanlines(size_t count) {
    if (mFrameMemory == nullptr || mFrameMemory->pointer() == nullptr) {
        return 0;
bool HeifDecoderImpl::getScanline(uint8_t* dst) {
    if (mCurScanline >= mHeight) {
        ALOGE("no more scanline available");
        return false;
    }

    if (mNumSlices > 1) {
        Mutex::Autolock autolock(mLock);

        while (!mAsyncDecodeDone && mCurScanline >= mAvailableLines) {
            mScanlineReady.wait(mLock);
        }
        return (mCurScanline < mAvailableLines) ? getScanlineInner(dst) : false;
    }

    return getScanlineInner(dst);
}
    VideoFrame* videoFrame = static_cast<VideoFrame*>(mFrameMemory->pointer());

size_t HeifDecoderImpl::skipScanlines(size_t count) {
    uint32_t oldScanline = mCurScanline;
    mCurScanline += count;
    if (mCurScanline > videoFrame->mHeight) {
        mCurScanline = videoFrame->mHeight;
    if (mCurScanline > mHeight) {
        mCurScanline = mHeight;
    }
    return (mCurScanline > oldScanline) ? (mCurScanline - oldScanline) : 0;
}
Loading