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;
}