C
Qt Quick Ultralite imagedecoder Example
/****************************************************************************** ** ** Copyright (C) 2024 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Quick Ultralite module. ** ** $QT_BEGIN_LICENSE:COMM$ ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** $QT_END_LICENSE$ ** ******************************************************************************/#include "rh850imagedecoder.h" #include "rh850_jpeg.h" #include <platforminterface/memoryallocator.h> #include <platform/platform.h> bool jpegInformation(Qul::PlatformInterface::ImageDecoder::RequestDataCallback &callback, int16_t *width, int16_t *height, Qul::PixelFormat *actualPixelFormat, Qul::PixelFormat optimalOpaquePixelFormat, Qul::PixelFormat optimalAlphaPixelFormat); void Rh850ImageDecoder::adjustForMCUSize(r_jcua_JpegFormat_t format, r_jcua_ImageInfo_t &jpegInfo) { switch (format) { case R_JCUA_JPEG_FORMAT_YCBCR420: //MCU size: 16x16 jpegInfo.DecodeWidth = (m_width % 16) ? 16 * ((m_width / 16) + 1) : m_width; jpegInfo.DecodeHeight = (m_height % 16) ? 16 * ((m_height / 16) + 1) : m_height; break; case R_JCUA_JPEG_FORMAT_YCBCR411: //MCU size: 8x32 jpegInfo.DecodeWidth = (m_width % 8) ? 8 * ((m_width / 8) + 1) : m_width; jpegInfo.DecodeHeight = (m_height % 32) ? 32 * ((m_height / 32) + 1) : m_height; break; case R_JCUA_JPEG_FORMAT_YCBCR422: //MCU size: 8x16 jpegInfo.DecodeWidth = (m_width % 8) ? 8 * ((m_width / 8) + 1) : m_width; jpegInfo.DecodeHeight = (m_height % 16) ? 16 * ((m_height / 16) + 1) : m_height; break; case R_JCUA_JPEG_FORMAT_YCBCR444: //MCU size: 8x8 jpegInfo.DecodeWidth = (m_width % 8) ? 8 * ((m_width / 8) + 1) : m_width; jpegInfo.DecodeHeight = (m_height % 8) ? 8 * ((m_height / 8) + 1) : m_height; break; default: Qul::PlatformInterface::log("Decode Error: Invalid chroma-subsampling format\r\n"); break; } } Rh850ImageDecoder::Rh850ImageDecoder() {} Rh850ImageDecoder::~Rh850ImageDecoder() {} bool Rh850ImageDecoder::imageInformation(RequestDataCallback &callback, int16_t *width, int16_t *height, Qul::PixelFormat *actualPixelFormat, Qul::PixelFormat optimalOpaquePixelFormat, Qul::PixelFormat optimalAlphaPixelFormat) { bool ret = jpegInformation(callback, width, height, actualPixelFormat, optimalOpaquePixelFormat, optimalAlphaPixelFormat); *actualPixelFormat = Qul::PixelFormat_ARGB32; m_width = *width; m_height = *height; return ret; } int Rh850ImageDecoder::decodeImage(RequestDataCallback &callback, unsigned char *outBuffer, uint32_t outBufferSize, Qul::PixelFormat pixelFormat, uint32_t requiredBytesPerLine) { const uint8_t decodeBuffer_bpp = 4; r_jcua_ImageInfo_t jpegInfo; if (pixelFormat != Qul::PixelFormat_ARGB32) { Qul::PlatformInterface::log("Decode Error: PixelFormat not supported\r\n"); return 1; } jpegInfo.Width = m_width; jpegInfo.Height = m_height; jpegInfo.EncodedFormat = CHROMA_SUBSAMPLING; //Adjust width and height for Minimum Coded Unit(MCU) size adjustForMCUSize(jpegInfo.EncodedFormat, jpegInfo); jpegInfo.StridePixel = jpegInfo.DecodeWidth; jpegInfo.Stride = jpegInfo.DecodeWidth * decodeBuffer_bpp; #ifdef USE_OUTPUT_SPLIT_MODE /* if JPEG Decoder is configured for division mode, use a image block with pixel lines which is multiples of 16 * for storing decoded output. JPEG decoder resues this image block to avoid allocating large process buffer. */ uint32_t processBufferSize = jpegInfo.DecodeWidth * decodeBuffPixelLines() * decodeBuffer_bpp; /* For images with YCrCb420 subsampling, the buffer must be atleast TWICE of this block size, * hence the factor 2. */ if (jpegInfo.EncodedFormat == R_JCUA_JPEG_FORMAT_YCBCR420) processBufferSize *= 2; #else uint32_t processBufferSize = jpegInfo.DecodeWidth * jpegInfo.DecodeHeight * decodeBuffer_bpp; #endif /* Allocate the process buffer from VRAM. * Renesas JCUA hardware does not allow decoder output framebuffer from internal RAM. */ Qul::PlatformInterface::MemoryAllocator *allocator = Qul::Platform::getPlatformInstance()->memoryAllocator( Qul::PlatformInterface::MemoryAllocator::Custom); if (!allocator) { Qul::PlatformInterface::log("Decode Error: NULL Allocator\r\n"); return 1; } /*Renesas JCUA driver requires 8 byte alignment for buffers*/ const size_t alignment = 8; const size_t offset = alignment - 1; unsigned char *addr = static_cast<unsigned char *>(allocator->allocate(processBufferSize + offset)); if (!addr) { Qul::PlatformInterface::log("Decode Error: allocation failed\r\n"); return 1; } void *processBufferAligned = (void *) ((size_t) addr); size_t space = processBufferSize + offset; Qul::PlatformInterface::stdalign(alignment, processBufferSize, processBufferAligned, space); #ifdef RH850_JPEG_DEBUG_LOGS Qul::PlatformInterface::log("ProcessWidth: %d, ProcessHeight %d\r\n", jpegInfo.DecodeWidth, jpegInfo.DecodeHeight); Qul::PlatformInterface::log("PixelFormat: %d, OutBufferSize %d, AllocatedBffer 0x%x, Req Bpl: %d, Size: %d\r\n", pixelFormat, outBufferSize, processBufferAligned, requiredBytesPerLine, processBufferSize); #endif r_jcua_Error_t ret = jpegDecode_Start(callback, outBuffer, outBufferSize, processBufferAligned, requiredBytesPerLine, jpegInfo); allocator->free(addr); if (ret != R_JCUA_ERR_OK) { r_jcua_ErrorDetail_t errorCode; R_JCUA_ErrorInfoGet(JCUA_HW_UNIT, &errorCode); Qul::PlatformInterface::log("Decoder failed with error Code 0x%X\r\n", errorCode); return 1; } return 0; }