This program plays QuickTime movies on GR-Peach
Dependencies: AsciiFont GR-PEACH_video GraphicsFramework LCD_shield_config R_BSP TLV320_RBSP mbed-rtos mbed
Requirements
- GR-Peach
- GR-Peach Audio Camera Shield or I²S compatible audio DAC
- GR-Peach LCD Shield
- USB memory stick
How to play movie files
- Encode movie files
encode movies with ffmpeg
$ ffmpeg -i <input -ar 44100 -acodec pcm_s16le -s 480x270 -vcodec mjpeg -q:v 3 -movflags faststart -threads 4 -vf fps=30 <output>.mov
- Copy movies to the root directory of USB memory
- Build and upload this program
- Run it
main.cpp
- Committer:
- mtkrtk
- Date:
- 2017-03-12
- Revision:
- 1:3e638b9e91cd
- Parent:
- 0:d0f130e27d32
File content as of revision 1:3e638b9e91cd:
#include "mbed.h" #include "USBHostMSD.h" #include "usb_host_setting.h" #include "LCD.hpp" #include "MovFile.hpp" #include "TLV320_RBSP.h" #include "MovPlayer.hpp" #include "AsciiFont.h" #include "BinaryImage_RZ_A1H.h" #include "CppStandardHelper.hpp" #define USE_TLV320 static constexpr int FRAME_BUFFER_BYTE_PER_PIXEL = 2; static constexpr int FRAME_BUFFER_STRIDE = ((LCD_PIXEL_WIDTH * FRAME_BUFFER_BYTE_PER_PIXEL) + 31u) & ~31u; static uint8_t MBED_ALIGN(32) user_frame_buffer[FRAME_BUFFER_STRIDE * LCD_PIXEL_HEIGHT]; static constexpr int FileNameBufferNum = 16; static constexpr int FileNameBufferLength = 32; static char filenameBuffer[FileNameBufferNum][FileNameBufferLength]; static rtos::Semaphore touchSemaphore(0); #ifdef ONLINE_COMPILER namespace TouchAction { #endif ENUM TouchAction { None, Play0, Play1, Play2, ScrollUp, ScrollDown }; #ifdef ONLINE_COMPILER } #endif namespace Menu { const graphics_image_t *top = menu; const graphics_image_t *one = menu1; const graphics_image_t *two = menu2; const graphics_image_t *three = menu3; const graphics_image_t *down = menud; const graphics_image_t *up = menuu; const graphics_image_t *upx = menuux; const graphics_image_t *downx = menudx; } static void dcache_clean(void * p_buf, uint32_t size) { uint32_t start_addr = (uint32_t)p_buf & 0xFFFFFFE0; uint32_t end_addr = (uint32_t)p_buf + size; uint32_t addr; /* Data cache clean */ for (addr = start_addr; addr < end_addr; addr += 0x20) { __v7_clean_dcache_mva((void *)addr); } } static void touchCallback() { touchSemaphore.release(); } #ifdef ONLINE_COMPILER static TouchAction::TouchAction readTouch(LCD *lcd, TouckKey_LCD_shield *touch, const graphics_image_t *currentImage) #else static TouchAction readTouch(LCD *lcd, TouckKey_LCD_shield *touch, const graphics_image_t *currentImage) #endif { TouchKey::touch_pos_t touchPos; printf("waiting for touch\n"); touchSemaphore.wait(); printf("touch detected\n"); touch->GetCoordinates(1, &touchPos); #ifdef ONLINE_COMPILER TouchAction::TouchAction ret = TouchAction::None; #else TouchAction ret = TouchAction::None; #endif const graphics_image_t *image = nullptr; int touchNum = 1; if (40 <= touchPos.x && touchPos.x <= 360) { if (35 <= touchPos.y && touchPos.y <= 70) { ret = TouchAction::Play0; image = Menu::one; } else if (115 <= touchPos.y && touchPos.y <= 155) { ret = TouchAction::Play1; image = Menu::two; } else if (195 <= touchPos.y && touchPos.y <= 235) { ret = TouchAction::Play2; image = Menu::three; } } else if (409 <= touchPos.x && touchPos.x <= 460) { if (22 <= touchPos.y && touchPos.y <= 68) { ret = TouchAction::ScrollUp; image = Menu::up; } else if (202 <= touchPos.y && touchPos.y <= 248) { ret = TouchAction::ScrollDown; image = Menu::down; } } if (lcd && image) { lcd->drawImage(image); } while (touchNum) { touchSemaphore.wait(); touchNum = touch->GetCoordinates(1, &touchPos); } if (lcd) { lcd->drawImage(currentImage); } return ret; } int main(int MBED_UNUSED argc, const char MBED_UNUSED * argv[]) { DigitalOut usb1en(P3_8); USBHostMSD msd("usb"); usb1en = 1; rtos::Thread::wait(5); usb1en = 0; DigitalOut led(LED1); while (! msd.connect()) { printf("not connected\n"); rtos::Thread::wait(500); led = ! led; } led = 0; LCD *lcd = LCD::singleton(); lcd->start(); #ifdef USE_TLV320 TLV320_RBSP audio(P10_13, I2C_SDA, I2C_SCL, P4_4, P4_5, P4_7, P4_6, 0x80, MovPlayer::BufferLength - 1, 0); audio.power(0x02); audio.format(16); audio.frequency(44100); MovPlayer::AudioCallback callback(&audio, &TLV320_RBSP::write); #else R_BSP_Ssif audio(P2_4, P2_5, P2_7, P2_6, 0x80, MovPlayer::BufferLength - 1, 0); ssif_channel_cfg_t ssif_cfg; ssif_cfg.enabled = true; ssif_cfg.int_level = 0x78; ssif_cfg.slave_mode = false; ssif_cfg.sample_freq = 44100u; ssif_cfg.clk_select = SSIF_CFG_CKS_AUDIO_X1; ssif_cfg.multi_ch = SSIF_CFG_MULTI_CH_1; ssif_cfg.data_word = SSIF_CFG_DATA_WORD_16; ssif_cfg.system_word = SSIF_CFG_SYSTEM_WORD_16; ssif_cfg.bclk_pol = SSIF_CFG_FALLING; ssif_cfg.ws_pol = SSIF_CFG_WS_HIGH; ssif_cfg.padding_pol = SSIF_CFG_PADDING_LOW; ssif_cfg.serial_alignment = SSIF_CFG_DATA_FIRST; ssif_cfg.parallel_alignment = SSIF_CFG_LEFT; ssif_cfg.ws_delay = SSIF_CFG_NO_DELAY; ssif_cfg.noise_cancel = SSIF_CFG_ENABLE_NOISE_CANCEL; ssif_cfg.tdm_mode = SSIF_CFG_DISABLE_TDM; ssif_cfg.romdec_direct.mode = SSIF_CFG_DISABLE_ROMDEC_DIRECT; ssif_cfg.romdec_direct.p_cbfunc = NULL; audio.ConfigChannel(&ssif_cfg); MovPlayer::AudioCallback callback(&audio, &R_BSP_Ssif::write); #endif DisplayBase Display; memset(user_frame_buffer, 0, sizeof(user_frame_buffer)); dcache_clean(user_frame_buffer, sizeof(user_frame_buffer)); DisplayBase::rect_t rect; rect.vs = 0; rect.vw = LCD_PIXEL_HEIGHT; rect.hs = 0; rect.hw = LCD_PIXEL_WIDTH; Display.Graphics_Read_Setting(DisplayBase::GRAPHICS_LAYER_1, (void *)user_frame_buffer, FRAME_BUFFER_STRIDE, DisplayBase::GRAPHICS_FORMAT_ARGB4444, DisplayBase::WR_RD_WRSWA_32_16BIT, &rect); Display.Graphics_Start(DisplayBase::GRAPHICS_LAYER_1); AsciiFont ascii(user_frame_buffer, LCD_PIXEL_WIDTH, LCD_PIXEL_HEIGHT, FRAME_BUFFER_STRIDE, FRAME_BUFFER_BYTE_PER_PIXEL); TouckKey_LCD_shield touch(P4_0, P2_13, I2C_SDA, I2C_SCL); touch.SetCallback(touchCallback); touch.Reset(); MovFile *mov = MovFile::sharedFile(); MovPlayer *player = MovPlayer::defaultPlayer(); memset(filenameBuffer, 0, FileNameBufferNum * FileNameBufferLength); DIR *directory = opendir("/usb/"); struct dirent *file = NULL; int numOfMovies = 0; while (numOfMovies < FileNameBufferNum && (file = readdir(directory))) { size_t length = strlen(file->d_name); if (file->d_name[0] == '.') { continue; } if (memcmp(&file->d_name[length - 4], ".mov", 4)) { continue; } strcpy(filenameBuffer[numOfMovies], "/usb/"); strcat(filenameBuffer[numOfMovies], file->d_name); ++numOfMovies; } closedir(directory); int fileIndex = 0; const graphics_image_t *currentImage = Menu::upx; lcd->drawImage(Menu::upx); constexpr uint32_t black = 0x000000f0; while (1) { ascii.DrawStr(&filenameBuffer[fileIndex][5], 0, 30, black, 2); ascii.DrawStr(&filenameBuffer[fileIndex + 1][5], 0, 110, black, 2); ascii.DrawStr(&filenameBuffer[fileIndex + 2][5], 0, 190, black, 2); dcache_clean(user_frame_buffer, sizeof(user_frame_buffer)); #ifdef ONLINE_COMPILER TouchAction::TouchAction action = readTouch(lcd, &touch, currentImage); #else TouchAction action = readTouch(lcd, &touch, currentImage); #endif char *path = nullptr; switch (action) { case TouchAction::Play0: path = filenameBuffer[fileIndex]; break; case TouchAction::Play1: path = filenameBuffer[fileIndex + 1]; break; case TouchAction::Play2: path = filenameBuffer[fileIndex + 2]; break; case TouchAction::ScrollUp: fileIndex -= 3; if (fileIndex <= 0) { fileIndex = 0; currentImage = Menu::upx; } else { currentImage = Menu::top; } lcd->drawImage(currentImage); ascii.Erase(); dcache_clean(user_frame_buffer, sizeof(user_frame_buffer)); break; case TouchAction::ScrollDown: fileIndex += 3; if (fileIndex + 3 >= numOfMovies) { fileIndex = numOfMovies - 3; if (fileIndex < 0) { fileIndex = 0; } currentImage = Menu::downx; } else { currentImage = Menu::top; } lcd->drawImage(currentImage); ascii.Erase(); dcache_clean(user_frame_buffer, sizeof(user_frame_buffer)); break; default: break; } if (path && *path) { ascii.Erase(); dcache_clean(user_frame_buffer, sizeof(user_frame_buffer)); FILE *file = fopen(path, "r"); printf("start playing %s\n", path); mov->start(file); player->play(mov, lcd, callback); fclose(file); printf("finished playing\n"); } else { continue; } touch.Reset(); while (touchSemaphore.wait(0) > 0) ; readTouch(nullptr, &touch, nullptr); lcd->drawImage(currentImage); } return 0; }