#include "FreeRTOS.h" #include "task.h" #include "semphr.h" #include "board.h" #include "chip.h" #include "sfud.h" #include "updatefile.h" #include "mfcapi.h" #include "dwl.h" #include "animation.h" #if DEVICE_TYPE_SELECT == EMMC_FLASH #include "mmcsd_core.h" #endif static TaskHandle_t animation_task = NULL; static SemaphoreHandle_t animation_mutex; #if ANIMATION_POLICY == ANIMATION_USE_SMALL_MEM static BANIHEADER ani_header; static BANIHEADER *aniheader = &ani_header; #else static BANIHEADER *aniheader; #endif static unsigned int anioffset; static unsigned int anisize; static int ani_playing = 0; static int ani_replay = 0; static int ani_stop = 0; static int ani_frames = 0; static int ani_display_index = 0; static int ani_take_vdisbuf = 0; static unsigned int ani_frame_addr; static uint32_t first_show_done = 0; #if 0 #include "ff_stdio.h" static int get_h264_single_file_from_sd(void *buf, int *len) { #define READ_SIZE (LCD_WIDTH*LCD_HEIGHT*2) char path_name[64] = "/sd/000.h264"; static int count = 0; FF_FILE *fp; int ret = -1; sprintf(path_name, "/sd/%.3d.h264", count++); *len = 0; fp = ff_fopen(path_name, "rb"); if (fp) { ret = ff_fread(buf, 1, READ_SIZE, fp); if (ret <= 0) { printf("read sdmmc file:%s failed, maybe read done\n", path_name); return -1; } *len = ret; } else { printf("### open %s fail.\n", path_name); count = 0; return -1; } if(fp) ff_fclose(fp); //printf("###read %s len:%d.\n", path_name, *len); return 0; } static void h264_decode_test_thread(void *param) { #define H264DEC_SEMIPLANAR_YUV420 0x020001 #define H264DEC_INBUF_SIZE (LCD_WIDTH*LCD_HEIGHT*2) #define H264DEC_DISP_COUNTS 2 DWLLinearMem_t inBuf; OutFrameBuffer outBuf = {0}; uint32_t h264SrcSize = 0; MFCHandle *handle = NULL; uint32_t display_addr[H264DEC_DISP_COUNTS] = {0}; uint32_t display_addr_index = 0; uint32_t first_show_done = 0; int ret; int i; void *h264SrcBuf = pvPortMalloc(H264DEC_INBUF_SIZE); if(!h264SrcBuf) { printf("%s, h264SrcBuf pvPortMalloc failed.\n", __func__); return ; } for(i=0; i= H264DEC_DISP_COUNTS) { display_addr_index = 0; } if(!first_show_done) { ark_lcd_set_osd_size(LCD_VIDEO_LAYER, /*outBuf.codedWidth, outBuf.codedHeight*/LCD_WIDTH, LCD_HEIGHT); ark_lcd_set_osd_format(LCD_VIDEO_LAYER, LCD_OSD_FORAMT_YUV420); ark_lcd_set_osd_yuv420_mode(LCD_VIDEO_LAYER, LCD_OSD_Y_UV420); ark_lcd_osd_enable(LCD_VIDEO_LAYER, 1); ark_lcd_osd_enable(LCD_UI_LAYER, 0); first_show_done = 1; } ark_lcd_set_osd_yaddr(LCD_VIDEO_LAYER, yaddr); ark_lcd_set_osd_uaddr(LCD_VIDEO_LAYER, uaddr); ark_lcd_set_osd_vaddr(LCD_VIDEO_LAYER, vaddr); ark_lcd_set_osd_sync(LCD_VIDEO_LAYER); ark_lcd_set_osd_sync(LCD_UI_LAYER); ark_lcd_wait_for_vsync(); } else { continue; } } } } if(handle) mfc_uninit(handle); if(h264SrcBuf) vPortFree(h264SrcBuf); for(i=0; i 0) { void *anibuf = pvPortMalloc(anisize); if (anibuf) { #if DEVICE_TYPE_SELECT != EMMC_FLASH sflash = sfud_get_device(0); sfud_read(sflash, anioffset, anisize, anibuf); #else emmc_read(anioffset, anisize, anibuf); #endif aniheader = (BANIHEADER*)anibuf; if (aniheader->magic != MKTAG('B', 'A', 'N', 'I') #ifdef PLAY_SHUTDOWN_ANIMATION && aniheader->magic != MKTAG('S', 'A', 'N', 'I') #endif ) { printf("Read animation file error!\n"); vPortFree(anibuf); vTaskDelete(NULL); return; } CP15_clean_dcache_for_dma((uint32_t)anibuf, (uint32_t)anibuf + anisize); } else { printf("Error! No enough memory for animation file.\n"); vTaskDelete(NULL); return; } } else { printf("Warning! Not found animation in update file.\n"); vTaskDelete(NULL); return; } ani_frame_addr = (uint32_t)aniheader + sizeof(BANIHEADER); for (;;) { ulTaskNotifyTake(pdTRUE, portMAX_DELAY); xSemaphoreTake(animation_mutex, portMAX_DELAY); if (ani_replay) { ani_frame_addr = (uint32_t)aniheader + sizeof(BANIHEADER); ani_frames = 0; ani_replay = 0; } stick = xTaskGetTickCount(); ani_playing = 1; size = *(uint32_t*)ani_frame_addr; if (xVideoDisplayBufTake(pdMS_TO_TICKS(10)) == pdTRUE) { if(!mfc_handle) mfc_handle = mfc_init(RAW_STRM_TYPE_JPEG); if(!mfc_handle) { printf("%s, mfc_init failed.\n", __func__); continue ; } display_addr = ulVideoDisplayBufGet(); JpegHeaderInfo jpegInfo = {0}; jpegInfo.handle = mfc_handle; jpegInfo.jpg_addr = ani_frame_addr + 8; jpegInfo.jpg_size = size; jpegInfo.dec_addry = display_addr; #if LCD_ROTATE_ANGLE != LCD_ROTATE_ANGLE_0 if(!tmp_addr) { uint32_t tmp_size = ulVideoDisplayBufGetSize(); tmp_addr = (u32 *)pvPortMalloc(tmp_size); if(!tmp_addr) { printf("tmp_addr pvPortMalloc failed.\n"); } } if(tmp_addr) { jpegInfo.dec_addry = VIRT_TO_PHY((u32)tmp_addr); } #endif if (mfc_jpegdec(&jpegInfo) != 0) { printf("animation decode %d frame fail.\n", ani_frames); vVideoDisplayBufFree(display_addr); } else { if(!first_show_done) { #if LCD_ROTATE_ANGLE == LCD_ROTATE_ANGLE_0 int align_width = (LCD_WIDTH + 0xF) & (~0xF); int align_height = (LCD_HEIGHT + 0xF) & (~0xF); if((align_width == jpegInfo.dec_width) && (align_height == jpegInfo.dec_height)) { ark_lcd_set_osd_size(LCD_VIDEO_LAYER, LCD_WIDTH, LCD_HEIGHT); } else { ark_lcd_set_osd_size(LCD_VIDEO_LAYER, jpegInfo.dec_width, jpegInfo.dec_height); } ark_lcd_set_osd_format(LCD_VIDEO_LAYER, LCD_OSD_FORAMT_YUV420); ark_lcd_set_osd_yuv420_mode(LCD_VIDEO_LAYER, LCD_OSD_Y_UV420); #else ark_lcd_set_osd_size(LCD_VIDEO_LAYER, LCD_WIDTH, LCD_HEIGHT); ark_lcd_set_osd_format(LCD_VIDEO_LAYER, LCD_OSD_FORAMT_RGB565); #endif ark_lcd_osd_enable(LCD_VIDEO_LAYER, 1); ark_lcd_osd_enable(LCD_UI_LAYER, 0); first_show_done = 1; } animo_flag++; if(animo_flag == 3){ BrightnessPowerOnSetting(); pwm_enable(2); pwm_enable(3); } // printf("animo_flag------------ %d .\r\n",animo_flag); #if LCD_ROTATE_ANGLE == LCD_ROTATE_ANGLE_0 ark_lcd_set_osd_yaddr(LCD_VIDEO_LAYER, jpegInfo.dec_addry); ark_lcd_set_osd_uaddr(LCD_VIDEO_LAYER, jpegInfo.dec_addru); ark_lcd_set_osd_vaddr(LCD_VIDEO_LAYER, jpegInfo.dec_addrv); #else pxp_scaler_rotate(jpegInfo.dec_addry, jpegInfo.dec_addru, jpegInfo.dec_addrv, PXP_SRC_FMT_YUV2P420, jpegInfo.dec_width, jpegInfo.dec_height, display_addr, 0, PXP_OUT_FMT_RGB565, LCD_WIDTH, LCD_HEIGHT, LCD_ROTATE_ANGLE); ark_lcd_set_osd_yaddr(LCD_VIDEO_LAYER, display_addr); #endif ark_lcd_set_osd_sync(LCD_VIDEO_LAYER); ark_lcd_set_osd_sync(LCD_UI_LAYER); ark_lcd_wait_for_vsync(); vVideoDisplayBufRender(display_addr); ani_take_vdisbuf = 1; } } ani_frame_addr += size; ani_display_index = !ani_display_index; if (ani_stop || (++ani_frames >= aniheader->aniCount + aniheader->hasBootlogo ? 1 : 0) #if ANIMATION_POLICY == ANIMATION_USE_SMALL_MEM || (ani_frame_addr > anioffset + anisize)) #else || (ani_frame_addr > (uint32_t)aniheader + anisize)) #endif { printf("animation end.\n"); extern void Set_sys_power_on_self_test(uint8_t value); Set_sys_power_on_self_test(50); ani_stop = 0; if (aniheader->aniCount > 0) vTaskDelay(aniheader->aniDelayHideTime); else if (aniheader->hasBootlogo) vTaskDelay(aniheader->bootlogoDisplayTime); #ifdef PLAY_SHUTDOWN_ANIMATION if(shutdown_anim) ani_take_vdisbuf = 0; #endif if (ani_take_vdisbuf) { ark_lcd_osd_enable(LCD_VIDEO_LAYER, 0); ark_lcd_osd_enable(LCD_UI_LAYER, 1); ark_lcd_set_osd_sync(LCD_UI_LAYER); ark_lcd_set_osd_sync(LCD_VIDEO_LAYER); } vVideoDisplayBufFree(display_addr); vVideoDisplayBufGive(); ani_playing = 0; if (ani_replay) xTaskNotifyGive(animation_task); xSemaphoreGive(animation_mutex); if(mfc_handle) { mfc_uninit(mfc_handle); mfc_handle = NULL; } if(tmp_addr) { vPortFree(tmp_addr); tmp_addr = NULL; } #ifdef PLAY_SHUTDOWN_ANIMATION break; #endif continue; } vVideoDisplayBufGive(); xSemaphoreGive(animation_mutex); etick = xTaskGetTickCount(); if (aniheader->hasBootlogo && ani_frames == 1) delaytick = pdMS_TO_TICKS(aniheader->bootlogoDisplayTime) > (etick - stick) ? pdMS_TO_TICKS(aniheader->bootlogoDisplayTime) - (etick - stick) : 0; else delaytick = pdMS_TO_TICKS(1000 / aniheader->aniFps) > (etick - stick) ? pdMS_TO_TICKS(1000 / aniheader->aniFps) - (etick - stick) : 0; if (delaytick) vTaskDelay(delaytick); xTaskNotifyGive(animation_task); } #ifdef PLAY_SHUTDOWN_ANIMATION if(aniheader) { vPortFree(aniheader); aniheader = NULL; } animation_task = NULL; vTaskDelete(NULL); #endif } int animation_init(void) { if (animation_task) { printf("animation is already inited.\n"); return 0; } animation_mutex = xSemaphoreCreateMutex(); /* Create a task to play animation */ //if (xTaskCreate(h264_decode_test_thread, "h264_decode_test", configMINIMAL_STACK_SIZE*2, NULL, if (xTaskCreate(animation_thread, "animation", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &animation_task) != pdPASS) { printf("create animation task fail.\n"); animation_task = NULL; return -1; } return 0; } void animation_start(void) { xSemaphoreTake(animation_mutex, portMAX_DELAY); first_show_done=0; if (ani_playing) { printf("animation is already playing.\n"); xSemaphoreGive(animation_mutex); return; } #if ANIMATION_POLICY == ANIMATION_USE_SMALL_MEM ani_frame_addr = anioffset + sizeof(BANIHEADER); #else ani_frame_addr = (uint32_t)aniheader + sizeof(BANIHEADER); #endif ani_frames = 0; if (animation_task) xTaskNotifyGive(animation_task); xSemaphoreGive(animation_mutex); } /* replay animation even if animation is already playing */ void animation_restart(void) { xSemaphoreTake(animation_mutex, portMAX_DELAY); first_show_done=0; ani_stop=0; if (ani_playing) { ani_replay = 1; xSemaphoreGive(animation_mutex); return; } #if ANIMATION_POLICY == ANIMATION_USE_SMALL_MEM ani_frame_addr = anioffset + sizeof(BANIHEADER); #else ani_frame_addr = (uint32_t)aniheader + sizeof(BANIHEADER); #endif ani_frames = 0; if (animation_task) xTaskNotifyGive(animation_task); xSemaphoreGive(animation_mutex); } #ifdef PLAY_SHUTDOWN_ANIMATION int play_shutdown_animation(void) { #define TIMEOUT_SEC 10 uint32_t wait_tick; if (animation_task) { printf("%s, animation is already inited.\n", __func__); return -1; } xSemaphoreTake(animation_mutex, portMAX_DELAY); shutdown_anim = 1; ani_frames = 0; first_show_done = 0; ani_stop = 0; ani_take_vdisbuf = 0; xSemaphoreGive(animation_mutex); if (xTaskCreate(animation_thread, "animation", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, &animation_task) != pdPASS) { printf("%s, create animation task fail.\n", __func__); animation_task = NULL; return -1; } xSemaphoreTake(animation_mutex, portMAX_DELAY); if (ani_playing) { printf("%s, animation is already playing.\n", __func__); xSemaphoreGive(animation_mutex); return -1; } if (animation_task) xTaskNotifyGive(animation_task); xSemaphoreGive(animation_mutex); //wait for animation_thread exit. wait_tick = xTaskGetTickCount(); while(xTaskGetTickCount() - wait_tick < configTICK_RATE_HZ * TIMEOUT_SEC) { if(ani_stop) break; vTaskDelay(pdMS_TO_TICKS(100)); } return 0; } #endif void animation_stop(void) { xSemaphoreTake(animation_mutex, portMAX_DELAY); ani_stop = 1; xSemaphoreGive(animation_mutex); } int get_animation_status(void) { return ani_playing; }