389 lines
10 KiB
C++
389 lines
10 KiB
C++
/*
|
|
* Copyright (C) 2023 ArtInChip Technology Co., Ltd.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Author: Keliang Liu <keliang.liu@artinchip.com>
|
|
*/
|
|
|
|
#include "aicdashboardview.h"
|
|
|
|
#include <QPainter>
|
|
#include <QFile>
|
|
#include <QDebug>
|
|
#include <QPainter>
|
|
#include <QString>
|
|
#include <qmath.h>
|
|
|
|
AiCDashBoardView::AiCDashBoardView(QSize size, QWidget *parent) : QWidget(parent)
|
|
{
|
|
setFixedSize(size);
|
|
initView(size.width(), size.height());
|
|
}
|
|
|
|
#ifdef QTLAUNCHER_GE_SUPPORT
|
|
#define ANGLE_SIN(x) qSin(x * 3.14159265 / 180) * 4096
|
|
#define ANGLE_COS(x) qCos(x * 3.14159265 / 180) * 4096
|
|
|
|
void AiCDashBoardView::initView(int width, int height)
|
|
{
|
|
int dmafd;
|
|
mDegree1 = 0;
|
|
mDegree2 = 180;
|
|
|
|
mBoardFormat = QImage::Format_ARGB32;
|
|
mMppFormat = convertFormat(mBoardFormat);
|
|
|
|
dmafd = dmabuf_device_open();
|
|
initMppBuf(dmafd, &mBoardBuf, width, height, mMppFormat);
|
|
initMppBuf(dmafd, &mBGImgBuf, 490, 498, mMppFormat);
|
|
initMppBuf(dmafd, &mPointerImgBuf, 48, 220, mMppFormat);
|
|
|
|
dmabuf_device_close(dmafd);
|
|
// 490 x 498
|
|
decoderImage(":/resources/ge/ge-clock.png", &mBGImgBuf, 0);
|
|
// 48 x 220
|
|
decoderImage(":/resources/ge/ge-second.png", &mPointerImgBuf, 0);
|
|
|
|
setSpeed(50);
|
|
}
|
|
|
|
void AiCDashBoardView::setSpeed(int speed)
|
|
{
|
|
mTimer = new QTimer(this);
|
|
connect(mTimer, SIGNAL(timeout()), this, SLOT(onTimeOut()));
|
|
mTimer->start(speed);
|
|
}
|
|
|
|
void AiCDashBoardView::onTimeOut()
|
|
{
|
|
mDegree1 = (mDegree1 + 5) % 360;
|
|
|
|
// first clock + second
|
|
BLIT_DST_CENTER_X = 11; //(width() / 2 - 490)/2;
|
|
BLIT_DST_CENTER_Y = 11; //(height() - 498)/2;
|
|
ROT_SRC_CENTER_X = 24;
|
|
ROT_SRC_CENTER_Y = 194;
|
|
ROT_DST_CENTER_X = 255; //(width() / 2 - 48)/2 + BLIT_DST_CENTER_X + 10;
|
|
ROT_DST_CENTER_Y = 257; // height()/2 - BLIT_DST_CENTER_Y + 8;
|
|
geBlit(&mBoardBuf, &mBGImgBuf, 0);
|
|
geRotate(&mBoardBuf, &mPointerImgBuf, mDegree1);
|
|
|
|
// second clock + second
|
|
mDegree2 = (mDegree2 + 5) % 360;
|
|
BLIT_DST_CENTER_X = 523; // width() / 2 + (width() / 2 - 490)/2;
|
|
BLIT_DST_CENTER_Y = 11; //(height() - 498)/2;
|
|
ROT_SRC_CENTER_X = 24;
|
|
ROT_SRC_CENTER_Y = 194;
|
|
ROT_DST_CENTER_X = 767; //(width() / 2 - 48)/2 + BLIT_DST_CENTER_X + 10;
|
|
ROT_DST_CENTER_Y = 257; // height()/2 - BLIT_DST_CENTER_Y + 8;
|
|
geBlit(&mBoardBuf, &mBGImgBuf, 0);
|
|
geRotate(&mBoardBuf, &mPointerImgBuf, mDegree2);
|
|
|
|
update();
|
|
}
|
|
|
|
void AiCDashBoardView::paintEvent(QPaintEvent *)
|
|
{
|
|
QPainter painter(this);
|
|
int size = calMppBufSize(&mBoardBuf);
|
|
unsigned char *buf = dmabuf_mmap(mBoardBuf.fd[0], size);
|
|
painter.drawImage(0, 0, QImage(buf, width(), height(), mBoardFormat));
|
|
dmabuf_munmap(buf, size);
|
|
}
|
|
|
|
int AiCDashBoardView::calMppBufSize(struct mpp_buf *buf)
|
|
{
|
|
return buf->stride[0] * buf->size.height;
|
|
}
|
|
|
|
int AiCDashBoardView::calDmaBufSize(int width, int height, mpp_pixel_format mppFormat)
|
|
{
|
|
int bytes = 4;
|
|
switch (mppFormat)
|
|
{
|
|
case MPP_FMT_ARGB_8888:
|
|
bytes = 4;
|
|
break;
|
|
case MPP_FMT_RGB_888:
|
|
bytes = 3;
|
|
break;
|
|
case MPP_FMT_RGB_565:
|
|
bytes = 2;
|
|
break;
|
|
default:
|
|
bytes = 4;
|
|
break;
|
|
}
|
|
|
|
return width * height * bytes;
|
|
}
|
|
|
|
int AiCDashBoardView::createDmaBuf(int dmafd, int width, int height, mpp_pixel_format mppFormat)
|
|
{
|
|
int size = calDmaBufSize(width, height, mppFormat);
|
|
int fd = dmabuf_alloc(dmafd, size);
|
|
if (fd < 0)
|
|
return -1;
|
|
|
|
unsigned char *buf = dmabuf_mmap(fd, size);
|
|
if (buf == NULL)
|
|
return -1;
|
|
|
|
memset(buf, 0, size);
|
|
dmabuf_munmap(buf, size);
|
|
return fd;
|
|
}
|
|
|
|
void AiCDashBoardView::initMppBuf(int dmafd, struct mpp_buf *buf, int width, int height, mpp_pixel_format mppFormat)
|
|
{
|
|
buf->buf_type = MPP_DMA_BUF_FD;
|
|
buf->fd[0] = createDmaBuf(dmafd, width, height, mppFormat);
|
|
buf->stride[0] = calStrideSize(width, mppFormat);
|
|
buf->size.width = width;
|
|
buf->size.height = height;
|
|
buf->format = mppFormat;
|
|
buf->crop_en = 0;
|
|
buf->crop.x = 0;
|
|
buf->crop.y = 0;
|
|
buf->crop.width = 0;
|
|
buf->crop.height = 0;
|
|
}
|
|
|
|
void AiCDashBoardView::copyMppBuf(struct mpp_buf *dst, struct mpp_buf *src)
|
|
{
|
|
dst->buf_type = src->buf_type;
|
|
dst->fd[0] = src->fd[0];
|
|
dst->stride[0] = src->stride[0];
|
|
dst->size.width = src->size.width;
|
|
dst->size.height = src->size.height;
|
|
dst->format = src->format;
|
|
dst->crop_en = src->crop_en;
|
|
dst->crop.x = src->crop.x;
|
|
dst->crop.y = src->crop.x;
|
|
dst->crop.width = src->crop.width;
|
|
dst->crop.height = src->crop.height;
|
|
}
|
|
|
|
int AiCDashBoardView::calStrideSize(int width, mpp_pixel_format mppFormat)
|
|
{
|
|
int bytes = 4;
|
|
switch (mppFormat)
|
|
{
|
|
case MPP_FMT_ARGB_8888:
|
|
bytes = 4;
|
|
break;
|
|
case MPP_FMT_RGB_888:
|
|
bytes = 3;
|
|
break;
|
|
case MPP_FMT_RGB_565:
|
|
bytes = 2;
|
|
break;
|
|
default:
|
|
bytes = 4;
|
|
break;
|
|
}
|
|
|
|
return width * bytes;
|
|
}
|
|
|
|
mpp_pixel_format AiCDashBoardView::convertFormat(QImage::Format format)
|
|
{
|
|
switch (format)
|
|
{
|
|
case QImage::Format_ARGB32:
|
|
return MPP_FMT_ARGB_8888;
|
|
case QImage::Format_RGB888:
|
|
return MPP_FMT_RGB_888;
|
|
case QImage::Format_RGB16:
|
|
return MPP_FMT_RGB_565;
|
|
default:
|
|
return MPP_FMT_ARGB_8888;
|
|
}
|
|
}
|
|
|
|
void AiCDashBoardView::decoderImage(const char *fileName, struct mpp_buf *buf, int rotate)
|
|
{
|
|
int ret = 0;
|
|
int fileSize = 0;
|
|
mpp_codec_type codecType = MPP_CODEC_VIDEO_DECODER_PNG;
|
|
QFile file(fileName);
|
|
|
|
if (file.open(QFile::ReadOnly))
|
|
fileSize = file.size();
|
|
else
|
|
return;
|
|
|
|
// 1. create mpp_decoder
|
|
struct mpp_decoder *dec = mpp_decoder_create(MPP_CODEC_VIDEO_DECODER_PNG);
|
|
|
|
struct decode_config config;
|
|
config.bitstream_buffer_size = (fileSize + 0xFF) & (~0xFF);
|
|
config.extra_frame_num = 0;
|
|
config.packet_count = 1;
|
|
|
|
// JPEG not supprt YUV2RGB
|
|
if (codecType == MPP_CODEC_VIDEO_DECODER_MJPEG)
|
|
config.pix_fmt = MPP_FMT_YUV420P;
|
|
else if (codecType == MPP_CODEC_VIDEO_DECODER_PNG)
|
|
config.pix_fmt = mMppFormat;
|
|
|
|
// 2. init mpp_decoder
|
|
mpp_decoder_init(dec, &config);
|
|
|
|
// 3. get an empty packet from mpp_decoder
|
|
struct mpp_packet packet;
|
|
memset(&packet, 0, sizeof(struct mpp_packet));
|
|
mpp_decoder_get_packet(dec, &packet, fileSize);
|
|
|
|
// 4. copy data to packet
|
|
packet.size = file.read((char *)packet.data, fileSize);
|
|
packet.flag = PACKET_FLAG_EOS;
|
|
|
|
// 5. put the packet to mpp_decoder
|
|
mpp_decoder_put_packet(dec, &packet);
|
|
|
|
// 6. decode
|
|
ret = mpp_decoder_decode(dec);
|
|
if (ret < 0)
|
|
{
|
|
qDebug() << "decode error";
|
|
mpp_decoder_destory(dec);
|
|
return;
|
|
}
|
|
|
|
// 7. get a decoded frame
|
|
struct mpp_frame frame;
|
|
memset(&frame, 0, sizeof(struct mpp_frame));
|
|
mpp_decoder_get_frame(dec, &frame);
|
|
|
|
// 8. ge copy, copy frame to the right dma buffer
|
|
geCopy(buf, &frame.buf, rotate);
|
|
// 9. return this frame
|
|
mpp_decoder_put_frame(dec, &frame);
|
|
|
|
// 10. destroy mpp_decoder
|
|
mpp_decoder_destory(dec);
|
|
}
|
|
|
|
void AiCDashBoardView::geCopy(struct mpp_buf *dstbuf, struct mpp_buf *srcbuf, int rotate)
|
|
{
|
|
struct mpp_ge *ge = mpp_ge_open();
|
|
struct ge_bitblt blt;
|
|
memset(&blt, 0, sizeof(blt));
|
|
|
|
blt.src_buf.buf_type = MPP_DMA_BUF_FD;
|
|
if (srcbuf->format == MPP_FMT_ARGB_8888 || srcbuf->format == MPP_FMT_RGB_888 || srcbuf->format == MPP_FMT_RGB_565)
|
|
{
|
|
mpp_ge_add_dmabuf(ge, srcbuf->fd[0]);
|
|
blt.src_buf.fd[0] = srcbuf->fd[0];
|
|
blt.src_buf.stride[0] = srcbuf->stride[0];
|
|
blt.src_buf.format = srcbuf->format;
|
|
}
|
|
else if (srcbuf->format == MPP_FMT_YUV420P)
|
|
{
|
|
mpp_ge_add_dmabuf(ge, srcbuf->fd[0]);
|
|
mpp_ge_add_dmabuf(ge, srcbuf->fd[1]);
|
|
mpp_ge_add_dmabuf(ge, srcbuf->fd[2]);
|
|
blt.src_buf.fd[0] = srcbuf->fd[0];
|
|
blt.src_buf.fd[1] = srcbuf->fd[1];
|
|
blt.src_buf.fd[2] = srcbuf->fd[2];
|
|
blt.src_buf.stride[0] = srcbuf->stride[0];
|
|
blt.src_buf.stride[1] = srcbuf->stride[1];
|
|
blt.src_buf.stride[2] = srcbuf->stride[2];
|
|
blt.src_buf.format = srcbuf->format;
|
|
}
|
|
|
|
blt.src_buf.size.width = srcbuf->size.width;
|
|
blt.src_buf.size.height = srcbuf->size.height;
|
|
blt.src_buf.crop_en = 0;
|
|
|
|
blt.ctrl.flags = rotate / 90; // rotate flag
|
|
blt.ctrl.ck_en = 0;
|
|
|
|
copyMppBuf(&blt.dst_buf, dstbuf);
|
|
blt.dst_buf.crop_en = 0;
|
|
blt.dst_buf.crop.width = 0;
|
|
blt.dst_buf.crop.height = 0;
|
|
blt.dst_buf.crop.x = 0;
|
|
blt.dst_buf.crop.y = 0;
|
|
|
|
mpp_ge_bitblt(ge, &blt);
|
|
mpp_ge_emit(ge);
|
|
mpp_ge_sync(ge);
|
|
mpp_ge_close(ge);
|
|
}
|
|
|
|
void AiCDashBoardView::geBlit(struct mpp_buf *dst, struct mpp_buf *src, int rotate)
|
|
{
|
|
struct mpp_ge *ge = mpp_ge_open();
|
|
struct ge_bitblt blt;
|
|
|
|
memset(&blt, 0, sizeof(struct ge_bitblt));
|
|
copyMppBuf(&blt.src_buf, src);
|
|
copyMppBuf(&blt.dst_buf, dst);
|
|
blt.dst_buf.crop_en = 1;
|
|
blt.dst_buf.crop.x = BLIT_DST_CENTER_X;
|
|
blt.dst_buf.crop.y = BLIT_DST_CENTER_Y;
|
|
blt.dst_buf.crop.width = src->size.width;
|
|
blt.dst_buf.crop.height = src->size.height;
|
|
|
|
blt.ctrl.flags = rotate / 90;
|
|
|
|
mpp_ge_bitblt(ge, &blt);
|
|
|
|
mpp_ge_emit(ge);
|
|
|
|
mpp_ge_sync(ge);
|
|
|
|
mpp_ge_close(ge);
|
|
}
|
|
|
|
void AiCDashBoardView::geRotate(struct mpp_buf *dst, struct mpp_buf *src, int angle)
|
|
{
|
|
struct mpp_ge *ge = mpp_ge_open();
|
|
struct ge_rotation rot;
|
|
|
|
memset(&rot, 0, sizeof(rot));
|
|
// source buffer
|
|
copyMppBuf(&rot.src_buf, src);
|
|
|
|
rot.src_buf.crop_en = 0;
|
|
rot.src_rot_center.x = ROT_SRC_CENTER_X;
|
|
rot.src_rot_center.y = ROT_SRC_CENTER_Y;
|
|
|
|
// destination buffer
|
|
copyMppBuf(&rot.dst_buf, dst);
|
|
|
|
rot.dst_buf.crop_en = 0;
|
|
rot.dst_rot_center.x = ROT_DST_CENTER_X;
|
|
rot.dst_rot_center.y = ROT_DST_CENTER_Y;
|
|
|
|
rot.ctrl.alpha_en = 1;
|
|
|
|
rot.angle_sin = (int)(ANGLE_SIN(angle));
|
|
rot.angle_cos = (int)(ANGLE_COS(angle));
|
|
|
|
mpp_ge_rotate(ge, &rot);
|
|
mpp_ge_emit(ge);
|
|
mpp_ge_sync(ge);
|
|
mpp_ge_close(ge);
|
|
}
|
|
|
|
AiCDashBoardView::~AiCDashBoardView()
|
|
{
|
|
dmabuf_free(mBoardBuf.fd[0]);
|
|
dmabuf_free(mPointerImgBuf.fd[0]);
|
|
dmabuf_free(mBGImgBuf.fd[0]);
|
|
}
|
|
#else
|
|
void AiCDashBoardView::initView(int width, int height)
|
|
{
|
|
qDebug() << width << ":" << height;
|
|
}
|
|
|
|
AiCDashBoardView::~AiCDashBoardView()
|
|
{
|
|
}
|
|
#endif
|