C
Qt Quick Ultralite imagedecoder Example
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial
#include "traveot2gimagedecoder.h"
#include <ut_class_surface.h>
extern "C" uint32_t Jpeg_DecStart(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
extern "C" uint32_t tvii_convert_decoded_buffers(
unsigned char *, uint32_t, uint32_t, uint32_t, uint32_t, CYGFX_SM_FORMAT);
static int16_t img_width, img_height;
bool jpegInformation(Qul::PlatformInterface::ImageDecoder::RequestDataCallback &callback,
int16_t *width,
int16_t *height,
Qul::PixelFormat *actualPixelFormat,
Qul::PixelFormat optimalOpaquePixelFormat,
Qul::PixelFormat optimalAlphaPixelFormat);
TviiImageDecoder::TviiImageDecoder() {}
TviiImageDecoder::~TviiImageDecoder() {}
bool TviiImageDecoder::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);
img_width = *width;
img_height = *height;
return ret;
}
static CYGFX_SM_FORMAT convertFormat(Qul::PixelFormat format)
{
CYGFX_SM_FORMAT result = CYGFX_SM_FORMAT_A8R8G8B8;
switch (format) {
case Qul::PixelFormat_ARGB32:
case Qul::PixelFormat_ARGB32_Premultiplied:
result = CYGFX_SM_FORMAT_A8R8G8B8;
break;
case Qul::PixelFormat_RGB32:
result = CYGFX_SM_FORMAT_X8R8G8B8;
break;
case Qul::PixelFormat_RGB888:
result = CYGFX_SM_FORMAT_R8G8B8;
break;
case Qul::PixelFormat_RGB16:
result = CYGFX_SM_FORMAT_R5G6B5;
break;
case Qul::PixelFormat_Alpha8:
result = CYGFX_SM_FORMAT_A8;
break;
default:
Qul::PlatformInterface::log("[%s] Unsupported Format! (%d)\n\r", __PRETTY_FUNCTION__, format);
}
return result;
}
int TviiImageDecoder::decodeImage(RequestDataCallback &callback,
unsigned char *outbuffer,
uint32_t outbufferSize,
Qul::PixelFormat pixelFormat,
uint32_t requiredBytesPerLine)
{
if (img_width % 64 != 0) {
Qul::PlatformInterface::log("JPEG decoder requires source images width to be multiples of 64.");
return -1;
}
unsigned int addr = reinterpret_cast<uintptr_t>(callback.rawData());
unsigned int size = callback.totalAvailableDataSize();
const uint32_t yBufferSize = img_width * img_height;
const uint32_t uvBufferSize = img_width * img_height / 2;
const uint32_t yuvBufferSize = yBufferSize + uvBufferSize;
void *yuvBuffer = utVideoAlloc(yuvBufferSize, 64, nullptr);
if (!yuvBuffer) {
Qul::PlatformInterface::log("JPEG decoder failed to allocate YUV buffer of size %d\n", yuvBufferSize);
return -1;
}
const uint32_t storeAddress0 = reinterpret_cast<uintptr_t>(yuvBuffer);
const uint32_t storeLength0 = yBufferSize;
const uint32_t storeAddress1 = storeAddress0 + storeLength0;
const uint32_t storeLength1 = uvBufferSize;
const uint32_t stride = img_width;
uint32_t ret = Jpeg_DecStart(addr, size, storeAddress0, storeAddress1, storeLength0, storeLength1, stride);
if (ret != 0) {
Qul::PlatformInterface::log("Jpeg_DecStart failed with return code %x\n", ret);
utVideoFree(yuvBuffer);
return -1;
}
ret = tvii_convert_decoded_buffers(outbuffer,
(uint32_t) img_width,
(uint32_t) img_height,
storeAddress0,
storeAddress1,
convertFormat(pixelFormat));
utVideoFree(yuvBuffer);
if (ret != 0) {
Qul::PlatformInterface::log("tvii_convert_decoded_buffers failed with return code %x\n", ret);
}
return ret;
}