mirror of
https://gitee.com/Vancouver2017/luban-lite-t3e-pro.git
synced 2025-12-14 10:28:54 +00:00
V1.0.6
This commit is contained in:
17
packages/artinchip/lvgl-ui/aic_widgets/SConscript
Normal file
17
packages/artinchip/lvgl-ui/aic_widgets/SConscript
Normal file
@@ -0,0 +1,17 @@
|
||||
from building import *
|
||||
import os
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
group = []
|
||||
src = Glob('*.c')
|
||||
CPPPATH = [cwd]
|
||||
|
||||
list = os.listdir(cwd)
|
||||
for d in list:
|
||||
path = os.path.join(cwd, d)
|
||||
if os.path.isfile(os.path.join(path, 'SConscript')):
|
||||
group = group + SConscript(os.path.join(d, 'SConscript'))
|
||||
|
||||
group = group + DefineGroup('LVGL-port', src, depend = ['LPKG_USING_LVGL'], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
17
packages/artinchip/lvgl-ui/aic_widgets/aic_canvas/SConscript
Normal file
17
packages/artinchip/lvgl-ui/aic_widgets/aic_canvas/SConscript
Normal file
@@ -0,0 +1,17 @@
|
||||
from building import *
|
||||
import os
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
group = []
|
||||
src = Glob('*.c')
|
||||
CPPPATH = [cwd]
|
||||
|
||||
list = os.listdir(cwd)
|
||||
for d in list:
|
||||
path = os.path.join(cwd, d)
|
||||
if os.path.isfile(os.path.join(path, 'SConscript')):
|
||||
group = group + SConscript(os.path.join(d, 'SConscript'))
|
||||
|
||||
group = group + DefineGroup('LVGL-port', src, depend = ['LPKG_USING_LVGL'], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
127
packages/artinchip/lvgl-ui/aic_widgets/aic_canvas/canvas_image.c
Normal file
127
packages/artinchip/lvgl-ui/aic_widgets/aic_canvas/canvas_image.c
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) 2024, ArtInChip Technology Co., Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Authors: Ning Fang <ning.fang@artinchip.com>
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
#include "lvgl.h"
|
||||
#include "aic_ui.h"
|
||||
#include "aic_core.h"
|
||||
#include "mpp_ge.h"
|
||||
|
||||
#define ALIGN_8B(x) (((x) + (7)) & ~7)
|
||||
#define ALIGN_1024B(x) ((x+1023) & (~1023))
|
||||
|
||||
struct lv_mpp_buf
|
||||
{
|
||||
struct mpp_buf buf;
|
||||
unsigned char *data;
|
||||
int size;
|
||||
};
|
||||
|
||||
struct lv_mpp_buf *lv_mpp_image_alloc(int width, int height, enum mpp_pixel_format fmt)
|
||||
{
|
||||
struct lv_mpp_buf *image;
|
||||
|
||||
int size = 0;
|
||||
image = (struct lv_mpp_buf *)aicos_malloc(MEM_DEFAULT, sizeof(struct lv_mpp_buf));
|
||||
if (!image) {
|
||||
LV_LOG_ERROR("aicos_malloc failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(image, 0, sizeof(struct lv_mpp_buf));
|
||||
if (fmt == MPP_FMT_ARGB_8888) {
|
||||
image->buf.stride[0] = ALIGN_8B(width * 4);
|
||||
} else if (fmt == MPP_FMT_RGB_565) {
|
||||
image->buf.stride[0] = ALIGN_8B(width * 2);
|
||||
} else {
|
||||
LV_LOG_ERROR("unsupport fmt:%d", fmt);
|
||||
aicos_free(MEM_DEFAULT, image);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size = image->buf.stride[0] * height;
|
||||
image->size = size;
|
||||
image->buf.buf_type = MPP_PHY_ADDR;
|
||||
image->buf.size.width = width;
|
||||
image->buf.size.height = height;
|
||||
image->buf.format = fmt;
|
||||
image->data = (unsigned char *)aicos_malloc(MEM_CMA, size + 1023);
|
||||
if (!image->data) {
|
||||
aicos_free(MEM_DEFAULT, image);
|
||||
return NULL;
|
||||
} else {
|
||||
image->buf.phy_addr[0] = (unsigned int)ALIGN_1024B(((unsigned long)image->data));
|
||||
aicos_dcache_clean_invalid_range((unsigned long *)((unsigned long)image->buf.phy_addr[0]), size);
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
void lv_mpp_image_flush_cache(struct lv_mpp_buf *image)
|
||||
{
|
||||
aicos_dcache_clean_invalid_range((unsigned long *)((unsigned long)image->buf.phy_addr[0]), image->size);
|
||||
return;
|
||||
}
|
||||
|
||||
void lv_mpp_image_free(struct lv_mpp_buf *image)
|
||||
{
|
||||
if (image) {
|
||||
if (image->data)
|
||||
aicos_free(MEM_CMA, image->data);
|
||||
|
||||
aicos_free(MEM_DEFAULT, image);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static struct mpp_ge *g_ge = NULL;
|
||||
|
||||
int lv_ge_fill(struct mpp_buf *buf, enum ge_fillrect_type type,
|
||||
unsigned int start_color, unsigned int end_color, int blend)
|
||||
{
|
||||
int ret;
|
||||
struct ge_fillrect fill = { 0 };
|
||||
|
||||
if (!g_ge)
|
||||
g_ge = mpp_ge_open();
|
||||
|
||||
/* fill info */
|
||||
fill.type = type;
|
||||
fill.start_color = start_color;
|
||||
fill.end_color = end_color;
|
||||
|
||||
/* dst buf */
|
||||
memcpy(&fill.dst_buf, buf, sizeof(struct mpp_buf));
|
||||
|
||||
/* ctrl */
|
||||
fill.ctrl.flags = 0;
|
||||
fill.ctrl.alpha_en = blend;
|
||||
|
||||
ret = mpp_ge_fillrect(g_ge, &fill);
|
||||
if (ret < 0) {
|
||||
LV_LOG_WARN("fillrect1 fail\n");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
ret = mpp_ge_emit(g_ge);
|
||||
if (ret < 0) {
|
||||
LV_LOG_WARN("emit fail\n");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
ret = mpp_ge_sync(g_ge);
|
||||
if (ret < 0) {
|
||||
LV_LOG_WARN("sync fail\n");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2022-2024, ArtInChip Technology Co., Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Authors: Ning Fang <ning.fang@artinchip.com>
|
||||
*/
|
||||
|
||||
#ifndef CANVAS_IMAGE_H
|
||||
#define CANVAS_IMAGE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "lvgl.h"
|
||||
#include "aic_ui.h"
|
||||
#include "aic_core.h"
|
||||
#include "mpp_ge.h"
|
||||
|
||||
struct lv_mpp_buf
|
||||
{
|
||||
struct mpp_buf buf;
|
||||
unsigned char *data;
|
||||
int size;
|
||||
};
|
||||
|
||||
struct lv_mpp_buf *lv_mpp_image_alloc(int width, int height, enum mpp_pixel_format fmt);
|
||||
|
||||
void lv_mpp_image_flush_cache(struct lv_mpp_buf *image);
|
||||
|
||||
void lv_mpp_image_free(struct lv_mpp_buf *image);
|
||||
|
||||
int lv_ge_fill(struct mpp_buf *buf, enum ge_fillrect_type type,
|
||||
unsigned int start_color, unsigned int end_color, int blend);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif //CANVAS_IMAGE_H
|
||||
@@ -0,0 +1,310 @@
|
||||
/*
|
||||
* Copyright (c) 2024, ArtInChip Technology Co., Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Authors: Ning Fang <ning.fang@artinchip.com>
|
||||
*/
|
||||
|
||||
#include "lv_aic_canvas.h"
|
||||
#include "lv_assert.h"
|
||||
#include "lv_math.h"
|
||||
#include "lv_draw.h"
|
||||
#include "lv_refr.h"
|
||||
#include "lv_draw_sw.h"
|
||||
|
||||
#define USE_HW_IMG_BLIT
|
||||
|
||||
#define MY_CLASS &lv_aic_canvas_class
|
||||
|
||||
static void lv_aic_canvas_constructor(const lv_obj_class_t *class_p, lv_obj_t *obj);
|
||||
static void lv_aic_canvas_destructor(const lv_obj_class_t *class_p, lv_obj_t *obj);
|
||||
static void init_fake_disp(lv_obj_t *canvas, lv_disp_t *disp, lv_disp_drv_t *drv, lv_area_t *clip_area);
|
||||
static void deinit_fake_disp(lv_obj_t *canvas, lv_disp_t *disp);
|
||||
|
||||
const lv_obj_class_t lv_aic_canvas_class = {
|
||||
.constructor_cb = lv_aic_canvas_constructor,
|
||||
.destructor_cb = lv_aic_canvas_destructor,
|
||||
.instance_size = sizeof(lv_aic_canvas_t),
|
||||
.base_class = &lv_img_class
|
||||
};
|
||||
|
||||
lv_obj_t *lv_aic_canvas_create(lv_obj_t * parent)
|
||||
{
|
||||
LV_LOG_INFO("begin");
|
||||
lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent);
|
||||
lv_obj_class_init_obj(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
lv_res_t lv_aic_canvas_alloc_buffer(lv_obj_t *obj, lv_coord_t w, lv_coord_t h, lv_img_cf_t cf)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
// only support argb8888 currently
|
||||
enum mpp_pixel_format fmt = MPP_FMT_ARGB_8888;
|
||||
lv_aic_canvas_t *canvas = (lv_aic_canvas_t *)obj;
|
||||
|
||||
if (cf != LV_IMG_CF_TRUE_COLOR_ALPHA) {
|
||||
LV_LOG_WARN("please check cf: %d, only support LV_IMG_CF_TRUE_COLOR_ALPHA", cf);
|
||||
}
|
||||
|
||||
canvas->img_buf= lv_mpp_image_alloc(w, h, fmt);
|
||||
if (!canvas->img_buf) {
|
||||
LV_LOG_ERROR("lv_mpp_image_alloc failed");
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
#ifdef USE_HW_IMG_BLIT
|
||||
canvas->dsc.header.cf = LV_IMG_CF_RESERVED_16;
|
||||
canvas->dsc.header.w = w;
|
||||
canvas->dsc.header.h = h;
|
||||
canvas->dsc.data = (uint8_t *)&canvas->img_buf->buf;
|
||||
#else
|
||||
canvas->dsc.header.cf = cf;
|
||||
canvas->dsc.header.w = w;
|
||||
canvas->dsc.header.h = h;
|
||||
canvas->dsc.data = (void *)((unsigned long)(canvas->img_buf->buf.phy_addr[0]));
|
||||
#endif
|
||||
lv_img_set_src(obj, &canvas->dsc);
|
||||
lv_img_cache_invalidate_src(&canvas->dsc);
|
||||
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
void lv_aic_canvas_draw_text(lv_obj_t *obj, lv_coord_t x, lv_coord_t y, lv_coord_t max_w,
|
||||
lv_draw_label_dsc_t * draw_dsc, const char * txt)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
|
||||
lv_aic_canvas_t *canvas = (lv_aic_canvas_t *)obj;
|
||||
lv_img_dsc_t *dsc = &canvas->dsc;
|
||||
|
||||
if(dsc->header.cf >= LV_IMG_CF_INDEXED_1BIT && dsc->header.cf <= LV_IMG_CF_INDEXED_8BIT) {
|
||||
LV_LOG_WARN("lv_canvas_draw_text: can't draw to LV_IMG_CF_INDEXED canvas");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a dummy display to fool the lv_draw function, It will think it draws to real screen
|
||||
lv_disp_t fake_disp;
|
||||
lv_disp_drv_t driver;
|
||||
lv_area_t clip_area;
|
||||
init_fake_disp(obj, &fake_disp, &driver, &clip_area);
|
||||
|
||||
lv_disp_t * refr_ori = _lv_refr_get_disp_refreshing();
|
||||
_lv_refr_set_disp_refreshing(&fake_disp);
|
||||
|
||||
lv_area_t coords;
|
||||
coords.x1 = x;
|
||||
coords.y1 = y;
|
||||
coords.x2 = x + max_w - 1;
|
||||
coords.y2 = dsc->header.h - 1;
|
||||
lv_draw_label(driver.draw_ctx, draw_dsc, &coords, txt, NULL);
|
||||
|
||||
_lv_refr_set_disp_refreshing(refr_ori);
|
||||
|
||||
deinit_fake_disp(obj, &fake_disp);
|
||||
|
||||
if (dsc->header.cf == LV_IMG_CF_RESERVED_16) {
|
||||
lv_mpp_image_flush_cache(canvas->img_buf);
|
||||
}
|
||||
|
||||
lv_obj_invalidate(obj);
|
||||
}
|
||||
|
||||
void lv_aic_canvas_draw_text_to_center(lv_obj_t *obj, lv_draw_label_dsc_t *label_dsc, const char *txt)
|
||||
{
|
||||
lv_aic_canvas_t *canvas = (lv_aic_canvas_t *)obj;
|
||||
lv_ge_fill(&canvas->img_buf->buf, GE_NO_GRADIENT, 0x00000000, 0x00000000, 0);
|
||||
|
||||
lv_point_t txt_size;
|
||||
lv_txt_get_size(&txt_size, txt, label_dsc->font, 0, 0, LV_COORD_MAX, LV_TEXT_FLAG_NONE);
|
||||
|
||||
lv_coord_t x = (canvas->dsc.header.w - txt_size.x) / 2;
|
||||
lv_coord_t y = (canvas->dsc.header.h - txt_size.y) / 2;
|
||||
|
||||
lv_aic_canvas_draw_text(obj, x, y, canvas->dsc.header.w, label_dsc, txt);
|
||||
lv_mpp_image_flush_cache(canvas->img_buf);
|
||||
lv_obj_invalidate(obj);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void lv_aic_canvas_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||
{
|
||||
LV_UNUSED(class_p);
|
||||
LV_TRACE_OBJ_CREATE("begin");
|
||||
|
||||
lv_aic_canvas_t * canvas = (lv_aic_canvas_t *)obj;
|
||||
|
||||
canvas->dsc.header.always_zero = 0;
|
||||
canvas->dsc.header.cf = LV_IMG_CF_TRUE_COLOR;
|
||||
canvas->dsc.header.h = 0;
|
||||
canvas->dsc.header.w = 0;
|
||||
canvas->dsc.data_size = 0;
|
||||
canvas->dsc.data = NULL;
|
||||
|
||||
lv_img_set_src(obj, &canvas->dsc);
|
||||
|
||||
if (canvas->img_buf)
|
||||
lv_mpp_image_free(canvas->img_buf);
|
||||
|
||||
LV_TRACE_OBJ_CREATE("finished");
|
||||
}
|
||||
|
||||
static void lv_aic_canvas_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj)
|
||||
{
|
||||
LV_UNUSED(class_p);
|
||||
LV_TRACE_OBJ_CREATE("begin");
|
||||
|
||||
lv_aic_canvas_t * canvas = (lv_aic_canvas_t *)obj;
|
||||
lv_img_cache_invalidate_src(&canvas->dsc);
|
||||
}
|
||||
|
||||
static inline lv_color32_t lv_pixel_mix(lv_color32_t c1, lv_color32_t c2, uint8_t mix)
|
||||
{
|
||||
lv_color32_t ret;
|
||||
|
||||
ret.ch.red = LV_UDIV255(c1.ch.red *mix + c2.ch.red * (255 - mix) + LV_COLOR_MIX_ROUND_OFS);
|
||||
ret.ch.green = LV_UDIV255(c1.ch.green *mix + c2.ch.green * (255 - mix) + LV_COLOR_MIX_ROUND_OFS);
|
||||
ret.ch.blue = LV_UDIV255(c1.ch.blue *mix + c2.ch.blue * (255 - mix) + LV_COLOR_MIX_ROUND_OFS);
|
||||
ret.ch.alpha = 0xff;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void lv_pixel_mix_with_alpha(lv_color32_t bg_color, lv_opa_t bg_opa,
|
||||
lv_color32_t fg_color, lv_opa_t fg_opa,
|
||||
lv_color32_t *res_color, lv_opa_t *res_opa)
|
||||
{
|
||||
if(fg_opa >= LV_OPA_MAX || bg_opa <= LV_OPA_MIN) {
|
||||
res_color->full = fg_color.full;
|
||||
*res_opa = fg_opa;
|
||||
} else if(fg_opa <= LV_OPA_MIN) {
|
||||
res_color->full = bg_color.full;
|
||||
*res_opa = bg_opa;
|
||||
} else if(bg_opa >= LV_OPA_MAX) {
|
||||
*res_color = lv_pixel_mix(fg_color, bg_color, fg_opa);
|
||||
*res_opa = LV_OPA_COVER;
|
||||
} else {
|
||||
static lv_opa_t fg_opa_save = 0;
|
||||
static lv_opa_t bg_opa_save = 0;
|
||||
static lv_color32_t fg_color_save = _LV_COLOR_ZERO_INITIALIZER32;
|
||||
static lv_color32_t bg_color_save = _LV_COLOR_ZERO_INITIALIZER32;
|
||||
static lv_color32_t res_color_saved = _LV_COLOR_ZERO_INITIALIZER32;
|
||||
static lv_opa_t res_opa_saved = 0;
|
||||
|
||||
if(fg_opa != fg_opa_save || bg_opa != bg_opa_save || fg_color.full != fg_color_save.full ||
|
||||
bg_color.full != bg_color_save.full) {
|
||||
fg_opa_save = fg_opa;
|
||||
bg_opa_save = bg_opa;
|
||||
fg_color_save.full = fg_color.full;
|
||||
bg_color_save.full = bg_color.full;
|
||||
res_opa_saved = 255 - ((uint16_t)((uint16_t)(255 - fg_opa) * (255 - bg_opa)) >> 8);
|
||||
LV_ASSERT(res_opa_saved != 0);
|
||||
lv_opa_t ratio = (uint16_t)((uint16_t)fg_opa * 255) / res_opa_saved;
|
||||
res_color_saved = lv_pixel_mix(fg_color, bg_color, ratio);
|
||||
|
||||
}
|
||||
|
||||
res_color->full = res_color_saved.full;
|
||||
*res_opa = res_opa_saved;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void rgb565_to_argb(uint16_t src_pixel, uint32_t* dst_color)
|
||||
{
|
||||
unsigned int a, r, g, b;
|
||||
|
||||
a = 0xff;
|
||||
r = ((src_pixel & 0xf800) >> 8);
|
||||
g = (src_pixel & 0x07e0) >> 3;
|
||||
b = (src_pixel & 0x1f) << 3;
|
||||
|
||||
*dst_color = (a << 24) | ((r | (r >> 5)) << 16) |
|
||||
((g | (g >> 6)) << 8) | (b | (b >> 5));
|
||||
|
||||
}
|
||||
|
||||
static void set_pixel_true_color_alpha(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w,
|
||||
lv_coord_t x, lv_coord_t y,
|
||||
lv_color_t color, lv_opa_t opa)
|
||||
{
|
||||
(void) disp_drv; /*Unused*/
|
||||
|
||||
uint8_t *buf_px = buf + (buf_w * y * 4 + x * 4);
|
||||
lv_color32_t bg_color;
|
||||
lv_color32_t fg_color;
|
||||
lv_color32_t res_color;
|
||||
lv_opa_t bg_opa = buf_px[3];
|
||||
|
||||
#if LV_COLOR_DEPTH == 16
|
||||
rgb565_to_argb((uint16_t)color.full, &fg_color.full);
|
||||
#else
|
||||
fg_color.full = color.full;
|
||||
#endif
|
||||
|
||||
bg_color = *((lv_color32_t *)buf_px);
|
||||
lv_pixel_mix_with_alpha(bg_color, bg_opa, fg_color, opa, &res_color, &buf_px[3]);
|
||||
if(buf_px[3] <= LV_OPA_MIN) return;
|
||||
buf_px[0] = res_color.ch.blue;
|
||||
buf_px[1] = res_color.ch.green;
|
||||
buf_px[2] = res_color.ch.red;
|
||||
}
|
||||
|
||||
static void lv_disp_drv_set_px_cb(lv_disp_drv_t * disp_drv, lv_img_cf_t cf)
|
||||
{
|
||||
switch(cf) {
|
||||
case LV_IMG_CF_TRUE_COLOR_ALPHA:
|
||||
disp_drv->set_px_cb = set_pixel_true_color_alpha;
|
||||
break;
|
||||
default:
|
||||
LV_LOG_ERROR("unknown cf:%d", cf);
|
||||
disp_drv->set_px_cb = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void init_fake_disp(lv_obj_t *canvas, lv_disp_t *disp, lv_disp_drv_t *drv, lv_area_t *clip_area)
|
||||
{
|
||||
lv_aic_canvas_t *aic_canvas = (lv_aic_canvas_t *)canvas;
|
||||
lv_img_dsc_t * dsc = &aic_canvas->dsc;
|
||||
lv_img_cf_t cf = LV_IMG_CF_TRUE_COLOR_ALPHA;
|
||||
|
||||
clip_area->x1 = 0;
|
||||
clip_area->x2 = dsc->header.w - 1;
|
||||
clip_area->y1 = 0;
|
||||
clip_area->y2 = dsc->header.h - 1;
|
||||
|
||||
lv_memset_00(disp, sizeof(lv_disp_t));
|
||||
disp->driver = drv;
|
||||
|
||||
lv_disp_drv_init(disp->driver);
|
||||
disp->driver->hor_res = dsc->header.w;
|
||||
disp->driver->ver_res = dsc->header.h;
|
||||
|
||||
lv_draw_ctx_t * draw_ctx = lv_mem_alloc(sizeof(lv_draw_sw_ctx_t));
|
||||
LV_ASSERT_MALLOC(draw_ctx);
|
||||
if(draw_ctx == NULL) return;
|
||||
lv_draw_sw_init_ctx(drv, draw_ctx);
|
||||
disp->driver->draw_ctx = draw_ctx;
|
||||
draw_ctx->clip_area = clip_area;
|
||||
draw_ctx->buf_area = clip_area;
|
||||
|
||||
if (aic_canvas->img_buf) {
|
||||
if (dsc->header.cf == LV_IMG_CF_RESERVED_16)
|
||||
draw_ctx->buf = (void *)((unsigned long)(aic_canvas->img_buf->buf.phy_addr[0]));
|
||||
else
|
||||
draw_ctx->buf = (void *)dsc->data;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
cf = aic_canvas->img.cf;
|
||||
lv_disp_drv_set_px_cb(disp->driver, cf);
|
||||
}
|
||||
|
||||
static void deinit_fake_disp(lv_obj_t *canvas, lv_disp_t *disp)
|
||||
{
|
||||
LV_UNUSED(canvas);
|
||||
lv_draw_sw_deinit_ctx(disp->driver, disp->driver->draw_ctx);
|
||||
lv_mem_free(disp->driver->draw_ctx);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2024, ArtInChip Technology Co., Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Authors: Ning Fang <ning.fang@artinchip.com>
|
||||
*/
|
||||
|
||||
#ifndef LV_AIC_CANVAS_H
|
||||
#define LV_AIC_CANVAS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "lv_obj.h"
|
||||
#include "lv_img.h"
|
||||
#include "lv_draw_img.h"
|
||||
#include "canvas_image.h"
|
||||
|
||||
extern const lv_obj_class_t lv_aic_canvas_class;
|
||||
|
||||
typedef struct {
|
||||
lv_img_t img;
|
||||
lv_img_dsc_t dsc;
|
||||
struct lv_mpp_buf *img_buf;
|
||||
} lv_aic_canvas_t;
|
||||
|
||||
lv_obj_t *lv_aic_canvas_create(lv_obj_t *parent);
|
||||
|
||||
lv_res_t lv_aic_canvas_alloc_buffer(lv_obj_t *obj, lv_coord_t w, lv_coord_t h, lv_img_cf_t cf);
|
||||
|
||||
void lv_aic_canvas_draw_text(lv_obj_t *obj, lv_coord_t x, lv_coord_t y, lv_coord_t max_w,
|
||||
lv_draw_label_dsc_t * draw_dsc, const char *txt);
|
||||
|
||||
void lv_aic_canvas_draw_text_to_center(lv_obj_t *obj, lv_draw_label_dsc_t *label_dsc, const char *txt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_AIC_CANVAS_H*/
|
||||
@@ -0,0 +1,17 @@
|
||||
from building import *
|
||||
import os
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
group = []
|
||||
src = Glob('*.c')
|
||||
CPPPATH = [cwd]
|
||||
|
||||
list = os.listdir(cwd)
|
||||
for d in list:
|
||||
path = os.path.join(cwd, d)
|
||||
if os.path.isfile(os.path.join(path, 'SConscript')):
|
||||
group = group + SConscript(os.path.join(d, 'SConscript'))
|
||||
|
||||
group = group + DefineGroup('LVGL-port', src, depend = ['LPKG_USING_LVGL'], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
@@ -0,0 +1,502 @@
|
||||
#include "aic_lv_ffmpeg.h"
|
||||
|
||||
#if LV_USE_FFMPEG == 0 && defined(AIC_MPP_PLAYER_INTERFACE)
|
||||
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MY_CLASS &lv_aic_player_class
|
||||
|
||||
struct ffmpeg_context_s {
|
||||
struct aic_player *aic_player;
|
||||
struct av_media_info media_info;
|
||||
int play_end;
|
||||
int play_async;
|
||||
int play_detected;
|
||||
};
|
||||
|
||||
#define FRAME_DEF_REFR_PERIOD 33 /*[ms]*/
|
||||
|
||||
static void lv_ffmpeg_player_get_disp_area(lv_obj_t *obj, lv_point_t *pos,
|
||||
lv_coord_t *width, lv_coord_t *height, lv_coord_t *rotation);
|
||||
static void lv_ffmpeg_player_set_disp_area(lv_obj_t *obj, lv_point_t pos,
|
||||
lv_coord_t width, lv_coord_t height, lv_coord_t rotation);
|
||||
static void lv_ffmpeg_player_protect_disp_area(lv_obj_t *obj, lv_point_t *pos,
|
||||
lv_coord_t *width, lv_coord_t *height, lv_coord_t *rotation);
|
||||
|
||||
static void lv_ffmpeg_player_frame_update_cb(lv_timer_t * timer);
|
||||
|
||||
static void lv_ffmpeg_player_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
|
||||
static void lv_ffmpeg_player_destructor(const lv_obj_class_t * class_p, lv_obj_t * obj);
|
||||
|
||||
static int aic_event_handle(void *app_data, int event, int data1, int data2)
|
||||
{
|
||||
int ret = 0;
|
||||
struct ffmpeg_context_s *ffmpeg_ctx = (struct ffmpeg_context_s *)app_data;
|
||||
|
||||
switch(event) {
|
||||
case AIC_PLAYER_EVENT_PLAY_END:
|
||||
ffmpeg_ctx->play_end = 1;
|
||||
break;
|
||||
case AIC_PLAYER_EVENT_PLAY_TIME:
|
||||
break;
|
||||
case AIC_PLAYER_EVENT_DEMUXER_FORMAT_DETECTED:
|
||||
ffmpeg_ctx->play_detected = 1;
|
||||
break;
|
||||
case AIC_PLAYER_EVENT_DEMUXER_FORMAT_NOT_DETECTED:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
const lv_obj_class_t lv_aic_player_class = {
|
||||
.constructor_cb = lv_ffmpeg_player_constructor,
|
||||
.destructor_cb = lv_ffmpeg_player_destructor,
|
||||
.instance_size = sizeof(lv_ffmpeg_player_t),
|
||||
.base_class = &lv_img_class
|
||||
};
|
||||
|
||||
void lv_ffmpeg_init(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int lv_ffmpeg_get_frame_num(const char * path)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
lv_obj_t * lv_ffmpeg_player_create(lv_obj_t * parent)
|
||||
{
|
||||
lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, parent);
|
||||
lv_obj_class_init_obj(obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
lv_res_t lv_ffmpeg_player_set_src(lv_obj_t * obj, const char *path)
|
||||
{
|
||||
lv_res_t res = LV_RES_INV;
|
||||
char fake_image_name[128] = {0};
|
||||
struct ffmpeg_context_s *ffmpeg_ctx;
|
||||
|
||||
lv_ffmpeg_player_t *player = (lv_ffmpeg_player_t *)obj;
|
||||
lv_point_t pos;
|
||||
lv_coord_t width, height, rotation;
|
||||
|
||||
if (!player->ffmpeg_ctx) {
|
||||
player->ffmpeg_ctx = calloc(1, sizeof(struct ffmpeg_context_s));
|
||||
if(player->ffmpeg_ctx == NULL) {
|
||||
LV_LOG_ERROR("ffmpeg_ctx malloc failed");
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
ffmpeg_ctx = player->ffmpeg_ctx;
|
||||
if (!ffmpeg_ctx->aic_player) {
|
||||
ffmpeg_ctx->aic_player = aic_player_create((char *)path);
|
||||
if (!ffmpeg_ctx->aic_player) {
|
||||
LV_LOG_ERROR("create aic player failed: %s", path);
|
||||
goto failed;
|
||||
}
|
||||
aic_player_set_event_callback(ffmpeg_ctx->aic_player, ffmpeg_ctx, aic_event_handle);
|
||||
} else {
|
||||
aic_player_stop(ffmpeg_ctx->aic_player);
|
||||
}
|
||||
|
||||
lv_timer_pause(player->timer);
|
||||
aic_player_set_uri(ffmpeg_ctx->aic_player, (char *)path);
|
||||
|
||||
ffmpeg_ctx->play_detected = 0;
|
||||
if (ffmpeg_ctx->play_async == 0) {
|
||||
res = aic_player_prepare_sync(ffmpeg_ctx->aic_player);
|
||||
} else {
|
||||
res = aic_player_prepare_async(ffmpeg_ctx->aic_player);
|
||||
}
|
||||
|
||||
if (res) {
|
||||
LV_LOG_ERROR("aic_player_prepare failed");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
res = aic_player_get_media_info(ffmpeg_ctx->aic_player,
|
||||
&ffmpeg_ctx->media_info);
|
||||
if (res != 0) {
|
||||
LV_LOG_ERROR("aic_player_get_media_info failed");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* update the obj before redraw */
|
||||
lv_obj_update_layout(obj);
|
||||
|
||||
player->imgdsc.header.w = ffmpeg_ctx->media_info.video_stream.width;
|
||||
player->imgdsc.header.h = ffmpeg_ctx->media_info.video_stream.height;
|
||||
ffmpeg_ctx->play_end = 0;
|
||||
|
||||
if (ffmpeg_ctx->media_info.has_audio == 1 && ffmpeg_ctx->media_info.has_video == 0) {
|
||||
lv_obj_add_flag(obj, LV_OBJ_FLAG_HIDDEN); /* audio did't not disp */
|
||||
lv_timer_resume(player->timer);
|
||||
return LV_RES_OK;
|
||||
}
|
||||
|
||||
lv_ffmpeg_player_get_disp_area(obj, &pos, &width, &height, &rotation);
|
||||
if (width == 0 && height == 0) {
|
||||
width = player->imgdsc.header.w;
|
||||
height = player->imgdsc.header.h;
|
||||
}
|
||||
|
||||
snprintf(fake_image_name, 128, "L:/%dx%d_%d_%08x.fake",
|
||||
width, height, 0, 0x00000000);
|
||||
lv_img_set_src(&player->img.obj, fake_image_name);
|
||||
|
||||
if (width == 0 && height == 0) {
|
||||
width = player->imgdsc.header.w;
|
||||
height = player->imgdsc.header.h;
|
||||
}
|
||||
|
||||
lv_ffmpeg_player_protect_disp_area(obj, &pos, &width, &height, &rotation);
|
||||
|
||||
if (ffmpeg_ctx->play_async == 0)
|
||||
lv_ffmpeg_player_set_disp_area(obj , pos, width, height, rotation);
|
||||
lv_timer_resume(player->timer);
|
||||
return LV_RES_OK;
|
||||
|
||||
failed:
|
||||
return LV_RES_INV;
|
||||
}
|
||||
|
||||
void lv_ffmpeg_player_set_cmd(lv_obj_t * obj, lv_ffmpeg_player_cmd_t cmd)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_ffmpeg_player_t * player = (lv_ffmpeg_player_t *)obj;
|
||||
struct ffmpeg_context_s *ffmpeg_ctx;
|
||||
int ret;
|
||||
|
||||
if(!player->ffmpeg_ctx) {
|
||||
LV_LOG_ERROR("ffmpeg_ctx is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
ffmpeg_ctx = player->ffmpeg_ctx;
|
||||
if (!ffmpeg_ctx->aic_player) {
|
||||
LV_LOG_ERROR("aic_player is NULL ");
|
||||
return;
|
||||
}
|
||||
|
||||
switch(cmd) {
|
||||
case LV_FFMPEG_PLAYER_CMD_START:
|
||||
ret = aic_player_start(ffmpeg_ctx->aic_player);
|
||||
if (ret != 0) {
|
||||
LV_LOG_ERROR("aic_player_start failed");
|
||||
break;
|
||||
}
|
||||
LV_LOG_INFO("aic player start");
|
||||
break;
|
||||
case LV_FFMPEG_PLAYER_CMD_STOP:
|
||||
ret = aic_player_stop(ffmpeg_ctx->aic_player);
|
||||
if (ret != 0) {
|
||||
LV_LOG_ERROR("aic_player_stop failed");
|
||||
break;
|
||||
}
|
||||
LV_LOG_INFO("aic player stop");
|
||||
break;
|
||||
case LV_FFMPEG_PLAYER_CMD_PAUSE:
|
||||
ret = aic_player_pause(ffmpeg_ctx->aic_player);
|
||||
if (ret != 0) {
|
||||
LV_LOG_ERROR("aic_player_pause failed");
|
||||
break;
|
||||
}
|
||||
LV_LOG_INFO("aic player pause");
|
||||
break;
|
||||
case LV_FFMPEG_PLAYER_CMD_RESUME:
|
||||
ret = aic_player_play(ffmpeg_ctx->aic_player);
|
||||
if (ret != 0) {
|
||||
LV_LOG_ERROR("aic_player_start failed");
|
||||
break;
|
||||
}
|
||||
LV_LOG_INFO("aic player resume");
|
||||
break;
|
||||
default:
|
||||
LV_LOG_ERROR("Error cmd: %d", cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_ffmpeg_player_set_cmd_ex(lv_obj_t * obj, lv_ffmpeg_player_cmd_t cmd, void *data)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_ffmpeg_player_t * player = (lv_ffmpeg_player_t *)obj;
|
||||
struct ffmpeg_context_s *ffmpeg_ctx;
|
||||
int ret;
|
||||
|
||||
bool *end = (bool *)data;
|
||||
struct av_media_info *media_info = (struct av_media_info *)data;
|
||||
s32 *set_vol = (s32 *)data;
|
||||
s32 *get_vol = (s32 *)data;
|
||||
u64 *seek = (u64 *)data;
|
||||
|
||||
if(!player->ffmpeg_ctx) {
|
||||
LV_LOG_ERROR("ffmpeg_ctx is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
ffmpeg_ctx = player->ffmpeg_ctx;
|
||||
if (!ffmpeg_ctx->aic_player) {
|
||||
LV_LOG_ERROR("aic_player is NULL ");
|
||||
return;
|
||||
}
|
||||
|
||||
switch(cmd) {
|
||||
case LV_FFMPEG_PLAYER_CMD_START:
|
||||
case LV_FFMPEG_PLAYER_CMD_STOP:
|
||||
case LV_FFMPEG_PLAYER_CMD_PAUSE:
|
||||
case LV_FFMPEG_PLAYER_CMD_RESUME:
|
||||
lv_ffmpeg_player_set_cmd(obj, cmd);
|
||||
break;
|
||||
case LV_FFMPEG_PLAYER_CMD_PLAY_END_EX:
|
||||
*end = ffmpeg_ctx->play_end == 1 ? true : false;
|
||||
break;
|
||||
case LV_FFMPEG_PLAYER_CMD_GET_MEDIA_INFO_EX:
|
||||
memcpy(media_info, &ffmpeg_ctx->media_info, sizeof(struct av_media_info));
|
||||
break;
|
||||
case LV_FFMPEG_PLAYER_CMD_SET_VOLUME_EX:
|
||||
ret = aic_player_set_volum(ffmpeg_ctx->aic_player, *set_vol);
|
||||
if (ret != 0) {
|
||||
LV_LOG_ERROR("aic_player_set_volum failed");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case LV_FFMPEG_PLAYER_CMD_GET_VOLUME_EX:
|
||||
ret = aic_player_get_volum(ffmpeg_ctx->aic_player, get_vol);
|
||||
if (ret != 0) {
|
||||
LV_LOG_ERROR("aic_player_get_volum failed");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case LV_FFMPEG_PLAYER_CMD_SET_PLAY_TIME_EX:
|
||||
ffmpeg_ctx->play_end = 0;
|
||||
ret = aic_player_seek(ffmpeg_ctx->aic_player, *seek);
|
||||
if (ret != 0) {
|
||||
LV_LOG_ERROR("aic_player_seek failed");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case LV_FFMPEG_PLAYER_CMD_GET_PLAY_TIME_EX:
|
||||
if (ffmpeg_ctx->play_end == 1) {
|
||||
*seek = ffmpeg_ctx->media_info.duration;
|
||||
return;
|
||||
}
|
||||
*seek = aic_player_get_play_time(ffmpeg_ctx->aic_player);
|
||||
if (*seek < 0) {
|
||||
LV_LOG_ERROR("aic_player_get_play_time failed");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#ifdef PLAYER_ASYNC
|
||||
/* async src is not currently supported */
|
||||
case LV_FFMPEG_PLAYER_CMD_SET_SRC_ASYNC:
|
||||
ffmpeg_ctx->play_async = 1;
|
||||
break;
|
||||
case LV_FFMPEG_PLAYER_WAIT_SRC_ASYNC:
|
||||
while(ffmpeg_ctx->play_detected == 0) {
|
||||
rt_thread_mdelay(5);
|
||||
}
|
||||
lv_timer_ready(player->timer);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
LV_LOG_ERROR("Error cmd: %d", cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_ffmpeg_player_set_auto_restart(lv_obj_t * obj, bool en)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
lv_ffmpeg_player_t * player = (lv_ffmpeg_player_t *)obj;
|
||||
player->auto_restart = en;
|
||||
}
|
||||
|
||||
static void lv_ffmpeg_player_frame_update_cb(lv_timer_t * timer)
|
||||
{
|
||||
lv_obj_t * obj = (lv_obj_t *)timer->user_data;
|
||||
lv_ffmpeg_player_t * player = (lv_ffmpeg_player_t *)obj;
|
||||
struct ffmpeg_context_s *ffmpeg_ctx;
|
||||
|
||||
static lv_point_t point, last_point;
|
||||
static lv_coord_t rotation, last_rotation;
|
||||
static lv_coord_t width, last_width;
|
||||
static lv_coord_t height, last_height;
|
||||
|
||||
ffmpeg_ctx = player->ffmpeg_ctx;
|
||||
if(!ffmpeg_ctx) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ffmpeg_ctx->aic_player) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ffmpeg_ctx->media_info.has_audio == 1 && ffmpeg_ctx->media_info.has_video == 0) {
|
||||
goto update_cb_out;
|
||||
}
|
||||
|
||||
lv_ffmpeg_player_get_disp_area(obj, &point, &width, &height, &rotation);
|
||||
if (rotation != 90 || rotation != 180 || rotation != 270) {
|
||||
LV_LOG_ERROR("aic_player only supported rotation angles, 90, 180, 270\n");
|
||||
LV_LOG_ERROR("obj default rotation angle is set to 0\n");
|
||||
lv_obj_set_style_transform_angle(obj, 0, LV_PART_MAIN);
|
||||
goto update_cb_out;
|
||||
}
|
||||
|
||||
/* avoid repeatedly setting in callback functions */
|
||||
if (last_point.x != point.x || last_point.y != point.y ||
|
||||
last_width != width || last_height != height ||
|
||||
last_rotation != rotation) {
|
||||
lv_ffmpeg_player_protect_disp_area(obj, &point, &width, &height, &rotation);
|
||||
lv_ffmpeg_player_set_disp_area(obj, point, width, height, rotation);
|
||||
last_point.x = point.x;
|
||||
last_point.y = point.y;
|
||||
last_height = height;
|
||||
last_width = width;
|
||||
last_rotation = rotation;
|
||||
}
|
||||
|
||||
update_cb_out:
|
||||
if (player->auto_restart && ffmpeg_ctx->play_end) {
|
||||
ffmpeg_ctx->play_end = 0;
|
||||
aic_player_seek(ffmpeg_ctx->aic_player, 0);
|
||||
LV_LOG_INFO("auto_restart");
|
||||
}
|
||||
}
|
||||
|
||||
static void lv_ffmpeg_player_get_disp_area(lv_obj_t *obj, lv_point_t *pos,
|
||||
lv_coord_t *width, lv_coord_t *height, lv_coord_t *rotation)
|
||||
{
|
||||
lv_area_t coords;
|
||||
|
||||
lv_obj_get_coords(obj, &coords);
|
||||
|
||||
*width = lv_obj_get_style_width(obj, 0);
|
||||
*height = lv_obj_get_style_height(obj, 0);
|
||||
|
||||
pos->x = coords.x1;
|
||||
pos->y = coords.y1;
|
||||
|
||||
*rotation = lv_obj_get_style_transform_angle(obj, LV_PART_MAIN);
|
||||
}
|
||||
|
||||
static void lv_ffmpeg_player_set_disp_area(lv_obj_t *obj, lv_point_t pos,
|
||||
lv_coord_t width, lv_coord_t height, lv_coord_t rotation)
|
||||
{
|
||||
lv_ffmpeg_player_t *player = (lv_ffmpeg_player_t *)obj;
|
||||
struct ffmpeg_context_s *ffmpeg_ctx = player->ffmpeg_ctx;
|
||||
lv_obj_t *mask_img = &player->img.obj;
|
||||
struct mpp_rect disp_rect = {0};
|
||||
u32 mpp_rotation = MPP_ROTATION_0;
|
||||
|
||||
int ret = -1;
|
||||
char fake_image_name[128] = {0};
|
||||
snprintf(fake_image_name, 128, "L:/%dx%d_%d_%08x.fake",
|
||||
width, height, 0, 0x00000000);
|
||||
|
||||
/* use fake image to change the transparency of the relevant ui layer to 0,
|
||||
* so that the video player can not be affected.
|
||||
*/
|
||||
lv_img_set_src(mask_img, fake_image_name);
|
||||
|
||||
disp_rect.x = pos.x;
|
||||
disp_rect.y = pos.y;
|
||||
disp_rect.width = width;
|
||||
disp_rect.height = height;
|
||||
ret = aic_player_set_disp_rect(ffmpeg_ctx->aic_player, &disp_rect);
|
||||
if (ret != 0) {
|
||||
LV_LOG_ERROR("aic_player_set_disp_rect failed");
|
||||
}
|
||||
|
||||
if (rotation == 90)
|
||||
mpp_rotation = MPP_ROTATION_90;
|
||||
if (rotation == 180)
|
||||
mpp_rotation = MPP_ROTATION_180;
|
||||
if (rotation == 270)
|
||||
mpp_rotation = MPP_ROTATION_270;
|
||||
|
||||
ret = aic_player_set_rotation(ffmpeg_ctx->aic_player, mpp_rotation);
|
||||
if (ret != 0) {
|
||||
LV_LOG_ERROR("aic_player_set_rotation failed");
|
||||
}
|
||||
}
|
||||
|
||||
static void lv_ffmpeg_player_protect_disp_area(lv_obj_t *obj, lv_point_t *pos,
|
||||
lv_coord_t *width, lv_coord_t *height, lv_coord_t *rotation)
|
||||
{
|
||||
if (pos->x > LV_HOR_RES) {
|
||||
pos->x = LV_HOR_RES;
|
||||
LV_LOG_ERROR("lv obj pos x too large!");
|
||||
}
|
||||
|
||||
if (pos->y > LV_VER_RES) {
|
||||
pos->y = LV_VER_RES;
|
||||
LV_LOG_ERROR("lv obj pos y too large!");
|
||||
}
|
||||
|
||||
if (pos->x + *width > LV_HOR_RES) {
|
||||
*width = (LV_HOR_RES - pos->x);
|
||||
LV_LOG_ERROR("lv obj width too large!");
|
||||
}
|
||||
|
||||
if (pos->y + *height > LV_VER_RES) {
|
||||
*height = (LV_HOR_RES - pos->y);
|
||||
LV_LOG_ERROR("lv obj height too large!");
|
||||
}
|
||||
}
|
||||
|
||||
static void lv_ffmpeg_player_constructor(const lv_obj_class_t * class_p,
|
||||
lv_obj_t * obj)
|
||||
{
|
||||
LV_TRACE_OBJ_CREATE("begin");
|
||||
|
||||
lv_ffmpeg_player_t * player = (lv_ffmpeg_player_t *)obj;
|
||||
|
||||
player->auto_restart = false;
|
||||
player->ffmpeg_ctx = NULL;
|
||||
player->timer = lv_timer_create(lv_ffmpeg_player_frame_update_cb,
|
||||
FRAME_DEF_REFR_PERIOD, obj);
|
||||
lv_timer_pause(player->timer);
|
||||
|
||||
LV_TRACE_OBJ_CREATE("finished");
|
||||
}
|
||||
|
||||
static void lv_ffmpeg_player_destructor(const lv_obj_class_t * class_p,
|
||||
lv_obj_t * obj)
|
||||
{
|
||||
LV_TRACE_OBJ_CREATE("begin");
|
||||
|
||||
lv_ffmpeg_player_t * player = (lv_ffmpeg_player_t *)obj;
|
||||
|
||||
if(player->timer) {
|
||||
lv_timer_del(player->timer);
|
||||
player->timer = NULL;
|
||||
}
|
||||
|
||||
if(player->ffmpeg_ctx) {
|
||||
struct ffmpeg_context_s *ffmpeg_ctx;
|
||||
ffmpeg_ctx = player->ffmpeg_ctx;
|
||||
if (ffmpeg_ctx->aic_player) {
|
||||
aic_player_stop(ffmpeg_ctx->aic_player);
|
||||
aic_player_destroy(ffmpeg_ctx->aic_player);
|
||||
ffmpeg_ctx->aic_player = NULL;
|
||||
}
|
||||
free(player->ffmpeg_ctx);
|
||||
player->ffmpeg_ctx = NULL;
|
||||
}
|
||||
|
||||
LV_TRACE_OBJ_CREATE("finished");
|
||||
}
|
||||
|
||||
#endif /*NO LV_USE_FFMPEG*/
|
||||
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* lv__ffmpeg is compatible with the following formats on the luban and luban-lite platforms:
|
||||
*
|
||||
* Container Format: Supports MP4 container, mjpeg(D13x), H264(D21x) raw stream, and MP3 container.
|
||||
*
|
||||
* Transport Protocol: Supports local files.
|
||||
*
|
||||
* Video Decoding: Supports mjpeg(D13x), H264(D21x).
|
||||
|
||||
* Audio Decoding: Supports MP3 and AAC.
|
||||
|
||||
* This is because ffmpeg is implemented to interface with aic_player, so it only supports formats that are supported by aic_player.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* @file aic_lv_ffmpeg.h
|
||||
*
|
||||
*/
|
||||
#ifndef LV_AIC_FFMPEG_H
|
||||
#define LV_AIC_FFMPEG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lvgl.h"
|
||||
#if LV_USE_FFMPEG == 0 && defined(AIC_MPP_PLAYER_INTERFACE)
|
||||
#include "aic_player.h"
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
struct ffmpeg_context_s;
|
||||
|
||||
extern const lv_obj_class_t lv_ffmpeg_player_class;
|
||||
|
||||
typedef struct {
|
||||
lv_img_t img;
|
||||
lv_timer_t * timer;
|
||||
lv_img_dsc_t imgdsc;
|
||||
bool auto_restart;
|
||||
struct ffmpeg_context_s * ffmpeg_ctx;
|
||||
} lv_ffmpeg_player_t;
|
||||
|
||||
typedef enum {
|
||||
LV_FFMPEG_PLAYER_CMD_START,
|
||||
LV_FFMPEG_PLAYER_CMD_STOP,
|
||||
LV_FFMPEG_PLAYER_CMD_PAUSE,
|
||||
LV_FFMPEG_PLAYER_CMD_RESUME,
|
||||
/* the following extension commands are only supported by aic */
|
||||
LV_FFMPEG_PLAYER_CMD_PLAY_END_EX, /* data type is bool * */
|
||||
LV_FFMPEG_PLAYER_CMD_GET_MEDIA_INFO_EX, /* data type is struct av_media_info * */
|
||||
LV_FFMPEG_PLAYER_CMD_SET_VOLUME_EX, /* data type is s32 *, rang: 0 ~ 100 */
|
||||
LV_FFMPEG_PLAYER_CMD_GET_VOLUME_EX, /* data type is s32 *, rang: 0 ~ 100 */
|
||||
LV_FFMPEG_PLAYER_CMD_SET_PLAY_TIME_EX, /* data type is u64 *, unite: microsecond */
|
||||
LV_FFMPEG_PLAYER_CMD_GET_PLAY_TIME_EX, /* data type is u64 *, unite: microsecond */
|
||||
_LV_FFMPEG_PLAYER_CMD_LAST
|
||||
} lv_ffmpeg_player_cmd_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Register FFMPEG image decoder
|
||||
*/
|
||||
void lv_ffmpeg_init(void);
|
||||
|
||||
/**
|
||||
* Get the number of frames contained in the file
|
||||
* @param path image or video file name
|
||||
* @return Number of frames, less than 0 means failed
|
||||
*/
|
||||
int lv_ffmpeg_get_frame_num(const char * path);
|
||||
|
||||
/**
|
||||
* Create ffmpeg_player object
|
||||
* @param parent pointer to an object, it will be the parent of the new player
|
||||
* @return pointer to the created ffmpeg_player
|
||||
*/
|
||||
lv_obj_t * lv_ffmpeg_player_create(lv_obj_t * parent);
|
||||
|
||||
/**
|
||||
* Set the path of the file to be played
|
||||
* @param obj pointer to a ffmpeg_player object
|
||||
* @param path video file path
|
||||
* @return LV_RES_OK: no error; LV_RES_INV: can't get the info.
|
||||
*/
|
||||
lv_res_t lv_ffmpeg_player_set_src(lv_obj_t * obj, const char * path);
|
||||
|
||||
/**
|
||||
* Set command control video player
|
||||
* @param obj pointer to a ffmpeg_player object
|
||||
* @param cmd control commands
|
||||
*/
|
||||
void lv_ffmpeg_player_set_cmd(lv_obj_t * obj, lv_ffmpeg_player_cmd_t cmd);
|
||||
|
||||
/**
|
||||
* Set the video to automatically replay
|
||||
* @param obj pointer to a ffmpeg_player object
|
||||
* @param en true: enable the auto restart
|
||||
*/
|
||||
void lv_ffmpeg_player_set_auto_restart(lv_obj_t * obj, bool en);
|
||||
|
||||
/*=====================
|
||||
* Expansion functions
|
||||
*====================*/
|
||||
/**
|
||||
* Set command control video player, expansion commands can be used
|
||||
* @param obj pointer to a ffmpeg_player object
|
||||
* @param cmd control commands
|
||||
* @param data set or read data
|
||||
*/
|
||||
void lv_ffmpeg_player_set_cmd_ex(lv_obj_t * obj, lv_ffmpeg_player_cmd_t cmd, void *data);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_FFMPEG*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*LV_AIC_FFMPEG_H*/
|
||||
Reference in New Issue
Block a user