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
This commit is contained in:
Jörg Hohensohn 2003-12-15 07:44:43 +00:00
parent 50f63e334a
commit bd8f448fd0
5 changed files with 221 additions and 1 deletions

View File

@ -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)

View File

@ -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) */

198
apps/plugins/video.c Normal file
View File

@ -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

View File

@ -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,

View File

@ -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);