From bd8f448fd0cb10336c7dbc9a01e0ada0380c1c61 Mon Sep 17 00:00:00 2001 From: Jörg Hohensohn Date: Mon, 15 Dec 2003 07:44:43 +0000 Subject: the video player plugin and file the type / plugin API for it git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4145 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugin.c | 8 +++ apps/plugin.h | 9 ++- apps/plugins/video.c | 198 +++++++++++++++++++++++++++++++++++++++++++++++++++ apps/tree.c | 6 ++ apps/tree.h | 1 + 5 files changed, 221 insertions(+), 1 deletion(-) create mode 100644 apps/plugins/video.c (limited to 'apps') diff --git a/apps/plugin.c b/apps/plugin.c index 7a88a894d8..d71102701a 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -155,6 +155,14 @@ static struct plugin_api rockbox_api = { atoi, get_time, plugin_get_buffer, + + /* new stuff at the end, sort into place next time the API gets incompatible */ + +#ifndef HAVE_LCD_CHARCELLS + &lcd_framebuffer[0][0], + lcd_blit, +#endif + yield, }; int plugin_load(char* plugin, void* parameter) diff --git a/apps/plugin.h b/apps/plugin.h index e7ec86aa53..819d75dc24 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -43,7 +43,7 @@ #include "mpeg.h" /* increase this every time the api struct changes */ -#define PLUGIN_API_VERSION 7 +#define PLUGIN_API_VERSION 8 /* update this to latest version if a change to the api struct breaks backwards compatibility */ @@ -181,6 +181,13 @@ struct plugin_api { int (*atoi)(const char *str); struct tm* (*get_time)(void); void* (*plugin_get_buffer)(int* buffer_size); + /* new stuff */ +#ifndef HAVE_LCD_CHARCELLS + unsigned char* lcd_framebuffer; + /* performance function */ + void (*lcd_blit) (unsigned char* p_data, int x, int y, int width, int height, int stride); +#endif + void (*yield)(void); }; /* defined by the plugin loader (plugin.c) */ diff --git a/apps/plugins/video.c b/apps/plugins/video.c new file mode 100644 index 0000000000..396d5159ec --- /dev/null +++ b/apps/plugins/video.c @@ -0,0 +1,198 @@ +/*************************************************************************** +* __________ __ ___. +* Open \______ \ ____ ____ | | _\_ |__ _______ ___ +* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +* \/ \/ \/ \/ \/ +* $Id$ +* +* Experimental plugin for halftoning +* Reads raw image data from a file +* +* Copyright (C) 2003 Jörg Hohensohn [IDC]Dragon +* +* All files in this archive are subject to the GNU General Public License. +* See the file COPYING in the source tree root for full license agreement. +* +* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +* KIND, either express or implied. +* +****************************************************************************/ +#ifdef HAVE_LCD_BITMAP + +#include "plugin.h" +#include "system.h" + +#define DEFAULT_FILENAME "/default.rvf" +#define SCREENSIZE (LCD_WIDTH*LCD_HEIGHT/8) /* in bytes */ +#define FILEBUFSIZE SCREENSIZE*4 /* must result in a multiple of 512 */ + +static struct plugin_api* rb; /* here is a global api struct pointer */ + +int WaitForButton(void) +{ + int button; + + do + { + button = rb->button_get(true); + } while ((button & BUTTON_REL) && button != SYS_USB_CONNECTED); + + return button; +} + + +/* play from memory, loop until OFF is pressed */ +int show_buffer(unsigned char* p_start, int frames) +{ + unsigned char* p_current = p_start; + unsigned char* p_end = p_start + SCREENSIZE * frames; + int shown = 0; + int button; + + do + { + rb->lcd_blit(p_current, 0, 0, LCD_WIDTH, LCD_HEIGHT/8, LCD_WIDTH); + p_current += SCREENSIZE; + if (p_current >= p_end) + p_current = p_start; /* wrap */ + + rb->yield(); /* yield to the other treads */ + shown++; + + button = rb->button_get(false); + } while(button != BUTTON_OFF && button != SYS_USB_CONNECTED); + + return (button != SYS_USB_CONNECTED) ? shown : SYS_USB_CONNECTED; +} + + +/* play from file, exit if OFF is pressed */ +int show_file(unsigned char* p_buffer, int fd) +{ + int got_now; /* how many gotten for this frame */ + int shown = 0; + int button = BUTTON_NONE; + /* tricky buffer handling to read only whole sectors, then no copying needed */ + unsigned char* p_file = p_buffer; /* file read */ + unsigned char* p_screen = p_buffer; /* display */ + unsigned char* p_end = p_buffer + FILEBUFSIZE; /* for wraparound test */ + int needed; /* read how much data to complete a frame */ + int read_now; /* size to read for this frame, 512 or 1024 */ + + do + { + needed = SCREENSIZE - (p_file - p_screen); /* minus what we have */ + read_now = (needed + (SECTOR_SIZE-1)) & ~(SECTOR_SIZE-1); /* round up to whole sectors */ + + got_now = rb->read(fd, p_file, read_now); /* read the sector(s) */ + rb->lcd_blit(p_screen, 0, 0, LCD_WIDTH, LCD_HEIGHT/8, LCD_WIDTH); + + p_screen += SCREENSIZE; + if (p_screen >= p_end) + p_screen = p_buffer; /* wrap */ + + p_file += got_now; + if (p_file >= p_end) + p_file = p_buffer; /* wrap */ + + if (read_now < SCREENSIZE) /* below average? time to do something else */ + { + rb->yield(); /* yield to the other treads */ + button = rb->button_get(false); + } + + shown++; + + } while (got_now >= needed + && button != BUTTON_OFF + && button != SYS_USB_CONNECTED); + + return (button != SYS_USB_CONNECTED) ? shown : SYS_USB_CONNECTED; +} + + +int main(char* filename) +{ + char buf[32]; + int buffer_size, file_size; + unsigned char* p_buffer; + int fd; /* file descriptor handle */ + int got_now; /* how many bytes read from file */ + int frames, shown; + long time; + int button; + + p_buffer = rb->plugin_get_buffer(&buffer_size); + if (buffer_size < FILEBUFSIZE) + return PLUGIN_ERROR; /* not enough memory */ + + /* compose filename if none given */ + if (filename == NULL) + { + filename = DEFAULT_FILENAME; + } + + fd = rb->open(filename, O_RDONLY); + if (fd < 0) + return PLUGIN_ERROR; + + file_size = rb->filesize(fd); + if (file_size <= buffer_size) + { /* we can read the whole file in advance */ + got_now = rb->read(fd, p_buffer, file_size); + rb->close(fd); + frames = got_now / (LCD_WIDTH*LCD_HEIGHT/8); + time = *rb->current_tick; + shown = show_buffer(p_buffer, frames); + time = *rb->current_tick - time; + } + else + { /* we need to stream */ + time = *rb->current_tick; + shown = show_file(p_buffer, fd); + time = *rb->current_tick - time; + rb->close(fd); + } + + rb->close(fd); + and_b(~0x40, &PBDRL); /* hack workaround to get the LED off */ + + if (shown == SYS_USB_CONNECTED) /* exception */ + return PLUGIN_USB_CONNECTED; + + rb->lcd_clear_display(); + rb->snprintf(buf, sizeof(buf), "%d frames", shown); + rb->lcd_puts(0, 0, buf); + rb->snprintf(buf, sizeof(buf), "%d.%02d seconds", time/HZ, time%HZ); + rb->lcd_puts(0, 1, buf); + rb->snprintf(buf, sizeof(buf), "%d fps", (shown * HZ + time/2) / time); + rb->lcd_puts(0, 2, buf); + rb->snprintf(buf, sizeof(buf), "file: %d bytes", file_size); + rb->lcd_puts(0, 6, buf); + rb->snprintf(buf, sizeof(buf), "buffer: %d bytes", buffer_size); + rb->lcd_puts(0, 7, buf); + rb->lcd_update(); + button = WaitForButton(); + return (button == SYS_USB_CONNECTED) ? PLUGIN_USB_CONNECTED : PLUGIN_OK; + +} + + +/***************** Plugin Entry Point *****************/ + +enum plugin_status plugin_start(struct plugin_api* api, void* parameter) +{ + /* this macro should be called as the first thing you do in the plugin. + it test that the api version and model the plugin was compiled for + matches the machine it is running on */ + TEST_PLUGIN_API(api); + + rb = api; /* copy to global api pointer */ + + /* now go ahead and have fun! */ + return main((char*) parameter); +} + +#endif // #ifdef HAVE_LCD_BITMAP \ No newline at end of file diff --git a/apps/tree.c b/apps/tree.c index 62b9ce289f..392328bd1d 100644 --- a/apps/tree.c +++ b/apps/tree.c @@ -82,6 +82,7 @@ static struct #ifdef HAVE_LCD_BITMAP { ".fnt", TREE_ATTR_FONT,Font }, { ".ch8", TREE_ATTR_CH8, -1 }, + { ".rvf", TREE_ATTR_RVF, Text }, #endif #ifndef SIMULATOR #ifdef HAVE_LCD_BITMAP @@ -1068,6 +1069,11 @@ static bool dirbrowse(char *root, int *dirfilter) plugin_load("/.rockbox/rocks/chip8.rock",buf); break; + /* "movie" animation */ + case TREE_ATTR_RVF: + plugin_load("/.rockbox/rocks/video.rock",buf); + break; + case TREE_ATTR_FONT: font_load(buf); set_file(buf, global_settings.font_file, diff --git a/apps/tree.h b/apps/tree.h index fdc9641917..87cd469148 100644 --- a/apps/tree.h +++ b/apps/tree.h @@ -38,6 +38,7 @@ struct entry { #define TREE_ATTR_ROCK 0x0900 /* binary rockbox plugin */ #define TREE_ATTR_UCL 0x0A00 /* rockbox flash image */ #define TREE_ATTR_CH8 0x0B00 /* chip-8 game */ +#define TREE_ATTR_RVF 0x0C00 /* rockbox video file */ #define TREE_ATTR_MASK 0xFFC0 /* which bits tree.c uses (above) */ void tree_init(void); -- cgit v1.2.3