[MPlayer-dev-eng] Mplayer -vo ps3

Kristian Jerpetjøn kristian.jerpetjoen at gmail.com
Tue Apr 7 01:50:01 CEST 2009


2009/4/5 Reimar Döffinger <Reimar.Doeffinger at gmx.de>:
> On Sat, Apr 04, 2009 at 10:26:33PM +0200, Kristian Jerpetjøn wrote:
>> >> +/* preinit - pre-initialization section
>> >> +*
>> >> +* Called before initializing video output driver for evaluating subopts.
>> >> +* Currently, we don't utilize any subopts (e.g. -vo ps3:subopt
>> >> +*/
>> >
>> > Comment is outdated, it should be doxygen compatible, but documenting functions
>> > that are part of the standard VO API is a bit pointless.
>>
>> Working on it throughout file
>>  This style is correct / ok ?
>>
>> /**
>> * Pointless test function
>> *
>> * @param testval test value for testfunct
>> * @return returns the test val
>> */
>> static int testfuct(int testval){
>>     return testval;
>> }
>
> Yes, looks right to me.
>
>> >> +            return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_SWSCALE | VFCAP_ACCEPT_STRIDE;
>> >
>> > not sure VFCAP_SWSCALE is right, at least you are not using libswscale...
>>
>> removed seems to work fine without
>
> I am just not sure if it should actually set the HWSCALE flag or what it is
> called. Sure, it is in software, but with recent GPUs OpenGL etc. is just
> software too, the point is that it does not use the "main CPU".
> But as said, I am not completely sure myself.

Unsure seems to work without from what i managed to read out of
vf_vo.c its fine

>
>> >> +    vo_doublebuffering = VO_TRUE;
>> >> +    vo_directrendering = VO_TRUE;
>> >
>> > These really should be left to the user and not overridden.
>>
>> removed now generates uglyness if -dr is disabled from user
>
> Yes, I think I started understanding what the code does, hopefully
> I can explain to you what goes wrong and why.

Solved Uglyness

>
>> I need a serious amount of help here..
>> changing MP_IMGFLAG_ALLOCATED to MP_IMGFLAG_DIRECT gives me green/tearing output
>
> Yeah, it looks like "a load of bugs which all together almost cancel each other out"

Think i solved this one as well

>> >> +        case VOCTRL_UPDATE_SCREENINFO: /* 32 */
>> >> +            mp_msg ( MSGT_VO, MSGL_WARN, "[vo_ps3] control: todo: handle UPDATE_SCREENINFO (%u)\n", request );
>> >> +            return VO_NOTIMPL;
>> >
>> > can't you just set xinerama_x, xinerama_y, vo_screenwidth and vo_screenheight?
>> > xinerama_? to 0, the others to the framebuffer dimension (not this is called
>> > before config but after preinit).
>>
>> need to understand implications of this with respect to current code
>> before attempting
>
> Basically it just preinitializes vo_dx/vo_dy/vo_dwidth etc. and sets up
> aspect stuff. Should just allow you to remove a lot of code but not change much.

Think i solved this one as well

>> >> +    vo_dx = vo_dy = 0;
>> >> +    vo_screenwidth=fbW - ( fbX*2 );
>> >> +    vo_screenheight=fbH - ( fbY*2 );
>> > [...]
>> >> +    //set aspect stuff
>> >> +    aspect_save_orig ( srcW, srcH );
>> >> +    aspect_save_screenres ( vo_screenwidth, vo_screenheight );
>> >> +    aspect_save_prescale ( dstW, dstH );
>> >> +
>> >> +    geometry ( &vo_dx, &vo_dy, &dstW, &dstH, vo_screenwidth, vo_screenheight );
>> >> +    aspect ( &dstW, &dstH, A_NOZOOM );
>> >> +    //center image -- this is wrong from mplayer's perspective - it should be
>> >> +    //                before the geometry & aspect call, but i don't want
>> >> +    //                mplayer to center the image because i can do it in
>> >> +    //                spu-medialib and we don't have to draw the extra black bars
>> >> +    vo_dx = ( fbW - ( 2 * fbX ) - dstW ) /2;
>> >> +    vo_dx = ( vo_dx+3 ) &~3;
>> >> +    vo_dy = ( fbH - ( 2 * fbY ) - dstH ) /2;
>> >
>> > Implement VOCTRL_UPDATE_SCREENINFO and you (hopefully) shouldn't need any of that.
>> > I have no idea WTF that comment is talking about.
>> > I guess the code was never tested with -geometry though...
>>
>> need some help implementing geometry correctly
>> however i did some cleanup here
>
> Well, the idea is: just implement VOCTRL_UPDATE_SCREENINFO and then display
> the video at vo_dx, vo_dy with size vo_dwidth, vo_dheight.
> To go fullscreen remember these and set the size from aspect(..., A_ZOOM) and
> vo_dx, vo_dy to create proper black borders.
> To return from fullscreen, restore the previous values.

New implementation

>
>> >> +    yuvscsc_set_srcW ( yuvcsc, srcW );
>> >> +    yuvscsc_set_srcH ( yuvcsc, srcH );
>> >> +    yuvscsc_set_dstW ( yuvcsc, dstW );
>> >> +    yuvscsc_set_dstH ( yuvcsc, dstH );
>> >> +    yuvscsc_set_offset ( yuvcsc, offset );
>> >> +    yuvscsc_set_maxwidth ( yuvcsc, maxW );
>> >
>> > Somebody has not yet found out about the thing called "struct" yet?!?
>>
>> Yes we have but unfortunately i have not bothered to make a new API
>> for this part of spu-medialib yet i should put it on the todo for 0.2
>
> It's not that bad, I just considered it a bit funny and coould not resist a comment.

Well now its gone..

>
>> It is one step closer now and i need help on a few parts regarding the
>> get_image and draw_image and general buffer handling
>>
>> Currently spu-medialib is configured with two planar images as input
>> divided amongst 6 buffers for yv12 etc...
>
> Two buffers is not going to great with -dr.
> For it to work well with MPEG-2 you need one to store the I-frame in,
> one to store the P-frame in, and then you need to draw the B-frame
> without break the I- or P-frame.

Solved buffers = 4 when doing DR..

>
>> +static uint32_t get_image ( mp_image_t * mpi )
>> +{
>> +    //TODO fix this whole mess somehow
>> +    get_image_count++;
>> +
>> +    if ( ( mpi->flags & MP_IMGFLAG_READABLE ) && ( mpi->type == MP_IMGTYPE_IPB\
>> +        || mpi->type == MP_IMGTYPE_IP ) )
>

removed

>
>> +    {
>> +        buf_plane_ptr[0] = parking_lot_y[parking_lot_page];
>> +        buf_plane_ptr[1] = parking_lot_u[parking_lot_page];
>> +        buf_plane_ptr[2] = parking_lot_v[parking_lot_page];
>> +        //mpi->flags |=MP_IMGFLAG_DIRECT;
>> +        //FIXME crash without understand what Bill was thinking here
>> +        mpi->flags |= MP_IMGFLAG_ALLOCATED;
>> +        parking_lot_page^=1;
>> +    }
>> +    else
>> +    {
>> +        buf_plane_ptr[0] = inbuf_y[page];
>> +        buf_plane_ptr[1] = inbuf_u[page];
>> +        buf_plane_ptr[2] = inbuf_v[page];
>> +        mpi->flags |= MP_IMGFLAG_DIRECT;
>> +    }
>
> If you do not set MP_IMGFLAG_DIRECT that means in draw_image you will
> still call memcpy, thus get_image is completely pointless then, so just
> returning VO_FALSE in that case should work the same.
> Next, you have only two buffers available. You need one in case you
> somehow get and mpi without MP_IMGFLAG_DIRECT in draw_image.
> Since you do not know when that will happen, you can not give that one
> out in get_image when MP_IMGFLAG_PRESERVE is set (i.e. the application
> expects to get the same content back somewhen).
> Now I am not sure if the second buffer is available or if that one might
> still be processed by the SPEs.
> Either way, that one buffer is not enought for MP_IMGTYPE_IP.
> So you end up with two possibilities:
> 1)
>  if (mpi->flags & MP_IMGFLAG_PRESERVE) return VO_FALSE;
>  if (mpi->type != MP_IMGTYPE_STATIC && mpi->type != MP_IMGTYPE_TEMP &&
>      (mpi->type != MP_IMGTYPE_NUMBERED || mpi->number))
>    return VO_FALSE;
>  fill planes etc. with the same buffer you would use in draw_image and
>  set MP_IMGFLAG_DIRECT, skip the memcpy in draw_image if that flag is set
>
> 2)
>  if (mpi->type != MP_IMGTYPE_STATIC && mpi->type != MP_IMGTYPE_TEMP &&
>      (mpi->type != MP_IMGTYPE_NUMBERED || mpi->number))
>    return VO_FALSE;
>  fill planes etc. with the second buffer and set MP_IMGFLAG_DIRECT, skip
>  the memcpy in draw_image if that flag is set.
>  If that flag is not set in memcpy, memcpy _always_ to the first buffer
>  in draw_image.
>
> Either way unless you provide at least 3 buffers (and ignore correctness a bit,
> which is okay since vo_xv does so already) or better 4 buffers, you will
> probably gain little from direct-rendering...
> btw. you should just call draw_slice to make the memcpy in draw_image,
> if they do not use the same code they are almost certainly wrong :-)

4 buffers seemed fine :)

>
>> +static void draw_osd ( void )
>> +{
>> +
>> +    vo_draw_text ( srcW, srcH, draw_alpha );
>> +}
>
> Hm, I somehow missed it, what does draw_alpha draw onto?
> Hopefully not onto something you gave out as PRESERVE/READABLE in get_image
> because then you'd just have broken a promise :-)

I will not solve OSD in this patch
However i have now solved a lot of issues and the overall quality is
greatly improved

optional and working -fs -double -dr -geometry i think

I have to make a new release of spu-medialib but it was a neccesary
step to make it work with 4 buffers that release is ready the day the
patch is approved

Cheers
-- 
Kristian Jerpetjøn
Tlf:        +4721694436
Mob      +4792822774
Email:  kristian.jerpetjoen at gmail.com
-------------- next part --------------
Index: Makefile
===================================================================
--- Makefile	(revision 29136)
+++ Makefile	(working copy)
@@ -618,6 +618,7 @@
 SRCS_MPLAYER-$(OSS)           += libao2/ao_oss.c
 SRCS_MPLAYER-$(PNG)           += libvo/vo_png.c
 SRCS_MPLAYER-$(PNM)           += libvo/vo_pnm.c
+SRCS_MPLAYER-$(PS3)           += libvo/vo_ps3.c
 SRCS_MPLAYER-$(PULSE)         += libao2/ao_pulse.c
 SRCS_MPLAYER-$(QUARTZ)        += libvo/vo_quartz.c
 SRCS_MPLAYER-$(S3FB)          += libvo/vo_s3fb.c
Index: libvo/video_out.c
===================================================================
--- libvo/video_out.c	(revision 29136)
+++ libvo/video_out.c	(working copy)
@@ -114,6 +114,7 @@
 extern vo_functions_t video_out_directx;
 extern vo_functions_t video_out_kva;
 extern vo_functions_t video_out_dxr2;
+extern vo_functions_t video_out_ps3;
 extern vo_functions_t video_out_dxr3;
 extern vo_functions_t video_out_ivtv;
 extern vo_functions_t video_out_v4l2;
@@ -201,6 +202,9 @@
         &video_out_fbdev,
         &video_out_fbdev2,
 #endif
+#ifdef CONFIG_PS3
+	&video_out_ps3,
+#endif
 #ifdef CONFIG_SVGALIB
         &video_out_svga,
 #endif
Index: libvo/vo_ps3.c
===================================================================
--- libvo/vo_ps3.c	(revision 0)
+++ libvo/vo_ps3.c	(revision 0)
@@ -0,0 +1,593 @@
+/*
+ * video driver for cell / BE Playstation3 framebuffer
+ * Copyright 2007 by Bill Garrett <wgarrett at sc.rr.com>
+ * Copyright 2009 by Kristian Jerpetjoen <kristian.jerpetjoen at gmail.com>
+ *
+ * This video out device uses the Cell Broadband Engine spe's to accelerate
+ * scaling and colorspace conversion to a Framebuffer
+ *
+ * This vo depends on spu-medialib which is a BSDv2 library
+ * https://sourceforge.net/projects/spu-medialib
+ *
+ * This file is part of MPlayer.
+ *
+ * MPlayer is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * MPlayer is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with MPlayer; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <libspe2.h>
+
+#include "config.h"
+#include "mplayer.h"
+#include "aspect.h"
+#include "mp_msg.h"
+#include "help_mp.h"
+#include "video_out.h"
+#include "video_out_internal.h"
+#include "subopt-helper.h"
+#include "fastmemcpy.h"
+#include "osd.h"
+#include "sub.h"
+
+#if HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+
+#include <spu-medialib/spu_control.h>
+#include <spu-medialib/yuv2argb_scaler.h>
+
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/kd.h>
+#include <linux/fb.h>
+#include <asm/ps3fb.h>
+
+#define NUM_BUFFERS 4
+#define MAXW 1920
+#define MAXH 1200
+
+#define FB_DEV "/dev/fb0"
+#define CONSOLE "/dev/tty"
+#define FALLBACK "/dev/console"
+
+static vo_info_t info =
+{
+    "PS3 framebuffer w/ spe offload courtesy of spu_medialib (https://sourceforge.net/projects/spu-medialib)",
+    "ps3",
+    "Bill Garrett <wgarrett at sc.rr.com>",
+    "Kristian Jerpetjoen <kristian.jerpetjoen at gmail.com"
+};
+
+LIBVO_EXTERN(ps3)
+
+static uint8_t *inbuf_y[NUM_BUFFERS], *inbuf_u[NUM_BUFFERS], *inbuf_v[NUM_BUFFERS];
+
+static uint32_t src_stride[3], src_p_siz[3], src_fmt, src_bpp;
+static uint32_t offsetW, offsetH;
+static uint32_t suggestedW, suggestedH;
+static uint8_t *buf_plane_ptr[3];
+static int fb,  console, fb_length;
+
+static int current_buf = 0;
+static int current_ip_buf = 0;
+static int num_buffers = 1;     // default
+static int visible_buf = -1; // no visible buffer
+
+static unsigned int yuvcsc_msg;
+static int wait_yuvcsc, yuvcsc_not_ready;
+
+static struct ps3fb_ioctl_res ps3_fb;
+
+static struct spu_medialib_conv_ctx_s conv_ctx;
+
+static yuvscaler2argb_t *yuvcsc;
+
+
+/**
+ * Initiates the ps3 framebuffer and disables the console
+ * @return -1 if unsuccessful
+ */
+static int init_framebuffer(void)
+{
+    int arg;
+    int res = 0;
+
+    console = open(CONSOLE, O_NONBLOCK);
+
+    if (console >= 0)
+        res = ioctl(console, KDGETMODE, &arg);
+
+    //This will only work if you are root
+    if (console < 0 || res < 0) {
+
+        if (console >= 0)
+            close(console);
+
+        console = open(FALLBACK, O_NONBLOCK);
+        res = ioctl(console, KDGETMODE, &arg);
+    }
+
+    if (console >= 0){
+        if (arg !=KD_GRAPHICS && ioctl(console, KDSETMODE, KD_GRAPHICS) < 0)
+            mp_msg(MSGT_VO,MSGL_INFO,"[vo_ps3] failed to disable console\n");
+    }
+    //we got this far now even if the console failed we continue
+    res = 0;
+
+    fb = open(FB_DEV, O_RDWR);
+
+    if (fb < 0) {
+
+        mp_msg(MSGT_VO, MSGL_INFO,
+               "[vo_ps3] init_framebuffer: failed to open fb\n" );
+        goto fail;
+    }
+
+    if (ioctl(fb, PS3FB_IOCTL_SCREENINFO, (unsigned long)&ps3_fb) < 0) {
+
+        mp_msg(MSGT_VO, MSGL_INFO,
+               "[vo_ps3] init_framebuffer: failed to get fb info\n" );
+        goto fail;
+    }
+
+    if (ioctl(fb, PS3FB_IOCTL_ON ) < 0) {
+
+        mp_msg(MSGT_VO, MSGL_INFO,
+               "[vo_ps3] init_framebuffer: failed to set manual swap control\n"
+              );
+        goto fail;
+    }
+
+    fb_length = ps3_fb.xres * ps3_fb.yres * 4;
+
+    //get the FB mmap
+    conv_ctx.Out = mmap(NULL, fb_length, PROT_WRITE, MAP_SHARED, fb, 0);
+    //actual widt of FB including offscreen
+    conv_ctx.maxwidth = ps3_fb.xres;
+
+    return 0;
+
+fail:
+    if (fb >= 0) {
+        ioctl(fb,PS3FB_IOCTL_OFF);
+        close(fb);
+    }
+
+    if (console >= 0) {
+        ioctl (console, KDSETMODE, KD_TEXT);
+        close(console);
+    }
+
+    return -1;
+}
+
+/**
+ * yuvcsc_check - check spu_yuv2argb_scaler process
+ * make sure it's not running
+ */
+static void yuvcsc_check(void)
+{
+
+    if (!wait_yuvcsc)
+        return;
+
+    yuvcsc_msg = yuvscsc_receive_message(yuvcsc);
+
+    while (yuvcsc_msg != RDY) {
+
+        yuvcsc_not_ready++;
+        mp_msg(MSGT_VO, MSGL_WARN,
+               "VO: [ps3] yuvcsc_check: ***yuvcsc not ready to run! :(\n" );
+
+        yuvcsc_msg = yuvscsc_receive_message(yuvcsc);
+    }
+
+    wait_yuvcsc = 0;
+}
+
+/**
+ * Puts the destination image onto the framebuffer
+ */
+static void yuvcsc_blit(void)
+{
+    wait_yuvcsc = 1;
+
+    conv_ctx.planes[0] = inbuf_y[current_buf];
+    conv_ctx.planes[1] = inbuf_u[current_buf];
+    conv_ctx.planes[2] = inbuf_v[current_buf];
+
+    yuvscsc_blit_yuvscaler2argb(yuvcsc, &conv_ctx);
+}
+
+/**
+ * Initiates the spu medialib spe vo accellerator
+ */
+static void init_spu_medialib(void)
+{
+    yuvcsc = yuvscsc_init_yuvscaler2argb();
+    //set wait flag
+    wait_yuvcsc = 1;
+    //wait for init to complete
+    yuvcsc_check();
+    mp_msg(MSGT_VO, MSGL_INFO,
+           "VO: [ps3] Initiated\n" );
+}
+
+/**
+ * Clears the target-framebuffer
+ */
+static void clear_framebuffer(void)
+{
+    //make sure spu medialib is not currently drawing on target framebuffer
+    yuvcsc_check();
+    //clear target framebuffer
+    memset(conv_ctx.Out, 0, fb_length);
+}
+
+/**
+ * Updates the screen settings
+ */
+static void update_screen(void)
+{
+    if (vo_fs){
+        aspect(&conv_ctx.dstW, &conv_ctx.dstH, A_ZOOM);
+        vo_dx = (vo_screenwidth - conv_ctx.dstW) / 2;
+        vo_dy = (vo_screenheight - conv_ctx.dstH) / 2;
+    } else {
+        conv_ctx.dstW = suggestedW;
+        conv_ctx.dstH = suggestedH;
+        vo_dx = offsetW;
+        vo_dy = offsetH;
+    }
+
+    //round down to nearest 4x4 users should consider restrictions
+    aspect_fit(&conv_ctx.dstW, &conv_ctx.dstH, conv_ctx.dstW & (~0x3),
+               conv_ctx.dstH & (~0x3));
+
+    //round offset up to nearest 4x4 users should consider restrictions
+    vo_dx=(vo_dx + 3) & (~0x3);
+    vo_dy=(vo_dy + 3) & (~0x3);
+    conv_ctx.offset=vo_dx + (vo_dy*ps3_fb.xres);
+}
+
+
+/**
+ * Toggles fullscreen off and on
+ */
+static void toggle_fullscreen(void)
+{
+    //toggle fullscreen flag
+    vo_fs = !vo_fs;
+    //check that nothings currently working on the framebufer
+    yuvcsc_check();
+    //clear the framebuffer in case vo_dy/vo_dx was in the outer rims
+    clear_framebuffer();
+    //update_screen
+    update_screen();
+}
+
+//buildtin documented elsewhere
+static int query_format(uint32_t format)
+{
+
+    switch(format)
+    {
+        case IMGFMT_I420:       //Planar I420 0x30323449
+        case IMGFMT_YV12:       //Planar YV12 0x32315659
+        case IMGFMT_IYUV:       //Planar IYUV 0x56555949
+            return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW |
+                   VFCAP_ACCEPT_STRIDE ;
+        default:
+            return VO_FALSE;    //not supporting anything else yet
+    }
+}
+
+//buildtin documented elsewhere
+static void draw_osd(void){
+//TODO make me draw osd
+}
+
+//buildtin documented elsewhere
+static int config(uint32_t width, uint32_t height, uint32_t d_width,
+    uint32_t d_height, uint32_t flags, char *title, uint32_t format)
+{
+    int i;
+
+    conv_ctx.srcW = width;
+    conv_ctx.srcH = height;
+
+    offsetW=vo_dx;
+    offsetH=vo_dy;
+
+    suggestedW = d_width;
+    suggestedH = d_height;
+
+    switch(format)
+    {
+        case IMGFMT_I420:   //Planar I420 0x30323449
+        case IMGFMT_YV12:   //Planar YV12 0x32315659
+        case IMGFMT_IYUV:   //Planar IYUV 0x56555949
+            //TODO add more sanity to strides inside spu-medialib
+            src_stride[0] = conv_ctx.srcW;
+            src_stride[1] = src_stride[2] = src_stride[0]/2;
+            src_p_siz[0] = conv_ctx.srcW * conv_ctx.srcH;
+            src_p_siz[1] = src_p_siz[2] = (conv_ctx.srcW/2) * (conv_ctx.srcH/2);
+            src_bpp = 12;
+            break;
+        default:
+            mp_msg(MSGT_VO, MSGL_FATAL,
+                   "[vo_ps3] config: Unsupported format: %i\n", format );
+            return 1;
+    }
+
+    src_fmt=format;
+
+    if (vo_doublebuffering)
+        num_buffers=2;
+
+    if (vo_directrendering)
+        num_buffers=NUM_BUFFERS;
+
+    for (i = 0; i < num_buffers; i++) {
+        inbuf_y[i] = memalign(128, src_p_siz[0] * 2);
+        inbuf_u[i] = memalign(128, src_p_siz[1] * 2);
+        inbuf_v[i] = memalign(128, src_p_siz[2] * 2);
+    }
+    //make sure we have black borders
+    clear_framebuffer();
+    //get the right screen
+    update_screen();
+    //initiate accelerator
+    init_spu_medialib();
+
+    return 0;
+}
+
+//buildtin documented elsewhere
+static int draw_slice(uint8_t *src[], int stride[], int w, int h, int x, int y)
+{
+    int i;
+    int slice_siz[3], slice_p_w[3], slice_p_h[3], offset[3];
+
+    buf_plane_ptr[0] = inbuf_y[current_buf];
+    buf_plane_ptr[1] = inbuf_u[current_buf];
+    buf_plane_ptr[2] = inbuf_v[current_buf];
+
+    slice_siz[0] = stride[0] * h;
+    slice_siz[1] = stride[1] * h/2;
+    slice_siz[2] = stride[2] * h/2;
+
+    slice_p_w[0] = w;
+    slice_p_w[1] = slice_p_w[2] = w/2;
+
+    slice_p_h[0] = h;
+    slice_p_h[1] = slice_p_h[2] = h/2;
+
+    offset[0] = y * src_stride[0] + x;
+    offset[1] = y/2 * src_stride[1] + x/2;
+    offset[2] = y/2 * src_stride[2] + x/2;
+
+    for ( i=0; i<3; i++ ) {
+        memcpy_pic(buf_plane_ptr[i] + offset[i], src[i], slice_p_w[i],
+                   slice_p_h[i], src_stride[i], stride[i]);
+    }
+    return 0;
+}
+
+//buildtin documented elsewhere
+static uint32_t draw_image(mp_image_t *mpi)
+{
+    if (mpi->flags & MP_IMGFLAG_DIRECT) {
+        //direct rendering
+        current_buf = (int) (mpi->priv);// hack! seems to work on spu-medialib?
+        return VO_TRUE;
+    }
+
+    if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
+        return VO_TRUE;         // done
+
+    if (mpi->flags & MP_IMGFLAG_PLANAR) {
+        draw_slice(mpi->planes, mpi->stride, mpi->w, mpi->h, 0, 0);
+        return VO_TRUE;
+    }
+
+    return VO_FALSE; // not (yet) supported
+
+}
+
+//buildtin documented elsewhere
+static uint32_t get_image(mp_image_t * mpi)
+{
+    int buf = current_buf;
+
+    if (mpi->type == MP_IMGTYPE_STATIC && num_buffers > 1)
+        return VO_FALSE;        // it is not static
+
+    if (mpi->imgfmt != src_fmt)
+        return VO_FALSE;        // needs conversion :(
+
+    if (mpi->flags & MP_IMGFLAG_READABLE &&
+        (mpi->type == MP_IMGTYPE_IPB || mpi->type == MP_IMGTYPE_IP))
+    {
+        // reference (I/P) frame of IP or IPB:
+        if (num_buffers < 2)
+            return VO_FALSE;    // not enough
+
+        current_ip_buf ^= 1;
+        // for IPB with 2 buffers we can DR only one of the 2 P frames:
+        if (mpi->type == MP_IMGTYPE_IPB && num_buffers < 3
+            && current_ip_buf)
+            return VO_FALSE;
+
+        buf = current_ip_buf;
+
+        if (mpi->type == MP_IMGTYPE_IPB)
+            ++buf;              // preserve space for B
+    }
+
+    if (mpi->flags & (MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_ACCEPT_WIDTH))
+    {
+        current_buf = buf;
+        mpi->planes[0] = inbuf_y[current_buf];
+        mpi->stride[0] = src_stride[0];
+        mpi->width = mpi->stride[0] / (mpi->bpp / 8);
+
+        if (mpi->flags & MP_IMGFLAG_PLANAR) {
+            if (mpi->flags & MP_IMGFLAG_SWAPPED) {
+                // I420
+                mpi->planes[1] = inbuf_v[current_buf];
+                mpi->planes[2] = inbuf_u[current_buf];
+                mpi->stride[1] = src_stride[1];
+                mpi->stride[2] = src_stride[1];
+            } else
+            {
+                // YV12
+                mpi->planes[1] = inbuf_u[current_buf];
+                mpi->planes[2] = inbuf_v[current_buf];
+                mpi->stride[1] = src_stride[1];
+                mpi->stride[2] = src_stride[1];
+            }
+        }
+
+        if (current_buf == visible_buf)
+            yuvcsc_check();
+
+        mpi->flags |= MP_IMGFLAG_DIRECT;
+        mpi->priv = (void *) current_buf;
+        return VO_TRUE;
+    }
+    return VO_FALSE;
+           return 0;
+}
+
+//buildtin documented elsewhere
+static int draw_frame(uint8_t *src[])
+{
+    //do nothing
+    return 0;
+}
+
+//buildtin documented elsewhere
+static void flip_page(void)
+{
+    int frame = 0;
+    int crt = 0;
+
+    //make sure last frame is done
+    yuvcsc_check();
+    //flip output to monitor
+    ioctl(fb, PS3FB_IOCTL_FSEL, (unsigned long)&frame);
+     //make sure flip is complete
+    ioctl(fb, FBIO_WAITFORVSYNC, (unsigned long)&crt);
+    //run process next frame
+    yuvcsc_blit();
+    //set buffer as visible
+    visible_buf = current_buf;
+
+    if (num_buffers > 1) {
+        current_buf = vo_directrendering ? 0 : ((current_buf + 1) %num_buffers);
+    } else {
+        //make sure spu-medialib is done with buffer
+        yuvcsc_check();
+    }
+}
+
+//buildtin documented elsewhere
+static void check_events(void)
+{
+    //no events to check
+}
+
+//buildtin documented elsewhere
+static void uninit(void)
+{
+
+    int i;
+    // Cleanup spu-medialib
+    yuvcsc_check();
+
+    yuvscsc_destroy(yuvcsc);
+
+    //Cleanup FrameBuffer and re-enable console */
+    ioctl(fb, PS3FB_IOCTL_OFF);
+
+    ioctl(console, KDSETMODE, KD_TEXT);
+
+    if (console >= 0)
+        close(console);
+
+    if (console >= 0)
+        close(fb);
+
+    for (i = 0; i < num_buffers; i++) {
+        free(inbuf_y[i]);
+        free(inbuf_u[i]);
+        free(inbuf_v[i]);
+    }
+
+    mp_msg(MSGT_VO, MSGL_INFO,
+           "VO: [ps3] Closed and re-enabled console.\n" );
+}
+
+//buildtin documented elsewhere
+static int preinit(const char *arg)
+{
+    /* init PS3 FrameBuffer */
+    if (init_framebuffer() < 0)
+        return -1;
+    return 0;
+}
+
+//buildtin documented elsewhere
+static int control(uint32_t request, void *data, ...)
+{
+    switch(request)
+    {
+        case VOCTRL_QUERY_FORMAT:
+            return query_format (*(uint32_t*)data);
+
+        case VOCTRL_FULLSCREEN:
+            toggle_fullscreen();
+            return 0;
+
+        case VOCTRL_PAUSE:
+            return 0;
+
+        case VOCTRL_RESUME:
+            return 0;
+
+        case VOCTRL_GET_IMAGE:
+            return get_image(data);
+
+        case VOCTRL_DRAW_IMAGE:
+            return draw_image(data);
+
+        case VOCTRL_UPDATE_SCREENINFO:
+            vo_screenwidth = (int)(ps3_fb.xres - (ps3_fb.xoff * 2));
+            vo_screenheight = (int)(ps3_fb.yres - (ps3_fb.yoff * 2));
+            xinerama_x=xinerama_y=0;
+            aspect_save_screenres(vo_screenwidth, vo_screenheight);
+            return VO_TRUE;
+
+        default:
+            return VO_NOTIMPL;
+    }
+}
Index: configure
===================================================================
--- configure	(revision 29136)
+++ configure	(working copy)
@@ -391,6 +391,7 @@
   --enable-xshape          enable XShape support [autodetect]
   --disable-xss            disable screensaver support via xss [autodetect]
   --enable-fbdev           enable FBDev video output [autodetect]
+  --enable-ps3             enable FBDev video output SPU optimized for PS3 [autodetect]
   --enable-mlib            enable mediaLib video output (Solaris) [disable]
   --enable-3dfx            enable obsolete /dev/3dfx video output [disable]
   --enable-tdfxfb          enable tdfxfb video output [disable]
@@ -577,6 +578,7 @@
 _svga=auto
 _vesa=auto
 _fbdev=auto
+_ps3=auto
 _dvb=auto
 _dvbhead=auto
 _dxr2=auto
@@ -931,6 +933,8 @@
   --disable-vesa)	_vesa=no	;;
   --enable-fbdev)	_fbdev=yes	;;
   --disable-fbdev)	_fbdev=no	;;
+  --enable-ps3)        _ps3=yes        ;;
+  --disable-ps3)       _ps3=no         ;;
   --enable-dvb)		_dvb=yes	;;
   --disable-dvb)        _dvb=no		;;
   --enable-dvbhead)	_dvbhead=yes	;;
@@ -4758,6 +4762,26 @@
 echores "$_fbdev"
 
 
+echocheck "PS3"
+if test "$_ps3" = auto ; then
+  cat > $TMPC << EOF
+#include <libspe2.h>
+#include <spu-medialib/spu_control.h>
+#include <spu-medialib/yuv2argb_scaler.h>
+int main(void) { return 0; }
+EOF
+  _ps3=no
+  cc_check -lspu-medialib -lspe2 && _ps3=yes
+fi
+if test "$_ps3" = yes; then
+  def_ps3='#define CONFIG_PS3 1'
+  libs_mplayer="$libs_mplayer -lspu-medialib -lspe2"
+  _vomodules="ps3 $_vomodules"
+else
+  def_ps3='#undef CONFIG_PS3'
+  _novomodules="ps3 $_novomodules"
+fi
+echores "$_ps3"
 
 echocheck "DVB"
 if test "$_dvb" = auto ; then
@@ -8257,6 +8281,7 @@
 PNG = $_png
 PNM = $_pnm
 PRIORITY = $_priority
+PS3 = $_ps3
 PULSE = $_pulse
 PVR = $_pvr
 QTX_CODECS = $_qtx
@@ -8730,6 +8755,7 @@
 $def_mng
 $def_png
 $def_pnm
+$def_ps3
 $def_quartz
 $def_s3fb
 $def_sdl


More information about the MPlayer-dev-eng mailing list