| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- #include "FreeRTOS.h"
- #include "task.h"
- #include "semphr.h"
- #include "board.h"
- #include "chip.h"
- #include "sfud.h"
- #include "ota_update.h"
- #include "mfcapi.h"
- #include "jpegdecapi.h"
- #include "animation.h"
- 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;
- static void animation_thread(void *param)
- {
- MFCHandle *mfc_handle = NULL;
- #if DEVICE_TYPE_SELECT != EMMC_FLASH
- sfud_flash *sflash;
- #endif
- uint32_t size;
- uint32_t stick, etick, delaytick;
- uint32_t display_addr;
- uint32_t *tmp_addr = NULL;
- anioffset = get_upfile_offset(UPFILE_TYPE_ANIMATION, 0);
- anisize = get_upfile_size(UPFILE_TYPE_ANIMATION);
- if (anisize > 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')) {
- 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;
- jpegInfo.dec_size = ulVideoDisplayBufGetSize();
- #if LCD_ROTATE_ANGLE != LCD_ROTATE_ANGLE_0
- if(!tmp_addr) {
- tmp_addr = (u32 *)pvPortMalloc(jpegInfo.dec_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 {
- int pxp_format = PXP_S0_FORMAT_YUV2P420;
- int lcd_format = LCD_OSD_FORAMT_Y_UV420;
- /* avoid warnning */
- (void) pxp_format;
- (void) lcd_format;
- /* YUV format only support y_uv420/y_u_v420/y_uv422/y_u_v422 */
- if (jpegInfo.dec_format == JPEGDEC_YCbCr420_SEMIPLANAR) {
- pxp_format = PXP_S0_FORMAT_YUV2P420;
- lcd_format = LCD_OSD_FORAMT_Y_UV420;
- } else if (jpegInfo.dec_format == JPEGDEC_YCbCr422_SEMIPLANAR) {
- pxp_format = PXP_S0_FORMAT_YUV2P422;
- lcd_format = LCD_OSD_FORAMT_Y_UV422;
- } else {
- printf("%s Invalid jpegdec format.\n", __func__);
- goto next_frame;
- }
- 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_format);
- #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;
- }
- #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_format, jpegInfo.dec_width, jpegInfo.dec_height,
- display_addr, 0, PXP_OUT_FORMAT_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;
- }
- }
- next_frame:
- 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");
- ani_stop = 0;
- if (aniheader->aniCount > 0)
- vTaskDelay(aniheader->aniDelayHideTime);
- else if (aniheader->hasBootlogo)
- vTaskDelay(aniheader->bootlogoDisplayTime);
- // 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;
- }
- 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);
- }
- }
- 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(animation_thread, "animation", configMINIMAL_STACK_SIZE, NULL,
- configMAX_PRIORITIES - 2, &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);
- }
- void animation_stop(void)
- {
- xSemaphoreTake(animation_mutex, portMAX_DELAY);
- ani_stop = 1;
- xSemaphoreGive(animation_mutex);
- }
- int get_animation_status(void)
- {
- return ani_playing;
- }
|