summaryrefslogtreecommitdiff
path: root/packages/mplayer/files
diff options
context:
space:
mode:
Diffstat (limited to 'packages/mplayer/files')
-rw-r--r--packages/mplayer/files/vo_pxa.c746
-rw-r--r--packages/mplayer/files/vo_pxa.h20
2 files changed, 649 insertions, 117 deletions
diff --git a/packages/mplayer/files/vo_pxa.c b/packages/mplayer/files/vo_pxa.c
index 2e9bb57b9c..1488d14064 100644
--- a/packages/mplayer/files/vo_pxa.c
+++ b/packages/mplayer/files/vo_pxa.c
@@ -7,6 +7,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
#include "config.h"
#include "video_out.h"
@@ -62,7 +63,8 @@ static int preinit(const char *vo_subdevice)
if( rc == -1 )
{
- mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: FBIOGET_VSCREENINFO line %d failed\n", __LINE__ );
+ mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: FBIOGET_VSCREENINFO preinit base_fd failed %d\n",
+ errno );
/* If this failed, close down the FD so we don't try to set this again */
close( priv->base_fd );
@@ -94,9 +96,9 @@ static int config(uint32_t src_width, uint32_t src_height,
{
pxa_priv_t *priv = &st_pxa_priv;
int rc;
+ int i;
- mp_msg(MSGT_VO, MSGL_V, "vo_pxa: config() was called\n");
- mp_msg(MSGT_VO, MSGL_V, "vo_pxa: src_width:%d, src_height:%d, dst_width:%d, dst_height:%d\n",
+ mp_msg(MSGT_VO, MSGL_V, "vo_pxa: config() src_width:%d, src_height:%d, dst_width:%d, dst_height:%d\n",
src_width, src_height, dst_width, dst_height);
/* Check format */
@@ -129,21 +131,23 @@ static int config(uint32_t src_width, uint32_t src_height,
if( rc == -1 )
{
- mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: Set of base fb failed\n");
+ mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: config() Set FBIOPUT_VSCREENINFO on base_fd failed %d\n",
+ errno );
priv->vm = 0;
goto err_out;
}
+
+ /* We need this sleep, to make the change in resolution actually happen, before we open the overlay */
+ sleep(1);
}
- /* We need these sleeps, to make the change in resolution actually happen, before we open the overlay */
- sleep(2);
/* Open up the overlay fbdev */
priv->fd = open( "/dev/fb2", O_RDWR );
if( priv->fd < 0 )
{
- mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: Could not open framebuffer device\n");
+ mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: Could not open /dev/fb2: %d\n", errno );
goto err_out;
}
@@ -152,13 +156,40 @@ static int config(uint32_t src_width, uint32_t src_height,
if( rc == -1 )
{
- mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: FBIOGET_VSCREENINFO line %d failed\n", __LINE__ );
+ mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: config() FBIOGET_VSCREENINFO from fd failed %d\n",
+ errno );
goto err_out;
}
+ /* Store away the source dimensions, so we can place in centre of screen later in vm mode */
+ priv->src_width = src_width;
+ priv->src_height = src_height;
+
/* Set up the buffer */
- priv->my_fb_var.xres = src_width;
- priv->my_fb_var.yres = src_height;
+ if( priv->vm )
+ {
+ /* Ignore size, as the rest of the screen is toast. Use max size */
+ priv->my_fb_var.xres = 240;
+ priv->my_fb_var.yres = 320;
+
+ /* Do we need to rotate? */
+ if( priv->src_width > priv->src_height )
+ {
+ /* Yes */
+ priv->rotate = 1;
+ }
+
+ priv->width = 240;
+ priv->height = 320;
+ }
+ else
+ {
+ priv->my_fb_var.xres = src_width;
+ priv->my_fb_var.yres = src_height;
+ priv->width = src_width;
+ priv->height = src_height;
+ }
+
priv->my_fb_var.nonstd = ( 4 << 20) /* Format YV12 */
| ( 0 << 0) /* x position */
| ( 0 << 10); /* y position */
@@ -171,7 +202,8 @@ static int config(uint32_t src_width, uint32_t src_height,
if( rc == -1 )
{
- mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: FBIOPUT_VSCREENINFO line %d failed\n", __LINE__ );
+ mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: config() FBIOPUT_VSCREENINFO to fd failed: %d\n",
+ errno );
goto err_out;
}
@@ -180,7 +212,8 @@ static int config(uint32_t src_width, uint32_t src_height,
if( rc == -1 )
{
- mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: FBIOGET_FSCREENINFO line %d failed\n", __LINE__ );
+ mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: config() FBIOGET_FSCREENINFO from fd failed: %d\n",
+ errno );
goto err_out;
}
@@ -191,7 +224,7 @@ static int config(uint32_t src_width, uint32_t src_height,
if( priv->fb_mem_base == MAP_FAILED )
{
- mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: mmap buffer failed\n" );
+ mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: mmap fd buffer failed: %d\n", errno );
goto err_out;
}
@@ -200,12 +233,79 @@ static int config(uint32_t src_width, uint32_t src_height,
if( rc == -1 )
{
- mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: FBIOGET_VSCREENINFO line %d failed\n", __LINE__ );
+ mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: config() FBIOGET_VSCREENINFO from fd (2) failed %d\n",
+ errno );
goto err_out;
}
+ /* Fill the overlay with black */
+ memset( priv->fb_mem_base + priv->my_fb_var.red.offset, 16, priv->my_fb_var.red.length );
+ memset( priv->fb_mem_base + priv->my_fb_var.green.offset, 128, priv->my_fb_var.green.length );
+ memset( priv->fb_mem_base + priv->my_fb_var.blue.offset, 128, priv->my_fb_var.blue.length );
+
+ /* Now open the OSD overlay - overlay 1, and fill with transparent */
+ sleep( 1 );
+
+ priv->overlay_fd = open( "/dev/fb1", O_RDWR );
+
+ if( priv->overlay_fd < 0 )
+ {
+ mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: Could not open /dev/fb1: %d\n", errno );
+ goto err_out;
+ }
+
+ /* Read in fb var data */
+ rc = ioctl( priv->overlay_fd, FBIOGET_VSCREENINFO, &(priv->osd_fb_var) );
+
+ if( rc == -1 )
+ {
+ mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: config() FBIOGET_VSCREENINFO from overlay_fd failed; %d\n",
+ errno );
+ goto err_out;
+ }
+
+ priv->osd_fb_var.xres = priv->width;
+ priv->osd_fb_var.yres = priv->height;
+ priv->osd_fb_var.nonstd = ( 0 << 0) /* x position */
+ | ( 0 << 10); /* y position */
+ /* Use 15 bit mode, with top bit transparency */
+ priv->osd_fb_var.bits_per_pixel = 16;
+
+ rc = ioctl( priv->overlay_fd, FBIOPUT_VSCREENINFO, &(priv->osd_fb_var) );
+
+ if( rc == -1 )
+ {
+ mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: config() FBIOPUT_VSCREENINFO to overlay_fd failed: %d\n",
+ errno );
+ goto err_out;
+ }
+
+ /* Next get the fixed fbvars, so we can mmap the data */
+ rc = ioctl( priv->overlay_fd, FBIOGET_FSCREENINFO, &(priv->osd_fb_fix) );
+
+ if( rc == -1 )
+ {
+ mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: config() FBIOGET_FSCREENINFO from overlay_fd failed %d\n",
+ errno );
+ goto err_out;
+ }
+
+ priv->osd_mem_base = mmap( NULL, priv->osd_fb_fix.smem_len, (PROT_READ | PROT_WRITE ),
+ MAP_SHARED,
+ priv->overlay_fd,
+ 0 );
+
+ if( priv->osd_mem_base == MAP_FAILED )
+ {
+ mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: mmap osd_mem_base failed: %d\n", errno );
+ goto err_out;
+ }
+
+ /* Fill the overlay with transparent */
+ vo_pxa_clear_osd( priv->osd_mem_base, priv->osd_fb_fix.smem_len );
+
/* We are good to go! */
- mp_msg( MSGT_VO, MSGL_V, "vo_pxa: FOpened screen %d x %d fourcc %s\n",
+ mp_msg( MSGT_VO, MSGL_V, "vo_pxa: Opened video overlay %d x %d fourcc %s\n",
priv->my_fb_var.xres,
priv->my_fb_var.yres,
vo_format_name(format) );
@@ -213,18 +313,8 @@ static int config(uint32_t src_width, uint32_t src_height,
return 0;
err_out:
-
- if( priv->fb_mem_base != MAP_FAILED )
- {
- munmap( priv->fb_mem_base, priv->my_fb_fix.smem_len );
- priv->fb_mem_base = MAP_FAILED;
- }
-
- if( priv->fd >= 0 )
- {
- close( priv->fd );
- priv->fd = -1;
- }
+
+ /* Don't do anything here for the moment */
return -1;
}
@@ -238,6 +328,8 @@ static int config(uint32_t src_width, uint32_t src_height,
****************************************************************************/
static int control(uint32_t request, void *data, ...)
{
+ mp_msg(MSGT_VO, MSGL_V, "vo_pxa: control %08x\n", request );
+
switch( request )
{
case VOCTRL_QUERY_FORMAT:
@@ -261,7 +353,7 @@ static int control(uint32_t request, void *data, ...)
int draw_frame(uint8_t *src[])
{
/* This is not implimented */
- mp_msg(MSGT_VO, MSGL_V, "vo_pxa: dummy draw_frame() was called\n");
+ mp_msg(MSGT_VO, MSGL_ERR, "vo_pxa: dummy draw_frame() was called\n");
return -1;
}
@@ -281,79 +373,291 @@ int draw_frame(uint8_t *src[])
int draw_slice(uint8_t *src[], int stride[], int w,int h, int x,int y)
{
pxa_priv_t *priv = &st_pxa_priv;
- uint8_t *my_src;
- uint8_t *dest;
- size_t length;
- int i;
/* This routine is only display routine actually implimented */
- mp_msg(MSGT_VO, MSGL_V, "vo_pxa: draw_slice() was called\n");
+ mp_msg(MSGT_VO, MSGL_V, "vo_pxa: draw_slice() w %d h %d x %d y %d stride %d %d %d\n",
+ w, h, x, y, stride[0], stride[1], stride[2] );
/* It would be faster to check if source and dest have same geometry and copy
* whole block
* For the moment we just copy a line at a time
*/
- /* Limit area written to */
- if( x >= priv->my_fb_fix.line_length )
+ /* In vm mode rotate if wider than long */
+ if( priv->vm )
{
- return 0;
- }
+ /* Do we nee to rotate? */
+ if( priv->rotate )
+ {
+ /* Yes, rotated version */
+ int dst_x_offset = 0;
+ int dst_y_offset = 0;
+ int src_x_offset = 0;
+ int src_y_offset = 0;
+
+ /* Figure out dst offset */
+ if( priv->src_width < 320 )
+ {
+ dst_x_offset = ( ( 320 - priv->src_width ) / 2 );
+ /* Make it a multiple of 16 */
+ dst_x_offset &= ~(0xf);
+ }
+
+ if( priv->src_height < 240 )
+ {
+ dst_y_offset = ( ( 240 - priv->src_height ) / 2 );
+ /* Make it a multiple of 16 */
+ dst_y_offset &= ~(0xf);
+ }
+
+ dst_x_offset += x;
+ dst_y_offset += y;
+
+ if( ( dst_x_offset >= 320 ) || ( dst_y_offset >= 240 ) )
+ {
+ /* Nothing to do - drawing off the screen! */
+ return( 0 );
+ }
+
+ /* Limit to drawable area */
+ if( ( w + dst_x_offset ) > 320 )
+ {
+ w = ( 320 - dst_x_offset );
+ }
+
+ if( ( h + dst_y_offset ) > 240 )
+ {
+ h = ( 240 - dst_y_offset );
+ }
+
+ /* And source offset */
+ if( priv->src_width > 320 )
+ {
+ src_x_offset = ( ( priv->src_width - 320 ) / 2 );
+ /* Make it a multiple of 16 */
+ src_x_offset &= ~(0xf);
+ }
+
+ if( priv->src_height > 240 )
+ {
+ src_y_offset = ( ( priv->src_height - 240 ) / 2 );
+ /* Make it a multiple of 16 */
+ src_y_offset &= ~(0xf);
+ }
+
+
+ /* Y first */
+ vo_pxa_copy_and_rotate( src[0] + src_x_offset + (src_y_offset * stride[0]), stride[0],
+ priv->fb_mem_base + priv->my_fb_var.red.offset + (240 * dst_x_offset) + (240 - dst_y_offset - h),
+ w, h, 240 );
+ /* Now U */
+ vo_pxa_copy_and_rotate( src[1] + src_x_offset/2 + (src_y_offset/2 * stride[1]), stride[1],
+ priv->fb_mem_base + priv->my_fb_var.green.offset + (120 * dst_x_offset/2) + (120 - dst_y_offset/2 - h/2),
+ w/2, h/2, 120 );
+ vo_pxa_copy_and_rotate( src[2] + src_x_offset/2 + (src_y_offset/2 * stride[2]), stride[2],
+ priv->fb_mem_base + priv->my_fb_var.blue.offset + (120 * dst_x_offset/2) + (120 - dst_y_offset/2 - h/2),
+ w/2, h/2, 120 );
+ }
+ else
+ {
+ /* Don't rotate */
+ int i;
+ uint8_t *my_src;
+ uint8_t *dest;
+ int dst_x_offset = 0;
+ int dst_y_offset = 0;
+ int src_x_offset = 0;
+ int src_y_offset = 0;
+
+ /* Figure out dst offset */
+ if( priv->src_width < 240 )
+ {
+ dst_x_offset = ( ( 240 - priv->src_width ) / 2 );
+ /* Make it a multiple of 16 */
+ dst_x_offset &= ~(0xf);
+ }
+
+ if( priv->src_height < 320 )
+ {
+ dst_y_offset = ( ( 320 - priv->src_height ) / 2 );
+ /* Make it a multiple of 16 */
+ dst_y_offset &= ~(0xf);
+ }
+
+ dst_x_offset += x;
+ dst_y_offset += y;
+
+ if( ( dst_x_offset >= 240 ) || ( dst_y_offset >= 320 ) )
+ {
+ /* Nothing to do - drawing off the screen! */
+ return( 0 );
+ }
+
+ /* Limit to drawable area */
+ if( ( w + dst_x_offset ) > 240 )
+ {
+ w = ( 240 - dst_x_offset );
+ }
+
+ if( ( h + dst_y_offset ) > 320 )
+ {
+ h = ( 320 - dst_y_offset );
+ }
+
+ /* And source offset */
+ if( priv->src_width > 240 )
+ {
+ src_x_offset = ( ( priv->src_width - 240 ) / 2 );
+ /* Make it a multiple of 16 */
+ src_x_offset &= ~(0xf);
+ }
+
+ if( priv->src_height > 320 )
+ {
+ src_y_offset = ( ( priv->src_height - 320 ) / 2 );
+ /* Make it a multiple of 16 */
+ src_y_offset &= ~(0xf);
+ }
+
+ /* First Y */
+ for( i = 0; i<h; i++ )
+ {
+ dest = priv->fb_mem_base +
+ priv->my_fb_var.red.offset +
+ ( (dst_y_offset+i) * priv->my_fb_fix.line_length ) +
+ dst_x_offset;
+ my_src = src[0] + src_x_offset + (stride[0] * (i+src_y_offset));
+ memcpy( dest, my_src, w );
+ }
+
+ /* Now U */
+ for( i = 0; i<(h/2); i++ )
+ {
+ dest = priv->fb_mem_base +
+ priv->my_fb_var.green.offset +
+ ( ((dst_y_offset/2)+i) * (priv->my_fb_fix.line_length/2) ) +
+ dst_x_offset/2;
+ my_src = src[1] + src_x_offset/2 + (stride[1] * (i+(src_y_offset/2)));
+ memcpy( dest, my_src, w/2 );
+ }
- if( w + x > priv->my_fb_fix.line_length )
- {
- w = priv->my_fb_fix.line_length - x;
+ /* Finaly V */
+ for( i = 0; i<(h/2); i++ )
+ {
+ dest = priv->fb_mem_base +
+ priv->my_fb_var.blue.offset +
+ ( ((dst_y_offset/2)+i) * (priv->my_fb_fix.line_length/2) ) +
+ dst_x_offset/2;
+ my_src = src[2] + src_x_offset/2 + (stride[2] * (i+(src_y_offset/2)));
+ memcpy( dest, my_src, w/2 );
+ }
+
+ }
}
-
- if( y>= priv->my_fb_var.yres )
+ else
{
- return 0;
- }
+ /* Not full screen mode */
+ uint8_t *my_src;
+ uint8_t *dest;
+ size_t length;
+ int i;
+
+ /* It would be faster to check if source and dest have same geometry and copy
+ * whole block
+ * For the moment we just copy a line at a time
+ */
+
+ /* Limit area written to */
+ if( x >= priv->my_fb_fix.line_length )
+ {
+ return 0;
+ }
- if( h + y > priv->my_fb_var.yres )
- {
- h = priv->my_fb_var.yres - y;
- }
+ if( w + x > priv->my_fb_fix.line_length )
+ {
+ w = priv->my_fb_fix.line_length - x;
+ }
- /* First Y */
- for( i = 0; i<h; i++ )
- {
- dest = priv->fb_mem_base +
- priv->my_fb_var.red.offset +
- ( (y+i) * priv->my_fb_fix.line_length ) +
- x;
- my_src = src[0] + stride[0] * i;
- memcpy( dest, my_src, w );
- }
+ if( y>= priv->my_fb_var.yres )
+ {
+ return 0;
+ }
+
+ if( h + y > priv->my_fb_var.yres )
+ {
+ h = priv->my_fb_var.yres - y;
+ }
+
+ /* First Y */
+ for( i = 0; i<h; i++ )
+ {
+ dest = priv->fb_mem_base +
+ priv->my_fb_var.red.offset +
+ ( (y+i) * priv->my_fb_fix.line_length ) +
+ x;
+ my_src = src[0] + stride[0] * i;
+ memcpy( dest, my_src, w );
+ }
- /* Now U */
- for( i = 0; i<(h/2); i++ )
- {
- dest = priv->fb_mem_base +
- priv->my_fb_var.green.offset +
- ( ((y/2)+i) * (priv->my_fb_fix.line_length/2) ) +
- x;
- my_src = src[1] + stride[1] * i;
- memcpy( dest, my_src, w/2 );
- }
+ /* Now U */
+ for( i = 0; i<(h/2); i++ )
+ {
+ dest = priv->fb_mem_base +
+ priv->my_fb_var.green.offset +
+ ( ((y/2)+i) * (priv->my_fb_fix.line_length/2) ) +
+ x;
+ my_src = src[1] + stride[1] * i;
+ memcpy( dest, my_src, w/2 );
+ }
- /* Finaly V */
- for( i = 0; i<(h/2); i++ )
- {
- dest = priv->fb_mem_base +
- priv->my_fb_var.blue.offset +
- ( ((y/2)+i) * (priv->my_fb_fix.line_length/2) ) +
- x;
- my_src = src[2] + stride[2] * i;
- memcpy( dest, my_src, w/2 );
+ /* Finaly V */
+ for( i = 0; i<(h/2); i++ )
+ {
+ dest = priv->fb_mem_base +
+ priv->my_fb_var.blue.offset +
+ ( ((y/2)+i) * (priv->my_fb_fix.line_length/2) ) +
+ x;
+ my_src = src[2] + stride[2] * i;
+ memcpy( dest, my_src, w/2 );
+ }
}
-
return 0;
}
static void draw_osd(void)
{
+ pxa_priv_t *priv = &st_pxa_priv;
+ int osd_has_changed;
+
+ /* This gets called every frame, so systems which do the OSD without a
+ * seperate overlay can mix in the image. We need to find out if the osd
+ * has actually been updated!
+ */
mp_msg(MSGT_VO, MSGL_V, "vo_pxa: draw_osd() was called\n");
+
+ osd_has_changed = vo_update_osd( priv->width, priv->height);
+
+ if(osd_has_changed)
+ {
+ int i;
+
+ mp_msg(MSGT_VO, MSGL_V, "vo_pxa: Clear and update OSD\n");
+
+ /* Fill with transparent */
+ vo_pxa_clear_osd( priv->osd_mem_base, priv->osd_fb_fix.smem_len );
+
+ priv->osd_cleared = 1;
+
+ /* now update */
+ if( priv->rotate )
+ {
+ vo_draw_text( priv->width, priv->height, vo_pxa_draw_alpha_with_rotate );
+ }
+ else
+ {
+ vo_draw_text( priv->width, priv->height, vo_pxa_draw_alpha );
+ }
+ }
}
/*****************************************************************************
@@ -377,6 +681,7 @@ static void flip_page(void)
****************************************************************************/
static void check_events(void)
{
+ mp_msg(MSGT_VO, MSGL_V, "vo_pxa: check_events() was called\n");
}
/*****************************************************************************
@@ -390,41 +695,74 @@ static void uninit(void)
pxa_priv_t *priv = &st_pxa_priv;
int rc;
- if( priv->fb_mem_base != MAP_FAILED )
- {
- munmap( priv->fb_mem_base, priv->my_fb_fix.smem_len );
- priv->fb_mem_base = MAP_FAILED;
- }
-
- if( priv->fd >= 0 )
- {
- close( priv->fd );
- priv->fd = -1;
- }
-
- /* We need these sleeps, to make the change in resolution actually happen */
- sleep(1);
-
+ mp_msg(MSGT_VO, MSGL_V, "vo_pxa: uninit() was called\n");
+
if( priv->vm )
{
+ /* We need these sleeps, to make the change in resolution actually happen */
+ sleep(1);
+
/* Restore original resolution */
if( priv->base_fd >= 0 )
{
- mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: Try to restore original video mode\n", __LINE__ );
-
rc = ioctl( priv->base_fd, FBIOPUT_VSCREENINFO, &(priv->base_orig_fb_var) );
if( rc == -1 )
{
- mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: FBIOPUT_VSCREENINFO line %d failed\n", __LINE__ );
+ mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: uninit() FBIOPUT_VSCREENINFO to base_fd failed %d\n",
+ errno );
}
}
-
+ /* We need these sleeps, to make the change in resolution actually happen */
+ /* For some reason, if we change the reolution the overlay buffer never gets deleted? */
+ sleep(1);
}
- /* We need these sleeps, to make the change in resolution actually happen */
- /* For some reason, if we change the reolution the overlay buffer never gets deleted? */
- sleep(1);
+
+ /* We need to force the overlays to be really disabled, otherwise they
+ * will come back as zombies after suspend, resume
+ * This trick seems to work, but will not be needed once kernel driver
+ * is fixed
+ */
+ if( priv->fd >= 0 )
+ {
+ rc = ioctl( priv->fd, FBIOGET_VSCREENINFO, &(priv->my_fb_var) );
+
+ if( rc == -1 )
+ {
+ mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: uninit() FBIOGET_VSCREENINFO from fd failed %d\n",
+ errno );
+ }
+ priv->my_fb_var.bits_per_pixel = 0;
+
+ rc = ioctl( priv->fd, FBIOPUT_VSCREENINFO, &(priv->my_fb_var) );
+
+ if( rc == -1 )
+ {
+ mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: uninit() FBIOPUT_VSCREENINFO from fd failed %d\n",
+ errno );
+ }
+ }
+
+ if( priv->overlay_fd >= 0 )
+ {
+ rc = ioctl( priv->overlay_fd, FBIOGET_VSCREENINFO, &(priv->my_fb_var) );
+
+ if( rc == -1 )
+ {
+ mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: uninit() FBIOGET_VSCREENINFO from overlay_fd failed %d\n",
+ errno );
+ }
+ priv->my_fb_var.bits_per_pixel = 0;
+
+ rc = ioctl( priv->overlay_fd, FBIOPUT_VSCREENINFO, &(priv->my_fb_var) );
+
+ if( rc == -1 )
+ {
+ mp_msg( MSGT_VO, MSGL_ERR, "vo_pxa: uninit() FBIOPUT_VSCREENINFO from overlay_fd failed %d\n",
+ errno );
+ }
+ }
if( priv->base_fd >= 0 )
{
@@ -444,25 +782,199 @@ static int vo_pxa_query_format( uint32_t format )
mp_msg(MSGT_VO, MSGL_V, "vo_pxa: vo_pxa_query_format was called: %x (%s)\n",
format, vo_format_name(format));
- if( IMGFMT_IS_RGB(format) )
+ switch (format)
+ {
+ /* Planar YUV Formats */
+ /* Warning! dropthrough */
+ case IMGFMT_YV12:
+ case IMGFMT_IYUV:
+ case IMGFMT_I420:
+ return( VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW
+ | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_OSD
+ | VFCAP_ACCEPT_STRIDE );
+ break;
+ }
+
+ return 0;
+}
+
+static void vo_pxa_copy_and_rotate( uint8_t *src, int stride, uint8_t *dst, int w, int h, int dst_stride )
+{
+ int i,j;
+ uint8_t *my_src, *my_dst;
+ Vo_Pxa_Pixel_Data8 *img_dst_pixel_data8;
+
+ /* Loop so writing consectuive data in rotated image */
+ /* This produces some pretty good assembler - better than the handcoded stuff in w100 */
+ for( j=0; j<w; j++ )
+ {
+ my_src = src + j + ( stride * (h - 1) );
+
+ img_dst_pixel_data8 = (Vo_Pxa_Pixel_Data8 *)dst;
+
+ /* Allow for src not multiple of 8 by running off the end a little. Should not matter */
+ for( i=0; i<((h+7)/8); i++ )
+ {
+ register Vo_Pxa_Pixel_Data8 build_pixels;
+
+ build_pixels.a = *my_src;
+ my_src -= stride;
+ build_pixels.a |= (*my_src<<8);
+ my_src -= stride;
+ build_pixels.a |= (*my_src<<16);
+ my_src -= stride;
+ build_pixels.a |= (*my_src<<24);
+ my_src -= stride;
+
+ build_pixels.b = *my_src;
+ my_src -= stride;
+ build_pixels.b |= (*my_src<<8);
+ my_src -= stride;
+ build_pixels.b |= (*my_src<<16);
+ my_src -= stride;
+ build_pixels.b |= (*my_src<<24);
+ my_src -= stride;
+
+ *img_dst_pixel_data8++ = build_pixels;
+ }
+
+ /* Allow source not as big as dest */
+ dst += dst_stride;
+ }
+}
+
+static void vo_pxa_draw_alpha( int x, int y, int w, int h, unsigned char *src,
+ unsigned char *srca, int stride )
+{
+ /* Dump data into our 15bit buffer with transparency */
+ pxa_priv_t *priv = &st_pxa_priv;
+ int i,j;
+ unsigned char *src_ptr = src;
+ unsigned char *a_ptr = srca;
+ unsigned short *out_ptr;
+
+ mp_msg(MSGT_VO, MSGL_V, "vo_pxa: vo_pxa_draw_alpha() w %d y %d w %d h %d\n", x, y, w, h );
+
+ /* We ignore the alpha channel, other than off or on */
+ for( i=0; i<h; i++ )
+ {
+ out_ptr = priv->osd_mem_base + x + ( priv->width * ( y + i ) );
+ src_ptr = src + ( i * stride );
+ a_ptr = srca + ( i * stride );
+
+ for( j=0; j<w; j++ )
+ {
+ /* The srca is a 0-255 transpaency level, where 0 is transparent.
+ * We only support transparent on or off
+ */
+ if( *a_ptr++ )
+ {
+ unsigned int grey;
+ /* The src is a greylevel from 0 - 255 */
+ /* We may as well use this value */
+ grey = *src_ptr++ >> 3;
+ *out_ptr++ = grey | (grey << 5) | (grey<<10);
+ }
+ else
+ {
+ *out_ptr++ = 0x8000;
+ src_ptr++;
+ }
+
+ }
+ }
+}
+
+static void vo_pxa_draw_alpha_with_rotate( int x, int y, int w, int h, unsigned char *src,
+ unsigned char *srca, int stride )
+{
+ /* Dump data into our 15bit buffer with transparency */
+ pxa_priv_t *priv = &st_pxa_priv;
+ int i,j;
+ unsigned char *src_ptr = src;
+ unsigned char *a_ptr = srca;
+ unsigned short *out_ptr;
+
+ mp_msg(MSGT_VO, MSGL_V, "vo_pxa: vo_pxa_draw_alpha_with_rotate() x %d y %d w %d h %d\n", x, y, w, h );
+
+ if( x >= 320 )
+ {
+ /* Off the screen */
+ return;
+ }
+
+ /* Limit to size of screen/memory */
+ if( ( w + x ) > 320 )
+ {
+ w = 320 - x;
+ }
+
+ if( y >= 240 )
{
- /* RGB/BGR Formats not supported yet */
- return 0;
- }
- else
+ /* Off the screen */
+ return;
+ }
+
+ /* Limit to size of screen/memory */
+ if( ( y + h ) > 240 )
+ {
+ h = 240 - y;
+ }
+
+
+ /* We ignore the alpha channel, other than off or on */
+ for( i=0; i<w; i++ )
{
- /* Planar YUV Formats */
- switch (format) {
- /* Warning! dropthrough */
- case IMGFMT_YV12:
- case IMGFMT_IYUV:
- case IMGFMT_I420:
- return( VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW
- | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_OSD
- | VFCAP_ACCEPT_STRIDE );
- break;
- }
+ out_ptr = priv->osd_mem_base + y + ( priv->width * ( x + i ) );
+ src_ptr = src + i + ( stride * (h - 1));
+ a_ptr = srca + i + ( stride * (h - 1));
+
+ for( j=0; j<h; j++ )
+ {
+ /* The srca is a 0-255 transpaency level, where 0 is transparent.
+ * We only support transparent on or off
+ */
+ if( *a_ptr )
+ {
+ unsigned int grey;
+ /* The src is a greylevel from 0 - 255 */
+ /* We may as well use this value */
+ grey = *src_ptr >> 3;
+ *out_ptr++ = grey | (grey << 5) | (grey<<10);
+ }
+ else
+ {
+ *out_ptr++ = 0x8000;
+ src_ptr;
+ }
+ a_ptr -= stride;
+ src_ptr -= stride;
+ }
}
+}
- return 0;
+static void vo_pxa_clear_osd( uint16_t *mem_base, int len )
+{
+ /* fill whole area with 0x8000 -> trsnaparent.
+ * assume area is word aligned, and a mulitple of 16 bytes in length
+ * However I tried I could not get the compiler to generate this.
+ * It always wanted to to do ldmia 4 words from stack followed by
+ * stmia 4 words. This seems odd!
+ */
+ __asm__ __volatile__ (
+ "mov r4, %0 \n\t"
+ "mov r5, %1, lsr #4 \n\t"
+ "subs r5, r5, #1\n\t"
+ "mov r0, #0x80000000 \n\t"
+ "orr r0, r0, #0x00008000 \n\t"
+ "mov r1, r0 \n\t"
+ "mov r2, r0 \n\t"
+ "mov r3, r0 \n\t"
+ "1: \n\t"
+ "subs r5, r5, #1\n\t"
+ "stmia r4!, {r0, r1, r2, r3} \n\t"
+ "bne 1b \n\t"
+ :
+ : "r"(mem_base), "r"(len)
+ : "memory", "r0", "r1", "r2", "r3", "r4", "r5", "cc" );
}
diff --git a/packages/mplayer/files/vo_pxa.h b/packages/mplayer/files/vo_pxa.h
index ee7825b76e..31cc1a7862 100644
--- a/packages/mplayer/files/vo_pxa.h
+++ b/packages/mplayer/files/vo_pxa.h
@@ -14,18 +14,38 @@
typedef struct pxa_priv_s {
uint8_t *fb_mem_base;
+ uint16_t *osd_mem_base;
+
int fd;
int base_fd;
+ int overlay_fd;
struct fb_var_screeninfo my_fb_var;
struct fb_fix_screeninfo my_fb_fix;
struct fb_var_screeninfo base_orig_fb_var;
+ struct fb_var_screeninfo osd_fb_var;
+ struct fb_fix_screeninfo osd_fb_fix;
int vm;
uint32_t format;
int src_width;
int src_height;
+ int width;
+ int height;
+ int rotate;
+ int osd_cleared;
} pxa_priv_t;
+typedef struct vo_pxa_pixel_data8 {
+ unsigned int a,b;
+} Vo_Pxa_Pixel_Data8;
+
#define UNUSED(v) ((void)(v))
/* Internal API */
static int vo_pxa_query_format( uint32_t format );
+static void vo_pxa_copy_and_rotate( uint8_t *src, int stride, uint8_t *dst, int w, int h, int dst_stride );
+static void vo_pxa_draw_alpha( int x, int y, int w, int h, unsigned char *src,
+ unsigned char *srca, int stride );
+static void vo_pxa_draw_alpha_with_rotate( int x, int y, int w, int h, unsigned char *src,
+ unsigned char *srca, int stride );
+
+static void vo_pxa_clear_osd( uint16_t *mem_base, int len );